Skip to content

ci: enable cargo cache in Earthly for CI runs; use branch as cache key locally - #2033

Open
ozgb wants to merge 5 commits into
mainfrom
ozgb-ci-cache
Open

ci: enable cargo cache in Earthly for CI runs; use branch as cache key locally#2033
ozgb wants to merge 5 commits into
mainfrom
ozgb-ci-cache

Conversation

@ozgb

@ozgb ozgb commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Overview

Follow-up to #1814

  • Enabled build caching in CI; keyed by branch name to avoid cache corruption
    • Takes advantage of our persistent buildkit instance on the self-hosted runners
    • External PRs don't use our runners, so caching is off there
  • Use branch name keys locally too, to avoid cache corruption

🗹 TODO before merging

  • Ready

📌 Submission Checklist

  • All commits are signed off (git commit -s) for the DCO
  • Changes are backward-compatible (or flagged if breaking)
  • Pull request description explains why the change is needed
  • Self-reviewed the diff
  • I have included a change file, or skipped for this reason:
  • If the changes introduce a new feature, I have bumped the node minor version
  • Update documentation (if relevant)
  • Updated AGENTS.md if build commands, architecture, or workflows changed
  • No new todos introduced

🧪 Testing Evidence

Please describe any additional testing aside from CI:

  • Additional tests are provided (if possible)

🔱 Fork Strategy

  • Node Runtime Update
  • Node Client Update
  • Other:
  • N/A

Links

…y locally

Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
@ozgb
ozgb requested a review from a team as a code owner August 18, 2026 09:44

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8c5a141293

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread .envrc Outdated
Comment on lines +43 to +44
if [[ "${CI:-}" != "true" ]]; then
export EARTHLY_BUILD_ARGS="${EARTHLY_BUILD_ARGS:+$EARTHLY_BUILD_ARGS,}CACHE_KEY=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-' || echo local)"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Pass a branch key to every self-hosted CI build

When the self-hosted continuous-integration.yml build job invokes +images and the main.yml publish job invokes +node-image/+toolkit-image, they source this file with GitHub's CI=true but do not pass --CACHE_KEY. This condition therefore leaves the Earthfile default of local, so the newly unconditional /target mounts become target-local-$TARGETARCH for every PR and release branch on those persistent runners, recreating the cross-branch stale-artifact failures that the cache key is intended to prevent. Ensure these callers derive and pass a sanitized ref, or derive it here from the GitHub ref variables instead of skipping CI.

Useful? React with 👍 / 👎.

gilescope
gilescope previously approved these changes Aug 18, 2026
@datadog-official

This comment has been minimized.

ozgb added 2 commits August 18, 2026 11:50
The CI branch of .envrc skipped CACHE_KEY entirely, so only the four jobs
that pass --CACHE_KEY by hand were scoped; +images (build node and images)
and main.yml's +node-image/+toolkit-image fell back to the "local" default
and shared one /target across every branch on the persistent runners —
exactly the cross-branch staleness the key exists to prevent.

Derive it from GITHUB_HEAD_REF/GITHUB_REF_NAME (rev-parse is useless under
actions/checkout's detached HEAD) with the same sanitizing the workflows
use. A target arg on the command line still overrides it, verified against
earthly 0.8.16, so the compact-contract-tests fixed key is unaffected.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>
… caches

Enabling the cargo caches on CI made concurrent builds on one buildkit
daemon corrupt each other: `failed to unpack windows v0.52.0 ... .cargo-ok:
File exists` and `failed to stat <polkadot-sdk git checkout>/westend.json`,
which took out all 3 retries of the amd64 build.

cargo already serializes precisely the section that must not overlap —
downloading/unpacking crates and updating git checkouts — with an flock on
$CARGO_HOME/.package-cache, and downgrades to a shared lock for the compile.
That lock was inert here: it lives in the image layer while registry/ and
git/ are shared CACHE mounts, so each concurrent container flocked its own
private file. Symlink it onto the registry mount so the exclusion spans them.

Measured with two concurrent `cargo fetch` runs (277 crates) sharing one
registry mount, earthly 0.8.16:
  before: both ran the whole fetch window concurrently, 0 lock waits
  after:  each reports "Blocking waiting for file lock on package cache",
          both still complete in 4s — compiles stay parallel

Buildkit's CACHE --sharing locked is not an alternative: measured, a mount
held locked by one build is not waited on by others; they are handed a fresh
empty cache dir instead, which would mean an empty registry mid-build.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7d5b408887

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread Earthfile
END
CACHE --sharing shared --id cargo-git /usr/local/cargo/git
CACHE --sharing shared --id cargo-reg /usr/local/cargo/registry
CACHE --id target-${CACHE_KEY}-${TARGETARCH} /target

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Key bot rebuild caches by the checked-out PR branch

The final tree fixes the previously named .envrc-based +images callers, but the self-hosted rebuild-metadata-bot.yml and rebuild-chainspec-bot.yml jobs still do not source .envrc, and this commit removes their cache-disabling EARTHLY_BUILD_ARGS without supplying CACHE_KEY. Consequently +rebuild-metadata reaches +build-node-only, and an unversioned +rebuild-chainspec reaches +node-image, with this newly unconditional target-local-$TARGETARCH mount shared across PR branches; stale artifacts can therefore be committed as metadata or chainspec output. Pass a sanitized steps.pr.outputs.ref as --CACHE_KEY in both supported bot workflows.

AGENTS.md reference: AGENTS.md:L27-L30

Useful? React with 👍 / 👎.

Comment thread .envrc
# EARTHLY_BUILD_ARGS survives; a `+target --CACHE_KEY=...` on the command line still wins
# over this (that is how the compact-contract-tests job keeps its fixed shared key).
if [[ "${EARTHLY_BUILD_ARGS:-}" != *CACHE_KEY=* ]]; then
_cache_key=$(printf '%s' "${GITHUB_HEAD_REF:-${GITHUB_REF_NAME:-$(git rev-parse --abbrev-ref HEAD 2>/dev/null)}}" | tr -c 'A-Za-z0-9._-' '-')

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve uniqueness when sanitizing cache keys

When two valid refs differ only by a character replaced by tr—for example feature/foo and feature-foo—both become the same cache key. If those branches build on the shared self-hosted daemon, they again share /target, defeating the isolation intended to prevent cross-branch stale Cargo artifacts. Append a hash of the original ref, or otherwise use an injective encoding rather than replacement alone.

Useful? React with 👍 / 👎.

.envrc now derives CACHE_KEY from the GitHub ref vars, so the four jobs that
computed it by hand were duplicating it. Verified equivalent: none of these
workflows trigger on pull_request_target, the only event where GITHUB_HEAD_REF
is set but `github.event_name == 'pull_request'` is false, and every one of
these steps sources .envrc before invoking earthly.

compact-contract-tests keeps its explicit --CACHE_KEY: a target arg on the
command line overrides EARTHLY_BUILD_ARGS (verified against earthly 0.8.16),
so its deliberately fixed, cross-branch key still wins.

The rebuild-*-bot workflows were the remaining hole — they pin EARTHLY_CONFIG
themselves rather than sourcing .envrc, so removing their CI=true (which used
to disable the caches outright) left them on the "local" key while running on
self-hosted runners; +rebuild-metadata reaches +build-node-only, which mounts
/target. They cannot just source .envrc either: on issue_comment events the
GitHub ref vars name the default branch, so a metadata rebuild would write the
PR's artifacts into main's cache. Use the PR head ref they already resolve.

Checked: actionlint clean, and the derivation yields the head ref on
pull_request, the queue ref on merge_group, `main` on push, the local branch
off-CI, and leaves a preset value untouched.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Oscar Bailey <79094698+ozgb@users.noreply.github.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a7a5178a33

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread .envrc
# EARTHLY_BUILD_ARGS survives; a `+target --CACHE_KEY=...` on the command line still wins
# over this (that is how the compact-contract-tests job keeps its fixed shared key).
if [[ "${EARTHLY_BUILD_ARGS:-}" != *CACHE_KEY=* ]]; then
_cache_key=$(printf '%s' "${GITHUB_HEAD_REF:-${GITHUB_REF_NAME:-$(git rev-parse --abbrev-ref HEAD 2>/dev/null)}}" | tr -c 'A-Za-z0-9._-' '-')

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Key manual publishes by the checked-out branch

When main.yml is manually dispatched with its branch input set to a branch other than the workflow's selected ref, the checkouts at main.yml:45 and main.yml:263 build the input branch, but GITHUB_REF_NAME still identifies the workflow-run ref and takes precedence over Git's checked-out state here. Both publish jobs can therefore reuse another branch's /target cache and push binaries containing stale artifacts. The fresh final-tree evidence beyond the earlier missing-key comment is that a key is now derived, but it is derived from a ref that can differ from the explicit checkout input; pass that input as the cache key or derive the checked-out commit/ref instead.

Useful? React with 👍 / 👎.

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