Skip to content

Comments

cache-homebrew-prefix: restore git state after prefix cache restore#799

Merged
dduugg merged 3 commits intomainfrom
fix/cache-restore-git-state
Feb 21, 2026
Merged

cache-homebrew-prefix: restore git state after prefix cache restore#799
dduugg merged 3 commits intomainfrom
fix/cache-restore-git-state

Conversation

@dduugg
Copy link
Member

@dduugg dduugg commented Feb 21, 2026

Summary

The cache-homebrew-prefix action caches the entire Homebrew prefix directory (including .git) via actions/cache/restore. When the cached snapshot was saved during a previous CI run on a different branch (typically main), restoring it silently resets the Homebrew repository to that branch — discarding the current checkout (e.g. a PR's merge commit).

This causes two problems for consumers:

  1. Test-bot runs the wrong code — it tests the cached main snapshot instead of the PR.
  2. New files from the PR appear as untracked modifications, causing brew doctor (via brew test-bot --only-setup) to fail with:
    Error: You have uncommitted modifications to Homebrew/brew.
    

Fix

Save the git HEAD sha before the cache restore and re-checkout it afterwards if the restore changed it. The new steps are a no-op when the cache doesn't affect .git (the if condition and sha comparison both guard against unnecessary work).

Instance of the failure

See this failing build from Homebrew/brew PR #21603 for a specific example.

Replaces the workaround in Homebrew/brew#21604 which applied the same fix inline in tests.yml.

The `actions/cache/restore` step restores the entire Homebrew prefix,
including `.git`. When the cached snapshot comes from a previous CI
run on a different branch (typically `main`), this silently resets the
repository to that branch, discarding the current checkout (e.g. a PR
merge commit).

Save the git HEAD sha before the cache restore and re-checkout it
afterwards if the cache restore changed it. This ensures callers
always run against the code they checked out.
Use env: block instead of ${{ }} interpolation in the run: script
to satisfy CodeQL's code injection check (GitHub Advanced Security).
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a critical issue where restoring the Homebrew prefix cache inadvertently resets the Homebrew repository's git state to a previously cached branch (typically main), causing PR workflows to test the wrong code and triggering "uncommitted modifications" errors.

Changes:

  • Add step to save the Homebrew repository's git HEAD SHA before cache restoration
  • Add step to restore the git state after cache restoration if it was changed
  • The fix ensures PR workflows test the correct code by re-checking out the original commit after cache restore

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Member

@MikeMcQuaid MikeMcQuaid left a comment

Choose a reason for hiding this comment

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

Thanks, great work 🙇🏻

@GunniBusch
Copy link

Wouldn't it make more sense to just cache the downloads? Because this will make it simpler and actually cache the thing we really want to cache? Especially since in a pr targeting homebrew/brew, can have unexpected issues. Also caching files that have been changes in the pr might be wasted cache storage. (just look at the size of the current prefix caches)

@MikeMcQuaid
Copy link
Member

Wouldn't it make more sense to just cache the downloads?

No. It is significantly slower.

If we can exclude the repository let's do that but this fixes the bug so is definitely better than the status quo.

@GunniBusch
Copy link

Wouldn't it make more sense to just cache the downloads?

No. It is significantly slower.

If we can exclude the repository let's do that but this fixes the bug so is definitely better than the status quo.

Sorry, I actually noticed, that I made it sound as criticism related to the pr, but no, I do agree this pr is important and be urged. And I should have opened an issue, which in retrospect would have been better. I apologise.

If rev-parse HEAD fails (e.g. corrupt .git), silently skip saving
the SHA so the restore step is a no-op and the action behaves as
it did before this PR.
@dduugg dduugg merged commit cced187 into main Feb 21, 2026
10 checks passed
@dduugg dduugg deleted the fix/cache-restore-git-state branch February 21, 2026 22:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants