Skip to content

Fork CI: static musl release binaries keyed by commit SHA - #2

Merged
thedancingdeveloper merged 3 commits into
fork/mainfrom
fork/release
Oct 9, 2026
Merged

thedancingdeveloper merged 3 commits into
fork/mainfrom
fork/release

Conversation

@thedancingdeveloper

Copy link
Copy Markdown

Summary

  • Adds .github/workflows/fork-release.yml, a fork-only workflow that builds static musl binaries for x86_64-unknown-linux-musl (ubuntu-24.04) and aarch64-unknown-linux-musl (ubuntu-24.04-arm) on every push to fork/main.
  • Reuses the upstream musl setup unchanged: zig 0.14.0 (mlugg/setup-zig), .github/scripts/install-musl-build-tools.sh, ./.github/actions/setup-rusty-v8, and AWS_LC_SYS_NO_JITTER_ENTROPY=1.
  • Builds --bin bwrap first, strips it and exports CODEX_BWRAP_SHA256 before the codex build. This is required: linux-sandbox embeds option_env!("CODEX_BWRAP_SHA256") and verifies the bundled bwrap against it (the unset case is a silent None, so the sandbox would skip its integrity check).
  • Stamps the workspace version 0.0.0 as <upstream>+fork.<shortsha> (currently 0.162.0) so codex --version reports the fork. The version is advanced in the rebase procedure; git describe cannot be used because upstream tags are not fetched.
  • Publishes a GitHub release tagged with the full commit SHA, with SHA256SUMS, which is how the Vogt engine installs the fork (WI-1142).
  • Every action is pinned to a full commit SHA verified to exist on 2026-10-09: checkout fbc6f399, rust-toolchain e0818162 (1.95.0), setup-zig d1434d08 (v2.2.1), upload-artifact ea165f8d (v4.6.2), download-artifact d3f86a10 (v4.3.0).

Not verified, left for CI: whether the musl script works on GitHub-hosted runners as it does on upstream's, and the build time and binary size. No local build was run; the root filesystem is too full for a workspace build.

Test plan

  • Merge and let the fork/main push run the workflow
  • Confirm the release tagged with the full SHA has both arch archives and SHA256SUMS
  • codex --version from the asset reports 0.162.0+fork.<shortsha>

@thedancingdeveloper thedancingdeveloper left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Review (epic lead, WI-1122). Blockers on head d003e74:

  1. bwrap is stripped again after its digest is taken. The "Build release binaries" loop strips codex codex-code-mode-host bwrap. linux-sandbox verifies the shipped bwrap against the embedded CODEX_BWRAP_SHA256 at runtime (codex-rs/linux-sandbox/src/bundled_bwrap.rs:151-175). If the second strip changes a byte, the sandbox fails closed, so the sandbox is broken in every release. Upstream deliberately skips bwrap at this point (rust-release.yml:293: "bwrap is already stripped before hashing"). Fix: drop bwrap from that loop, and add an assertion in Package that sha256sum bwrap equals $CODEX_BWRAP_SHA256, failing the job otherwise.
  2. The release job has no checkout, so gh release view/create has no repository context and will fail. Set GH_REPO: ${{ github.repository }} in that step's env.
  3. The top-level permissions: contents: write hands a write token to the build job, which runs third-party actions (setup-zig) and repo scripts. Set top-level contents: read, and contents: write only on release.
  4. upstream_version="0.162.0" is right only once fork/main is re-pointed to rust-v0.162.0 (see the #1 review). Keep it, conditional on that change.

Non-blocking:

  • Add a smoke step after the build: codex --version matches the stamp, and codex --help runs.
  • Add concurrency: fork-release-${{ github.sha }}.
  • A bare 40-hex tag name makes git print "refname is ambiguous" for anyone who fetches tags. fork-<sha> would avoid that. Either works for WI-1142, as long as one is chosen and documented in FORK.md.

Builds static x86_64 and aarch64 musl binaries on ubuntu-24.04 and
ubuntu-24.04-arm, reusing the upstream musl setup (zig 0.14.0,
install-musl-build-tools.sh, setup-rusty-v8, AWS_LC_SYS_NO_JITTER_ENTROPY).
bwrap is built and stripped first and its digest exported as
CODEX_BWRAP_SHA256, which linux-sandbox embeds and verifies. The workspace
version 0.0.0 is stamped <upstream>+fork.<shortsha> so codex --version
reports the fork. Publishes a GitHub release tagged with the full commit
SHA plus SHA256SUMS.

Every action is pinned to a full commit SHA verified to exist. New file
with a fork-unique name; no upstream workflow is edited.
- contents: read at the top level, contents: write only on the release job.
- bwrap is no longer stripped a second time after hashing, which would change
  the bytes CODEX_BWRAP_SHA256 covers. The package step asserts the shipped
  bwrap's sha256 equals the embedded digest and fails the build otherwise.
- The release step sets GH_REPO to github.repository so gh cannot fall back to
  the upstream repository.
@thedancingdeveloper

Copy link
Copy Markdown
Author

Addressed, rebased onto c1382380d. New head: 48e39fc74f.

  • bwrap is no longer re-stripped after hashing, and the package step asserts the shipped bwrap's sha256 equals CODEX_BWRAP_SHA256.
  • The release step sets GH_REPO to github.repository.
  • contents: read at the top level, contents: write only on the release job.

@thedancingdeveloper thedancingdeveloper left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Review (epic lead). Blocker on head 48e39fc:

  1. Every cargo build runs at the repo root, which has no Cargo.toml. The workspace is codex-rs/, so cargo build --bin bwrap fails at once. Upstream uses working-directory: codex-rs (rust-release.yml:75). Fix: add defaults: run: working-directory: codex-rs to the build job and adjust every relative path to match:
    • the stamp step's codex-rs/Cargo.toml becomes Cargo.toml;
    • target/… and dist/… now resolve under codex-rs/;
    • upload-artifact path: needs the codex-rs/ prefix, because actions don't take defaults.run.
      Run the workflow once with workflow_dispatch on the PR branch before asking for re-review, and link the run. A green run is the only real test of this file.

Resolved since last review: no bwrap re-strip, plus the digest assertion; GH_REPO; contents: read at the top with write only on release.

The repo root has no Cargo.toml, so every cargo build failed. The build job
now defaults its run steps to codex-rs/, the version stamp edits Cargo.toml
there, and the artifact paths are prefixed codex-rs/ because actions do not
honour defaults.run. The musl build-tools step stays at the repo root: its
script and setup-rusty-v8 write under GITHUB_WORKSPACE.

@thedancingdeveloper thedancingdeveloper left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Review: no blockers (head 4893226)

The working-directory fix is correct: defaults.run.working-directory: codex-rs on build, the musl script runs at the workspace root, and the stamp and artifact paths are adjusted. Every earlier blocker is resolved (bwrap digest assertion, GH_REPO, token scopes).

I'm withdrawing my request for a pre-merge dispatch run. workflow_dispatch only works when the file is on the repo's default branch, which is main (the upstream mirror), so it can't run from here. The first real test is the push trigger when this merges to fork/main. A failure there only delays the first release, so it goes in as a follow-up fix. Suggestion for oversight: make fork/main the fork's default branch. Dispatch then works, and gh pr create targets the right base by default.

@thedancingdeveloper
thedancingdeveloper merged commit a37c27e into fork/main Oct 9, 2026
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