Skip to content

Report when a build runs against drifted submodules - #668

Merged
hannesa2 merged 1 commit into
gitx:masterfrom
goneng:warn-on-submodule-drift
Sep 18, 2026
Merged

hannesa2 merged 1 commit into
gitx:masterfrom
goneng:warn-on-submodule-drift

Conversation

@goneng

@goneng goneng commented Sep 18, 2026 •

Copy link
Copy Markdown
Collaborator

Which commit each submodule sits on decides what gets compiled, but git status reports a drifted submodule and a merely dirty one the same way, so building against the wrong revision is easy to miss.

  • Add a git-submodule-check target to report any submodule that is not at the revision this tree records. Locally it carries on, since parking one on a commit of your own is a normal thing to be doing mid-change.
  • Run it before and after everything that compiles (build, unit-test, ui-test, all-tests, archive), keeping the status the build itself returned. make help and map pick the new target up on their own.
  • Fail the build under GitHub Actions instead, and raise it as an error annotation.
  • Look recursively, since libgit2 sits under objective-git and it is that pin which leaves a stale framework behind.
  • Have the help target accept the names the map target already accepts, so one carrying a digit or an underscore is listed.

Locally: warn, and say it twice

A warning printed once, before a build, is never read. This workflow's last run came to 242,188 log lines, of which the step it would print in was 96,970, and the UI collapses every step by default. The failing build is the moment someone actually reads output, so the report is repeated at the end:

make build
...
warning: submodules are not at the revisions this tree wants:
  External/MGScopeBar is at f59ffc66
  External/objective-git/External/libgit2 is at 1affb8b1
run `make git-submodule-sync` to check them out
make: *** [build] Error 1

The build's own exit status is preserved, so a failure still fails and a success still succeeds.

On CI: fail

Warning is the wrong response there. Nothing on a runner parks a submodule deliberately, actions/checkout is the only thing that puts submodules in place, and run make git-submodule-sync is advice nobody can act on mid-run. If this ever fires it means the checkout produced the wrong tree, and every artifact from that run should be distrusted rather than the run re-tried. So under GITHUB_ACTIONS it fails instead, with an error annotation that the run summary carries whatever the log does:

::error title=Submodule drift::the checkout left submodules that are not at the recorded revisions%0A...

That lands on the prerequisite, before xcodebuild starts, so nothing is built against a tree we do not trust.

This should never fire today, and that is the point. Both checkouts that precede a make use submodules: recursive; script/update_libgit2 only runs cmake and copies libgit2.a, never checking anything out; and there is no cache action in the workflow. It is insurance for the day one of those three changes.

Test plan

  • Clean tree: silent, exit 0, in both contexts, and confirmed silent on this PR's own CI runs.
  • A top-level submodule and a nested one checked out away from their pins: locally the warning above, exit 0, before and after the build. The nested line proves the recursion reaches libgit2, which is the pin that leaves stale headers behind.
  • The same drift with GITHUB_ACTIONS=true: the error annotation on stdout, which is the stream the runner parses, the readable form on stderr, and a non-zero exit. make unit-test then stops at the prerequisite with xcodebuild never invoked, while the same command without GITHUB_ACTIONS still runs the tests.
  • Exit status preserved across the tail call, checked by standing in a passing and a failing build: make build XCODEBUILD=true exits 0, make build XCODEBUILD=false prints the warning last and still reports Error 1.

@goneng
goneng marked this pull request as ready for review September 18, 2026 07:49
@goneng
goneng force-pushed the warn-on-submodule-drift branch 3 times, most recently from 788dbc3 to 7fc80e6 Compare September 18, 2026 09:30
@goneng goneng changed the title Warn when a build runs against drifted submodules Report when a build runs against drifted submodules Sep 18, 2026
Which commit each submodule sits on decides what gets compiled, but
git status reports a drifted submodule and a merely dirty one the same
way, so building against the wrong revision is easy to miss.

* Add a git-submodule-check target to report any submodule that is not
  at the revision this tree records, recursively, since libgit2 sits
  under objective-git and its pin leaves a stale framework behind.
* Warn and carry on locally, where parking a submodule on a commit of
  your own is a normal thing to be doing, and say it again once the
  build ends, keeping the status the build returned, since by then the
  first report is buried under tens of thousands of lines.
* Fail under GitHub Actions instead, where the checkout is the only
  thing that places submodules and drift is a defect rather than a
  choice, and raise it as an annotation the run summary shows.
* Have the help target accept the names the map target already accepts,
  so one carrying a digit or an underscore is listed.
@goneng
goneng force-pushed the warn-on-submodule-drift branch from 7fc80e6 to f6710ec Compare September 18, 2026 09:59
@hannesa2
hannesa2 merged commit 35d0316 into gitx:master Sep 18, 2026
3 checks passed
@goneng
goneng deleted the warn-on-submodule-drift branch September 18, 2026 22:20
@hannesa2

Copy link
Copy Markdown
Contributor

Yes, it works in real live 👍
image

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants