feat: add API boundary runner, relocate fixtures, and configure CI check#183
Conversation
…ownstream-consumers skill
…-boundary-runner-2026-07-16
|
Warning Gemini encountered an error creating the review. You can try again by commenting |
|
/Gemini review |
There was a problem hiding this comment.
Code Review
This pull request restructures the example fixtures by moving them under example/skills/ and updates the configuration, documentation, and tests accordingly. It also introduces a new api_boundary_runner tool to validate the public API boundary and adds guidelines for performing diagnostic API migrations. Feedback on the new runner suggests implementing a more robust path resolution mechanism to handle compiled snapshots and replacing direct exit(1) calls with exitCode = 1 and returns to allow proper flushing of output streams.
| final String scriptDir = p.dirname(Platform.script.toFilePath()); | ||
| final String validSkillPath = p.normalize( | ||
| p.absolute(p.join(scriptDir, '..', '..', 'skills', 'valid')), | ||
| ); | ||
| final String invalidSkillPath = p.normalize( | ||
| p.absolute(p.join(scriptDir, '..', '..', 'skills', 'invalid')), | ||
| ); |
There was a problem hiding this comment.
Relying solely on Platform.script.toFilePath() can fail if the script is executed as a compiled snapshot (e.g., via dart run under certain configurations) or if the scheme is not file. Resolving the path with fallback options based on the current working directory makes the runner much more robust across different execution environments.
String findPath(String relativeSuffix) {
final pathsToTry = [
p.join('example', 'skills', relativeSuffix),
p.join('..', 'skills', relativeSuffix),
if (Platform.script.scheme == 'file')
p.join(p.dirname(Platform.script.toFilePath()), '..', '..', 'skills', relativeSuffix),
];
for (final path in pathsToTry) {
final absolutePath = p.absolute(path);
if (Directory(absolutePath).existsSync()) {
return p.normalize(absolutePath);
}
}
throw StateError('Could not locate skills/$relativeSuffix directory.');
}
final String validSkillPath = findPath('valid');
final String invalidSkillPath = findPath('invalid');| if (!validResult) { | ||
| print('Error: Valid skill fixture failed validation!'); | ||
| exit(1); | ||
| } |
There was a problem hiding this comment.
Calling exit(1) immediately terminates the Dart VM, which can truncate pending asynchronous operations or stdout/stderr streams. Setting exitCode = 1 and returning from main allows the VM to flush all event queues and terminate cleanly.
| if (!validResult) { | |
| print('Error: Valid skill fixture failed validation!'); | |
| exit(1); | |
| } | |
| if (!validResult) { | |
| print('Error: Valid skill fixture failed validation!'); | |
| exitCode = 1; | |
| return; | |
| } |
| if (invalidResult) { | ||
| print('Error: Invalid skill fixture unexpectedly passed validation!'); | ||
| exit(1); | ||
| } |
There was a problem hiding this comment.
Setting exitCode = 1 and returning from main is preferred over calling exit(1) directly, as it allows the Dart VM to flush pending asynchronous stdout/stderr writes before terminating.
| if (invalidResult) { | |
| print('Error: Invalid skill fixture unexpectedly passed validation!'); | |
| exit(1); | |
| } | |
| if (invalidResult) { | |
| print('Error: Invalid skill fixture unexpectedly passed validation!'); | |
| exitCode = 1; | |
| return; | |
| } |
…ution and VM clean exit rules
This work is to prevent mistakes that caused the need for #182 Ensuring that the public api boundary is tested in a way that prevents impossible to use apis.
2 prongs to the fix, one is in the skill used to validate breaking changed against known downstream users. Second is an explicit test for the api boundary in a examples folder.
For good organization I also moved the existing valid and invalid skills into their own directory.
Agent authored description below
Introduces an automated API boundary verification test runner to programmatically validate the linter's public contract under external packaging constraints (preventing any future regressions where unexported classes or parameters slip into the public interface).
example/api_boundary_runnerwhich imports strictlypackage:dart_skills_lint/dart_skills_lint.dart(avoiding internal imports) and executes verification logic.example/skills/validandexample/skills/invalid, updating all references across READMEs, tests, and configurations..github/workflows/dart_skills_lint_workflow.yamlto build, analyze, format, and run the example code runner across GHA matrix OS platforms.check-downstream-consumers/SKILL.md] to mandate diagnostic API migration checks during PR reviews.