Skip to content

[REL] Publish signed releases index to R2#101

Merged
tazarov merged 1 commit into
mainfrom
codex/r2-release-history-index
Feb 28, 2026
Merged

[REL] Publish signed releases index to R2#101
tazarov merged 1 commit into
mainfrom
codex/r2-release-history-index

Conversation

@tazarov

@tazarov tazarov commented Feb 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add historical release tracking by publishing bounded releases.json to R2
  • sign and verify releases.json with cosign keyless (releases.json.sig/releases.json.pem)
  • upload and short-cache release metadata (latest.json, releases.json)
  • purge CDN cache for both metadata endpoints
  • update CI/CD docs to mention releases.json history metadata

Why

The global releasing-to-r2 skill recommends optional releases.json publishing so clients can fetch historical releases without listing bucket keys.

Validation

  • actionlint .github/workflows/rust-release.yml
  • actionlint .github/workflows/go-security.yml

@claude

claude Bot commented Feb 28, 2026

Copy link
Copy Markdown

Review

Good addition overall — the pattern follows the existing cosign keyless approach already established for artifacts/SHA256SUMS, and the bounded list with unique_by(.version) + 100-entry cap is solid.

Issues

Concurrent release race on releases.json (minor)
The read-modify-write of releases.json (download → append → upload) is not atomic. Two simultaneous releases could each read the same stale index and one will silently overwrite the other's entry. Unlikely in practice, but worth a comment in the code. The unique_by safeguard handles same-version re-runs but not two distinct concurrent releases.

releases.json signing inside the upload step
The sign + verify + upload sequence all lives in the "Upload artifacts" step. If upload fails after signing but before the S3 copy completes, the step fails cleanly due to set -euo pipefail — that's fine. But consistency with the rest of the workflow (which has a dedicated "Sign artifacts" step and a dedicated "Verify signatures" step) suggests splitting this out would be cleaner and easier to debug from the Actions log.

content-type for .pem files (nit)
text/plain works but application/x-pem-file is the registered MIME type. The .sig files (raw base64) also don't have a more specific type, so this is consistent with the existing uploads — just worth noting.

Minor observations

  • The go-security.yml quoting change is functionally identical to the unquoted form in bash; if it was flagged by actionlint, fine — otherwise it's noise in this PR.
  • RELEASE_DATE extraction to a variable (avoiding re-running date for both latest.json and releases.json) is a nice improvement from the prior inline subshell.
  • The graceful fallback to {"releases":[]} when the file doesn't exist or is malformed is good defensive coding.

Verdict

No blocking issues. The race condition is the most noteworthy concern but acceptable at this project's release cadence. The CDN purge covering all four new paths (latest.json, releases.json, .sig, .pem) is correct.

@tazarov tazarov merged commit b066ec1 into main Feb 28, 2026
13 checks passed
@tazarov tazarov deleted the codex/r2-release-history-index branch February 28, 2026 13:18
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.

1 participant