Skip to content

fix(ci): stop pinning submodules to tags via branch - #175

Merged
ryanio merged 1 commit into
mainfrom
fix/forge-ci-submodule-refs
Aug 22, 2026
Merged

fix(ci): stop pinning submodules to tags via branch#175
ryanio merged 1 commit into
mainfrom
fix/forge-ci-submodule-refs

Conversation

@ryanio

@ryanio ryanio commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

Motivation

Both Forge jobs in Test CI fail on the "Install forge dependencies" step, before any contract compiles:

Updating dependencies in /home/runner/work/seadrop/seadrop/lib
Error: git checkout exited with code 1: error: pathspec 'v1.5.0' did not match any file(s) known to git

.gitmodules declared branch = v1.5.0 for lib/forge-std and branch = v0.1.3 for lib/create2-helpers. Neither value is a branch. Both are tags, and both still exist upstream, so no ref was deleted.

forge install reads .gitmodules to build a foundry.lock. No lockfile is committed here, so every submodule is treated as out of sync and forge checks each one out at its recorded identifier. A submodule carrying a branch line becomes DepIdentifier::Branch { name }, and checkout_id() returns that literal string, so forge runs git checkout v1.5.0. actions/checkout clones submodules at depth 1 and fetches no tags, so the pathspec does not resolve and the step exits 1. Without a branch line the submodule becomes DepIdentifier::Rev { rev }, and forge checks out the recorded commit, which is present in the shallow clone.

The two jobs reported different pathspecs, v0.1.3 in Forge Coverage and v1.5.0 in Forge Tests, because the out-of-sync set is a hash map with no fixed iteration order. Either entry can surface first, so both had to go.

The forge-std pin was stale in content as well as wrong in kind. The recorded gitlink is 726a6ee, which is v1.9.5 plus two commits from January 2025, nowhere near v1.5.0. Nothing was resolving that label; it was only breaking the install.

Solution

Two changes, both confined to CI and dependency pinning. No contract source is touched.

Drop the two branch lines so the recorded submodule commits are the only pin. That is what the repo was already building against, so this changes which ref forge asks git for, not which code lands in lib/. All ten resolved commits are byte for byte identical to the gitlinks on main.

Pin the Foundry toolchain to v1.5.1 instead of tracking nightly. Toolchain drift is what broke the install step, and the same nightly introduces a second failure: it probes the fork RPC with anvil_nodeInfo, and Alchemy answers that unknown method with HTTP 400 rather than a JSON-RPC error, which aborts vm.createSelectFork in ERC721SeaDropCloneFactory.t.sol. Providers that return HTTP 200 with an error body are unaffected. I cannot read the ETHEREUM_RPC_URL secret, so I do not know whether CI would hit this, but v1.5.1 avoids it either way. v1.5.1 is what the toolchain action's stable channel currently resolves to.

Verification

Reproduced against forge 1.8.0-nightly (e469863), the exact build CI installed on 2026-08-22, using a clone that replicates actions/checkout (--depth=1 plus git submodule update --init --force --depth=1 --recursive).

Step Before After
forge install exit 1, pathspec 'v0.1.3' did not match exit 0
forge build not reached exit 0
forge test not reached 56 passed, 0 failed
forge coverage not reached exit 0

The test and coverage runs above are on v1.5.1 with a real mainnet RPC, so the forking test in ERC721SeaDropCloneFactory.t.sol ran rather than being skipped. Under 1.8.0-nightly the same suite is 55 passed / 1 failed, the one failure being the Alchemy probe described above; v1.7.1 also passes 56/56.

Dependency resolution is unchanged. Recorded gitlinks before and after the edit:

9be81f029a0883e0c7c6d5a410ee49c48c69205d  lib/ERC721A
bb4edecb6a824211ec7c09bb9d737921c89dc21c  lib/ERC721A-Upgradeable
16d44965aea6a06660b9e4e57d93706104e59938  lib/create2-helpers
e282159d5170298eb2455a6c05280ab5a73a4ef0  lib/ds-test
726a6ee5fc8427a0013d6f624e486c9130c0e336  lib/forge-std
5f962edf98f2aeaf2706f7bfd07fac4532b42cc6  lib/murky
6a8d977d2248cf1c115497fccfd7a2da3f86a58f  lib/openzeppelin-contracts
25aabd286e002a1526c345c8db259d57bdf0ad28  lib/openzeppelin-contracts-upgradeable
01a52350852b6036dd0fd9af909fb3db765d56dc  lib/solmate
6543a1dd10160936849de2f2fbcc18503906fb1e  lib/utility-contracts

Notes

forge install writes a foundry.lock that is neither committed nor ignored, so it shows up as untracked after a local run. Committing it would pin dependencies explicitly and is the direction Foundry recommends, but it adds a file that has to be kept in step with .gitmodules, so I left it out of this change.

`.gitmodules` declared `branch = v1.5.0` for lib/forge-std and
`branch = v0.1.3` for lib/create2-helpers. Both values are tags, not
branches. With no foundry.lock committed, `forge install` treats every
submodule as out of sync and checks it out at its recorded identifier; a
`branch` line makes that identifier the literal string, so forge runs
`git checkout v1.5.0` against the depth-1 submodule clone that
actions/checkout produces, which carries no tags. Every Forge job died
there before compiling anything.

Dropping both lines leaves the recorded commits as the only pin, which
is what the repo already built against. All ten resolved gitlinks are
unchanged.

Also pin foundry-toolchain to v1.5.1 rather than tracking nightly, since
toolchain drift is what broke the step.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 32604609308

Coverage increased (+11.3%) to 64.702%

Details

  • Coverage increased (+11.3%) from the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 905
Covered Lines: 693
Line Coverage: 76.57%
Relevant Branches: 605
Covered Branches: 284
Branch Coverage: 46.94%
Branches in Coverage %: Yes
Coverage Strength: 722.06 hits per line

💛 - Coveralls

@ryanio
ryanio merged commit 454c9f8 into main Aug 22, 2026
11 checks passed
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.

2 participants