Write build caches from every main push#1673

merged3
main
ci/cache-writes-on-main
openedOct 12, 2026byNNick
View on GitHubGitHub import enabledPR last imported 21d ago

Cache writes were gated on github.ref_protected. main lost its branch protection around Sep 11, so no run has written the R2 compiler cache or the cloud SDK cache since, and R2's lifecycle rule emptied the bucket on Oct 9-10. Every Rust job has compiled cold since.

Drop the ref_protected term. Only push events on main get write keys, and fork pull requests never receive secrets, so the write boundary is the same in practice.

Main pushes now fail setup-rust when the write credentials are missing, so a lost cache path shows up as a red main instead of slow CI weeks later.

Checks

2 failing Β· 23 successful
Some checks failed

Failing2

fa290d6
Synced from GitHub

Review in Change Stack β†’

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

βš™οΈ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 524f7ff0-aa4d-4268-9ede-8db234aac125

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 6d0ff2cd68fcbeb9ab2deff524adc3d40d46f3be and 418d2679e230adbac7191bdb8ebafc51e41a2ac2.


πŸ“’ Files selected for processing (5)
  • .github/actions/setup-rust/action.yml
  • .github/workflows/ci.yml
  • .github/workflows/cloud.yml
  • .github/workflows/release-contracts.yml
  • core/docs/RELEASE.md

ascii
1 ______________________________
2< AI vs. bugs. Round 1. Fight! >
3 ------------------------------
4 \
5 \ (\__/)
6 (β€’γ……β€’)
7 / γ€€ γ₯

No actionable comments were generated in the recent review. πŸŽ‰

ℹ️ Recent review info
βš™οΈ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c5e980d4-e5f0-401c-ae78-fc614752bc03

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 81194cea2af6134309ab125ebdd67b628f097cdf and 6d0ff2cd68fcbeb9ab2deff524adc3d40d46f3be.


πŸ“’ Files selected for processing (4)
  • .github/actions/setup-rust/action.yml
  • .github/workflows/ci.yml
  • .github/workflows/cloud.yml
  • .github/workflows/release-contracts.yml

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 6 remain after this review.



πŸ“ Summary

Summary by CodeRabbit

  • Chores
    • Main-branch builds can now save to the shared build cache regardless of branch-protection status.
    • Builds use read-only cache access outside main-branch pushes. Main-branch builds now report an error before compilation if the cache bucket is unavailable.
πŸ“ Summary
πŸ“ Summary

Walkthrough

GitHub Actions workflows now select writable KACHE credentials and enable cache saving for pushes to main, regardless of branch-protection status. The setup action also checks that KACHE_S3_BUCKET is set before running the compiler-cache action.

Changes

Main-branch KACHE cache configuration

Layer / File(s)Summary
Select KACHE credentials
.github/workflows/ci.yml, .github/workflows/cloud.yml, .github/workflows/release-contracts.yml
These workflows select write credentials for pushes to main without checking branch protection. Other runs use read-only credentials. The bucket remains empty if required credentials or the bucket variable are missing.
Validate bucket and enable cache saving
.github/actions/setup-rust/action.yml, .github/workflows/cloud.yml, .github/workflows/release-contracts.yml
The setup action reports an error and exits if the bucket is empty on a main-branch push. Cache saving for main-branch pushes no longer requires branch protection.

Priority: βž– Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: claude


Merge Risk: βšͺ Minimal Β· up to 6d0ff

Main pushes can write caches again and will fail visibly if cache credentials are unavailable. No actionable merge-blocking issue was established.

Architecture Summary

Architecture risk: πŸ”΅ Low Β· up to 6d0ff

The changed surface does not map to a changed system, dependency edge, entrypoint, or external dependency.

Changed systems: None identified.

Architecture concerns No architecture-level concerns identified.

Review details

Before / after behavior

  • observed β€” Modified behavior in .github/actions/setup-rust/action.yml: Adds a preflight check for pushes to getployz/ployz’s main branch. If KACHE_S3_BUCKET is empty, the action reports an error and exits with status 1.
  • observed β€” Modified behavior in .github/actions/setup-rust/action.yml: Removes the github.ref_protected requirement, so save-cache is enabled for pushes to main regardless of branch protection status.
  • observed β€” Modified behavior in .github/workflows/ci.yml: The comments now describe all main-branch pushes as receiving write keys. The write-credential selection in the bucket and key expressions no longer checks github.ref_protected; main-branch pushes use write credentials, while other events use read-only credentials. The bucket expression still requires both selected keys and vars.KACHE_S3_BUCKET, otherwise resolving to an empty string.
  • observed β€” Modified behavior in .github/workflows/cloud.yml: KACHE credential selection no longer checks github.ref_protected: pushes to refs/heads/main use the write credentials regardless of protection status; other runs use the read-only credentials. The bucket remains unset if either selected credential or the bucket variable is missing.

Pre-merge checks | Passed 5
βœ… Passed checks (5 passed)
Check nameStatusExplanation
Title checkPassedThe title clearly and concisely states the main change: enabling build-cache writes for every push to the main branch.
Description checkPassedThe description directly explains the cache-write issue, the removal of github.ref_protected, the credential boundary, and the failure behavior for missing write credentials.
Docstring CoveragePassedNo functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues checkPassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes checkPassedCheck skipped because no linked issues were found for this pull request.

✨ Finishing Touches
πŸ§ͺ Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

  • Autofix Β· Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

Cchatgpt-codex-connectorBotreviewed Β· 1 inline threadOct 12, 2026
Synced from GitHub

πŸ’‘ Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6d0ff2cd68

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 πŸ‘.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

.github/actions/setup-rust/action.ymlline 28Outdated Β· 6d0ff2cOpen thread
……@@ -20,6 +20,15 @@ runs:
25+ if: github.repository == 'getployz/ployz' && github.event_name == 'push' && github.ref == 'refs/heads/main'
26+ shell: bash
27+ run: |
28+ if [ -z "$KACHE_S3_BUCKET" ]; then

P2 Badge Validate write credentials instead of the fallback bucket

On a main push where either write secret is missing but the read-only credentials and bucket variable are still configured, the expressions in ci.yml, cloud.yml, and release-contracts.yml fall back to the read-only credential values while keeping KACHE_S3_BUCKET nonempty. This check therefore passes and the cache action receives a read-only or mixed credential pair, defeating the intended fail-fast behavior and allowing the shared cache to remain unwritable without this diagnostic; preserve a separate write-credential flag or test values that cannot be populated by the read fallback.

Useful? React with πŸ‘Β / πŸ‘Ž.

Valid. Fixed in ad0bd7c5c: KACHE_S3_WRITES is true only on a main push with both write secrets and the bucket, and the guard requires it, so a fallback to read keys now fails the run.

Synced from GitHub

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
πŸ“ Code Reviewβœ… Completed 2026-10-12T16:24:20.427469Zfa290d6New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to 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" or "@codex security review".

Codex reacts with πŸ‘€ while any review is running, comments if it has suggestions, and reacts with πŸ‘ once all reviews finish with no findings.

Independent verification

PASS+NOTES at 6d0ff2cd6

  • Security: OK. Write keys still need push + refs/heads/main. Reusable workflows see the caller's context. release.yml passes read secrets only and runs on tag refs. Fork PRs get no secrets. Same-repo PRs, workflow_dispatch, and cluster.yml schedule get read keys. The secrets are repo-scoped, so a collaborator could already reach them from any branch push. ref_protected never stopped that. Main is unprotected today, so every direct main push now writes the cache. That is the same trust as pushing code. For real isolation, move the write keys into a main-only Environment (follow-up).
  • Guard false-pass (.github/actions/setup-rust/action.yml:24-31): KACHE_S3_BUCKET falls back to the READ keys (ci.yml:21-22, same in cloud.yml and release-contracts.yml). If the write secrets go missing, or a gate like ref_protected comes back, the bucket stays non-empty and the guard passes. It would not have caught the original incident. It only catches "no credentials at all". Suggestion: export a KACHE_WRITE flag from the workflow env (push && main && secrets.KACHE_S3_ACCESS_KEY_ID != '') and require it.
  • Guard false-fail: none found. Every main-push caller of setup-rust (ci.yml jobs, and cloud.yml via secrets: inherit) has the bucket env. cluster.yml and build-testkit-image run only on schedule or dispatch. Release runs on tag refs.
  • actionlint clean. test-ci.py OK. No CI failures; rust-tests, cloud tests, and some release-contracts builds were still pending.

Independent verification (delta)

PASS at ad0bd7c5c. This fixes the guard false-pass from my earlier review.

  • KACHE_S3_WRITES (ci.yml:29, cloud.yml:46) is an && chain of comparisons, so it renders as the string true or false. Missing secrets evaluate to '', so a fallback to the read keys now fails the guard (setup-rust/action.yml:28).
  • cloud.yml called from ci.yml: a reusable workflow sees the caller's push/refs/heads/main context, the secrets passed through secrets: inherit, and the repo vars. It also defines its own copy of the variable, which it needs because a caller's workflow env does not reach a reusable workflow.
  • No false failure: the only setup-rust callers on a main push are the ci.yml jobs (90/122/184/222) and cloud.yml:85, and both workflows define the variable. cluster.yml and build-testkit-image run only on schedule or dispatch. When release.yml calls cloud.yml on a tag push, the ref is not main, so the guard is skipped. release-contracts.yml doesn't use setup-rust.
  • actionlint clean. test-ci.py OK. CI still pending, no failures.
Cchatgpt-codex-connectorBotreviewed Β· 2 inline threadsOct 12, 2026
Synced from GitHub

πŸ’‘ Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ad0bd7c5c6

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 πŸ‘.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

.github/workflows/release-contracts.ymlline 32Outdated Β· ad0bd7cOpen thread
……@@ -29,16 +29,16 @@ permissions:
3030
3131env:
32- # Only protected main pushes receive write keys; all other runs use R2 read-only keys.
32+ # Only main pushes receive write keys; all other runs use R2 read-only keys.

P2 Badge Update the release guide for unprotected main writes

This now intentionally gives every main push the write credentials, but core/docs/RELEASE.md:34 still says twice that only protected main pushes populate the cache and receive those credentials. Because that paragraph is the operational reference for configuring the R2 secrets, leaving it unchanged documents a credential boundary that no longer exists and can mislead incident response or future workflow maintenance.

Useful? React with πŸ‘Β / πŸ‘Ž.

Valid. Fixed in 418d2679e: core/docs/RELEASE.md now says main pushes receive write keys and fail without them. #1674 also updates the sentence on when release contracts run (b26efe065).

.github/workflows/release-contracts.ymlline 107Outdated Β· ad0bd7cOpen thread
……@@ -104,7 +104,7 @@ jobs:
105105 warm: true
106106 sync: false
107- save-cache: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && github.ref_protected }}
107+ save-cache: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}

P2 Badge Add the write-credential guard to release cache jobs

For a main push that selects release-contracts while the Cloud SDK cache hits and no regular Rust job runs, these direct kache-action steps never execute setup-rust's fail-fast check. Fresh evidence in this revision is that KACHE_S3_WRITES is checked only by setup-rust, whereas this workflow invokes the cache action directly; if either write secret is absent, lines 35–41 substitute read-only or mixed credentials and the expensive Linux/macOS builds proceed before the cache save fails or is lost. Add the equivalent credential guard before these release builds.

Useful? React with πŸ‘Β / πŸ‘Ž.

Valid. Fixed in 418d2679e: release-contracts.yml defines KACHE_S3_WRITES and both build jobs run the same guard before their direct kache-action step. Tag-ref release calls skip it.

Independent verification (delta 3)

PASS at 418d2679e

  • The guard in release-contracts.yml (:93, :161) can't false-fail:
    • When release.yml calls it on a tag push, the ref is refs/tags/v*, so the step is skipped.
    • Dispatching release.yml from main has event workflow_dispatch, so it is skipped too.
    • When ci.yml calls it on a PR, the step is skipped.
    • When ci.yml calls it on a main push with secrets: inherit, KACHE_S3_WRITES (:43) renders true.
  • actions/checkout runs before the guard in both jobs, so the default working-directory: core exists. The step never touches the directory.
  • core/docs/RELEASE.md:34 matches behavior. Every main push runs cloud (ci.yml if), so a main push without write keys does fail.
  • actionlint clean. test-ci.py OK.

Added 3 commits

  • Fail main pushes that lack compiler cache write keys524734f
  • Write build caches from every main pushaad41e7
  • Guard release cache jobs and document unprotected main writesfa290d6
Synced from GitHub

πŸ’‘ Codex Review

https://github.com/getployz/ployz/blob/fa290d62b2867aa30eb014a5298b357ae363ab7d/.github/workflows/cloud.yml#L46 P2 Badge Run the credential guard even on SDK cache hits

On a main push that selects no other Rust or release jobβ€”for example, a docs-only changeβ€”an existing exact-key sdk-cache causes setup-rust to be skipped at lines 85–86, so this flag is never checked and the push remains green after the R2 write secrets are removed. Since Cloud runs on every main push and this cache commonly hits, credential loss can again remain undetected until an SDK input changes; run the guard before the cache-hit branch or from an unconditional main-push job.

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 πŸ‘.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".