Problem
CI does not currently verify `foundry.lock` against either the submodule pointers in the tree or the upstream repos. It only clones submodules at whatever sha the tree records and runs the test suites against that. As a result a `foundry.lock` whose `rev` disagrees with the submodule pointer, or whose `rev` does not exist on the upstream repo at all, passes CI silently.
This shipped at #2558 — `foundry.lock` had `lib/rain.interpreter.rev = 1ea41cd0ec4a8afd7dec9aeae0a65a55c95fac46`, which does not exist on rainlanguage/rain.interpreter. The submodule pointer in the tree was the correct `1ea41cd004a926e3a964ba5498654f3cd538f139`, so all builds and tests passed. The breakage only surfaced when a downstream PR ran `forge update lib/rain.interpreter` and got `fatal: unable to read tree`. Fixed at #2559.
Suggested check
Add a CI step that runs:
```bash
nix develop -c forge update <each lib/*>
git diff --exit-code foundry.lock lib/
```
For a tree whose lockfile is consistent with reachable upstream commits, `forge update` is a no-op — no diff, exit 0. If `foundry.lock`'s `rev` does not exist upstream, `forge update` fails with `unable to read tree` and CI fails. If `foundry.lock`'s `rev` is a real but stale commit (not matching the tree pointer), `forge update` rewrites the submodule pointer to match, `git diff` is non-empty, and CI fails.
The check should iterate the four submodules in `foundry.lock`: `lib/rain.deploy`, `lib/rain.interpreter`, `lib/rain.raindex.interface`, `lib/sushixswap-v2`.
Out of scope
Whether the upstream commit is on the dep's main branch (i.e., catching pins to closed/abandoned branches) is a different concern — the proposed check only verifies reachability and consistency, not branch policy.
Problem
CI does not currently verify `foundry.lock` against either the submodule pointers in the tree or the upstream repos. It only clones submodules at whatever sha the tree records and runs the test suites against that. As a result a `foundry.lock` whose `rev` disagrees with the submodule pointer, or whose `rev` does not exist on the upstream repo at all, passes CI silently.
This shipped at #2558 — `foundry.lock` had `lib/rain.interpreter.rev = 1ea41cd0ec4a8afd7dec9aeae0a65a55c95fac46`, which does not exist on rainlanguage/rain.interpreter. The submodule pointer in the tree was the correct `1ea41cd004a926e3a964ba5498654f3cd538f139`, so all builds and tests passed. The breakage only surfaced when a downstream PR ran `forge update lib/rain.interpreter` and got `fatal: unable to read tree`. Fixed at #2559.
Suggested check
Add a CI step that runs:
```bash
nix develop -c forge update <each lib/*>
git diff --exit-code foundry.lock lib/
```
For a tree whose lockfile is consistent with reachable upstream commits, `forge update` is a no-op — no diff, exit 0. If `foundry.lock`'s `rev` does not exist upstream, `forge update` fails with `unable to read tree` and CI fails. If `foundry.lock`'s `rev` is a real but stale commit (not matching the tree pointer), `forge update` rewrites the submodule pointer to match, `git diff` is non-empty, and CI fails.
The check should iterate the four submodules in `foundry.lock`: `lib/rain.deploy`, `lib/rain.interpreter`, `lib/rain.raindex.interface`, `lib/sushixswap-v2`.
Out of scope
Whether the upstream commit is on the dep's main branch (i.e., catching pins to closed/abandoned branches) is a different concern — the proposed check only verifies reachability and consistency, not branch policy.