Add pre-commit hook to verify static analysis passes & format is correct#11941
Add pre-commit hook to verify static analysis passes & format is correct#11941camsim99 wants to merge 37 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a new githooks Dart package to automate pre-commit checks, including formatting and static analysis, for staged files. The package includes an installation script, a pre-commit command runner, and associated unit tests. Review feedback highlights a potential infinite loop on Windows when locating the .git directory, raw ANSI escape sequences being printed without verifying terminal support, the use of loose any version constraints in pubspec.yaml, and redundant dead code in the test mocks.
| print(diffResult.stderr); | ||
| } | ||
| // If we cannot determine the diff, abort pre-commit check. | ||
| return false; |
There was a problem hiding this comment.
I made this decision because I assume there must be a Git setup issue if this happens, but open to pushback if we think this could actually block valid commits.
reidbaker
left a comment
There was a problem hiding this comment.
Does the pr description still match what you have up for review?
| Future<void> _formatJava(Iterable<String> files) async { | ||
| final Iterable<String> javaFiles = _getPathsWithExtensions(files, <String>{'.java'}); | ||
| if (javaFiles.isNotEmpty) { | ||
| final String formatterPath = await _downloadJavaFormatterIfNecessary(); |
There was a problem hiding this comment.
Nice change to only downloading if we need to format those languages.
|
|
||
| return files | ||
| .where((File file) { | ||
| if (useDiff) { |
There was a problem hiding this comment.
quick double check that the conditions that are checked below like handFormattedExtension will still run as expected both when useDiff is true and false.
So as an example a hand formatted file that is edited will still be excluded
and a build/ file that is not edited will when useDiff is false will still be excluded.
There was a problem hiding this comment.
Yes it still works as expected! Added tests.
| /// Returns true if at least one staged file is located within a package directory | ||
| /// (under packages/ or third_party/packages/), false if there are none, or null | ||
| /// if the git command fails. | ||
| Future<bool?> _hasStagedPackages(Directory repoRoot) async { |
There was a problem hiding this comment.
I think this logic was moved to the format/package commands. If so consider removing it. If we add logic here to filter then it could be confusing if it diverges from what is in the other tooling.
There was a problem hiding this comment.
The optimization was moved to the format/package commands but this is an additional optimization--when there are no relevant changes to have this hook check, let's skip calling into the plugins tool altogether. Calling into at all adds steps like checking package dependencies that we can skip if we aren't going to end up running the checks at all.
I don't see the risk of divergence being high, but if you're concerned we can remove it! I don't feel super strongly since we don't necessarily expect high human usage.
There was a problem hiding this comment.
Ok in that case can you give me the situation and performance delta of this optimization? My understanding having not run it is that we are still spinning up dart and we are still filtering using the same git commands so I don't see how it could improve efficiency. Is there a step I am not seeing?
The most convincing evidence would be a common situation, maybe a merge conflict, and showing the difference is a multiple in speed.
I guess my larger concern is that the filtering should happen in one place unless we get a really large performance or ux gain and on my mind once we are in dart land we should be able to make the performance the same.
| if (analyzeResult.stderr.toString().isNotEmpty) { | ||
| print(analyzeResult.stderr); | ||
| } | ||
| print('Static analysis failed. Please fix the errors listed above.'); |
There was a problem hiding this comment.
Preference question for you. My gut says that all of our presubmits should fail, give the work around (--no-verify) then give the command to reproduce the failing condition. But it should not print everything that needs to be fixed. My logic here is that I don't want any complexity or logic in the presubmit that I can put someplace else and also if we make it a design expectation that the logic needs to live someplace else then that is more likely to happen.
There was a problem hiding this comment.
I agree. Modified the failure messages to point to the command to run to find/fix the issues.
reidbaker
left a comment
There was a problem hiding this comment.
Let's measure the performance gain of the filter code in the pre submit command. If there is a large gain then this looks good. If not then let's remove that logic.
Quick test of with
|
That is enough justification. Lets document that and move on. |
|
Would you be willing to file a bug to have me/us investigate why the performance gap was so large. |
|
autosubmit label was removed for flutter/packages/11941, because - The status or check suite Dashboard Checks has failed. Please fix the issues identified (or deflake) before re-applying this label. |
Adds a pre-commit hook that you can install to verify that
dart analyze --fatal-infosand the package format are correct when you make a call togit commit. Intended to ensure agents commit code that meets are quality standards.Also makes the following updates the plugins tool:
--run-on-staged-packagesflag that allows the command to only run on files with staged changes. This flag cannot be run with any other flags that filter packages where the command runs (like--run-on-dirty-packages)Miscellaneous notes:
script/githooks/bin/install_hooks.dartis the script to install the hook that devs would need to run to use it.githooksdirectory like https://github.com/flutter/flutter/tree/master/engine/src/flutter/tools/githooks to make it easier for folks to add new hooksPre-Review Checklist
[shared_preferences]///).If you need help, consider asking for advice on the #hackers-new channel on Discord.
Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the
gemini-code-assistbot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.Footnotes
Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. ↩ ↩2