Add the PwrAgent Codex release pipeline - #2
Merged
Harold Hunt (huntharo) merged 2 commits intoAug 19, 2026
Conversation
Builds and signs downstream Codex binaries once, for PwrAgent, PwrSnap, and PwrGit to share, so none of them signs Codex itself. Modeled on the equivalent pipeline in pwrdrvr/grok-build. Upstream's `rust-release.yml` cannot be reused here: it targets self-hosted runner groups (`codex-runners`, `macos-15-xlarge`) that do not exist on this fork, and signs through OpenAI's `codesigning` environment. So this is a separate workflow on GitHub-hosted runners, signing with PwrDrvr credentials from the `apple-signing` and `windows-signing` environments. Ships five assets: macOS arm64/x64, Linux arm64/x64, Windows x64. Each carries `codex`, `codex-app-server`, and `codex-code-mode-host`, plus the Windows sandbox helpers on Windows, alongside LICENSE, NOTICE, and a provenance stamp. Signing is fail-closed by construction, and `check-release-signing.py` pins the properties that make it so: - The jobs that build and stage enter no environment and read no secrets. They hand off a tarball plus its SHA-256; the signing jobs verify that digest before touching a credential. - `release-candidate` requires both signing jobs, so there is no path from a build to a published asset that skips a signer. - The Windows TrustedSigning client is downloaded, catalog-verified, and checksummed in the unprivileged prepare job and shipped to the signing job as pinned bytes. The signing job may not call `Save-Module`/`Install-Module`. - Every shipped executable is signed and then individually verified, rather than just the CLI entrypoint. The contract also pins the workflow to GitHub-hosted runners, since reaching for a self-hosted group is exactly how this would silently stop working on the fork. `ci:release-signing` on a pull request runs the whole pipeline, signing included, and produces a `signed-release-candidate` without publishing. A `pwragent-v*` tag publishes an immutable prerelease. Deliberate deviations from upstream, recorded in docs/pwragent-distribution.md: glibc rather than MUSL, no bundled `bwrap`, no DMG or dSYM archives, and no Windows arm64. The `bwrap` omission is the one most likely to need revisiting if a PwrDrvr product ships Codex on Linux to end users. macOS binaries are signed but not notarized. They are meant to nest inside an already-notarized PwrDrvr bundle, which works because they carry the same Team ID and hardened runtime; shipping one standalone would need a notarization step that does not exist yet.
- `workflow_dispatch` built macOS and Windows but produced nothing usable for them, because every artifact-producing job downstream is gated on a tag or the `ci:release-signing` label. Manual runs now emit `unsigned-*` archives, as grok-build does, so a smoke test is worth the runner time it costs. - Dropped the separate `signing-input-digest-*` artifact. It duplicated the checksum already shipped inside the payload artifact, written by the same job into the same store, so it added no integrity property. The comment claiming it approximated grok-build's job-output digest was wrong and is replaced with an accurate note about why this side cannot have one. - `windows-prepare` now prepares the TrustedSigning client before the release build. It takes about a minute and depends on PSGallery, so failing it after a two-hour compile threw the compile away. - Added a Cargo registry cache to all five build jobs, keyed on Cargo.lock. The target directory is deliberately not cached: five platforms would churn through the repository cache budget.
Harold Hunt (huntharo)
added a commit
that referenced
this pull request
Aug 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Builds and signs downstream Codex binaries once, for PwrAgent, PwrSnap, and
PwrGit to share, so none of them signs Codex itself. Modeled on the equivalent
pipeline in pwrdrvr/grok-build.
Upstream's
rust-release.ymlcannot be reused here: it targets self-hostedrunner groups (
codex-runners,macos-15-xlarge) that do not exist on thisfork, and signs through OpenAI's
codesigningenvironment. So this is aseparate workflow on GitHub-hosted runners, signing with PwrDrvr credentials
from the
apple-signingandwindows-signingenvironments.Ships five assets: macOS arm64/x64, Linux arm64/x64, Windows x64. Each carries
codex,codex-app-server, andcodex-code-mode-host, plus the Windowssandbox helpers on Windows, alongside LICENSE, NOTICE, and a provenance stamp.
Signing is fail-closed by construction, and
check-release-signing.pypins theproperties that make it so:
hand off a tarball plus its SHA-256; the signing jobs verify that digest
before touching a credential.
release-candidaterequires both signing jobs, so there is no path from abuild to a published asset that skips a signer.
checksummed in the unprivileged prepare job and shipped to the signing job as
pinned bytes. The signing job may not call
Save-Module/Install-Module.than just the CLI entrypoint.
The contract also pins the workflow to GitHub-hosted runners, since reaching
for a self-hosted group is exactly how this would silently stop working on the
fork.
ci:release-signingon a pull request runs the whole pipeline, signingincluded, and produces a
signed-release-candidatewithout publishing. Apwragent-v*tag publishes an immutable prerelease.Deliberate deviations from upstream, recorded in docs/pwragent-distribution.md:
glibc rather than MUSL, no bundled
bwrap, no DMG or dSYM archives, and noWindows arm64. The
bwrapomission is the one most likely to need revisitingif a PwrDrvr product ships Codex on Linux to end users.
macOS binaries are signed but not notarized. They are meant to nest inside an
already-notarized PwrDrvr bundle, which works because they carry the same Team
ID and hardened runtime; shipping one standalone would need a notarization step
that does not exist yet.
Before this can produce a signed build
Set up the two environments on
pwrdrvr/codex:apple-signingCSC_LINK,CSC_KEY_PASSWORDwindows-signingAZURE_TENANT_ID,AZURE_CLIENT_ID,AZURE_CLIENT_SECRETWIN_AZURE_SIGN_ACCOUNT,WIN_AZURE_SIGN_ENDPOINT,WIN_AZURE_SIGN_PUBLISHER_NAME,WIN_AZURE_SIGN_PROFILEValues are the same ones
pwrdrvr/grok-builduses; they are tabulated indocs/pwragent-distribution.md.Then apply the
ci:release-signinglabel to this PR to exercise the whole pipeline, signing included. Without the label onlypwragent-release-check.ymlruns.Unverified
The contract check and the YAML job graph were run locally; nothing else was. These are the parts most likely to need a second pass, in rough order of likelihood:
ubuntu-24.04/macos-15/windows-2022runner may run out of disk or exceed the 120-minute timeout. If so the fix is probablyswap-space/disk reclamation plussccache, or falling back to a self-hosted runner for the heavy targets.macos-15-intelavailability for this org.--bin codexwithoutbwrap. Upstream buildsbwrapfirst and embeds its digest. Skipping it should be fine, but nothing here proves the Linux binary behaves sanely without a bundledbwrap.refs/pull/<n>/mergeand environment protection. If either environment gets a branch rule, labeled PR runs will block on a reviewer instead of signing.🤖 Generated with Claude Code