Skip to content

Add pre-commit hook to verify static analysis passes & format is correct#11941

Open
camsim99 wants to merge 37 commits into
flutter:mainfrom
camsim99:cos_precommit
Open

Add pre-commit hook to verify static analysis passes & format is correct#11941
camsim99 wants to merge 37 commits into
flutter:mainfrom
camsim99:cos_precommit

Conversation

@camsim99

@camsim99 camsim99 commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Adds a pre-commit hook that you can install to verify that dart analyze --fatal-infos and the package format are correct when you make a call to git commit. Intended to ensure agents commit code that meets are quality standards.

Also makes the following updates the plugins tool:

  • Adds --run-on-staged-packages flag 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)
  • Adds optimization to the format tool to avoid invoking native tool chains to format when non-native files are modified

Miscellaneous notes:

Pre-Review Checklist

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-assist bot 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

  1. 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

@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jun 18, 2026
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 22, 2026
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jun 22, 2026
@camsim99 camsim99 added CICD Run CI/CD and removed CICD Run CI/CD labels Jun 22, 2026
@camsim99 camsim99 marked this pull request as ready for review June 22, 2026 17:58

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread script/githooks/bin/install_hooks.dart
Comment thread script/githooks/lib/src/pre_commit_command.dart Outdated
Comment thread script/githooks/lib/src/pre_commit_command.dart Outdated
Comment thread script/githooks/lib/src/pre_commit_command.dart Outdated
Comment thread script/githooks/pubspec.yaml
Comment thread script/githooks/test/pre_commit_command_test.dart
Comment thread script/githooks/test/pre_commit_command_test.dart
Comment thread script/githooks/test/pre_commit_command_test.dart
Comment thread script/githooks/test/pre_commit_command_test.dart
@camsim99 camsim99 removed the CICD Run CI/CD label Jun 22, 2026
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 26, 2026
print(diffResult.stderr);
}
// If we cannot determine the diff, abort pre-commit check.
return false;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@camsim99 camsim99 requested a review from reidbaker June 26, 2026 19:27
@camsim99 camsim99 added the CICD Run CI/CD label Jun 26, 2026

@reidbaker reidbaker left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice change to only downloading if we need to format those languages.

Comment thread script/tool/lib/src/common/package_looping_command.dart Outdated
Comment thread script/tool/lib/src/common/package_looping_command.dart Outdated
Comment thread script/tool/lib/src/format_command.dart Outdated

return files
.where((File file) {
if (useDiff) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it still works as expected! Added tests.

Comment thread script/tool/test/common/package_command_test.dart
Comment thread script/githooks/lib/src/pre_commit_command.dart Outdated
Comment thread script/githooks/lib/src/pre_commit_command.dart Outdated
/// 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 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@reidbaker reidbaker Jun 30, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread script/githooks/lib/src/pre_commit_command.dart Outdated
if (analyzeResult.stderr.toString().isNotEmpty) {
print(analyzeResult.stderr);
}
print('Static analysis failed. Please fix the errors listed above.');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. Modified the failure messages to point to the command to run to find/fix the issues.

@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 29, 2026
@camsim99 camsim99 added the CICD Run CI/CD label Jun 29, 2026
@camsim99 camsim99 requested a review from reidbaker June 29, 2026 22:24

@reidbaker reidbaker left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@camsim99

Copy link
Copy Markdown
Contributor Author

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 time git commit for empty commit:

With optimization Without
real 1.756s 6.005s
user 0.877s 5.925s
sys 0.563s 1.236s

@reidbaker

Copy link
Copy Markdown
Contributor

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 time git commit for empty commit:

With optimization Without
real 1.756s 6.005s
user 0.877s 5.925s
sys 0.563s 1.236s

That is enough justification. Lets document that and move on.

@reidbaker

reidbaker commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Would you be willing to file a bug to have me/us investigate why the performance gap was so large.

@github-actions github-actions Bot removed the CICD Run CI/CD label Jul 1, 2026
@camsim99 camsim99 added CICD Run CI/CD autosubmit Merge PR when tree becomes green via auto submit App labels Jul 1, 2026
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jul 1, 2026
@auto-submit

auto-submit Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants