feat(ci): ship releases without Apple signing credentials - #292
Open
hyperb1iss wants to merge 6 commits into
Open
hyperb1iss wants to merge 6 commits into
hyperb1iss wants to merge 6 commits into
Conversation
|
Warning Review limit reached
On-demand reviews are free for the next 5 days. After that, they cost $0.25 per reviewed file. Or wait 26 minutes for your next included review. View limit detailsLimit details: You’ve used the included review currently available. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (19)
Comment |
15 tasks
The renderer required all four platform digests plus both DMG digests, so a stable tag without signed macOS artifacts could not update the tap at all. Linux stanzas now always come from the published release; macOS stanzas come from the same release when it shipped the complete signed set, and are otherwise read back from the formula already in the tap with their own version line, the shape the tap carried at 0.5.1. The cask is only rendered when both DMGs exist. A release that publishes only part of the macOS set is still rejected, so the tap advances all of macOS or none of it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013dXbUNEe4yxrGhQLXbzRou
…ials The Release workflow refused to tag when any APPLE_* secret was missing, and the tag lane's credential gate, macOS matrix entries, and Homebrew job all assumed signed macOS artifacts exist. No Apple credentials are configured yet, so every release was blocked on macOS. release-credentials now probes the seven secrets and selects the release matrices from .github/release-matrix.json: macOS entries build only when every secret is present, and a missing one drops them with a warning instead of failing. The Release workflow reports the same status on dry runs and real cuts. update-homebrew reads the published assets and only tracks macOS when the whole signed set shipped, carrying the tap's current macOS build forward otherwise and refusing a partial set. create-release uploads onto an existing GitHub Release and the PyPI publish skips an already-published version, so re-dispatching the tag lane after the credentials land adds macOS to a release that shipped without it. Public CI still never publishes an unsigned macOS artifact. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013dXbUNEe4yxrGhQLXbzRou
…units Both packaged units carried CPUQuota=25% and MemoryMax=512M, and dist.sh copies that unit into the tarball, so the release installer, the deb, the AUR package, and Homebrew all shipped it. CPUQuota=25% is a quarter of one core, not a quarter of the machine, which starves a 60fps compositor plus in-process Servo on every packaged install, and the daemon idles near 330MB RSS, so the memory ceiling was an OOM kill waiting for a busy scene. The NixOS module already omitted both. Resource ceilings are a product baseline; the units now run unconstrained and rely on the watchdog and Restart=on-failure for runaway recovery. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013dXbUNEe4yxrGhQLXbzRou
The README, download page, and install guides told macOS readers to grab Hypercolor-<version>.dmg from the releases page, but no release since v0.3.2 has carried a macOS asset and the tap cask is pinned there. The pages now say macOS builds ship only when the signed lane runs and can lag Linux and Windows, point at the tap as the source of truth, and keep the DMG instructions for releases that did ship one. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013dXbUNEe4yxrGhQLXbzRou
…plate The hypercolor-app packaging tests asserted the macOS matrix entries inline in ci.yml and that the formula template carried no macOS version placeholder. Both moved: the entries live in .github/release-matrix.json so the credential probe can filter them, and the on_macos block carries its own version line so a Linux-only release can carry the tap's macOS build forward. rust-test gates both release builders, so these three assertions would have failed the very tag run the change exists to make possible. The template header now describes the carry-forward instead of claiming every platform renders from the same release. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013dXbUNEe4yxrGhQLXbzRou
A re-run that clobbered every artifact would replace the Linux and Windows assets with rebuilt files carrying new digests, because dist.sh does not produce byte-identical archives. The tap formula committed by the first run, the AUR and Nix pins, and anyone who verified a download would all break until a second publish wave landed. create-release now uploads only the assets the release does not already carry, so a re-run after the Apple credentials land adds the macOS set and leaves the rest untouched. RELEASING.md describes that behaviour instead of claiming the AUR and Nix jobs ignore a re-run. The two design docs that still listed the systemd caps as shipping config carry the retirement note. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013dXbUNEe4yxrGhQLXbzRou
hyperb1iss
force-pushed
the
nova/release-macos-optional
branch
from
September 15, 2026 20:34
cd7b4ea to
c5835e4
Compare
hyperb1iss
marked this pull request as ready for review
September 15, 2026 23:22
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.
What this changes
A stable release no longer needs Apple signing credentials to ship. The Release workflow reports missing
APPLE_*secrets instead of refusing to tag, the tag lane builds the macOS standalone tarballs and DMGs only when every secret is present, and the Homebrew job tracks macOS only when the release published the complete signed set, carrying the tap's current macOS build forward otherwise. Re-dispatching the tag lane after the credentials land adds the signed macOS artifacts to the same GitHub Release and advances the tap.The packaged systemd units also stop capping the daemon at
CPUQuota=25%andMemoryMax=512M, and the install pages stop promising a DMG on every release.Why
PR #285 made signed macOS a hard requirement of every release, and no Apple credentials exist yet (the Developer Program enrollment is pending), so 0.5.2 could not be cut at all. The dry run passed because the gate only ran on real cuts, so the failure would have surfaced after the rehearsal looked green.
CPUQuota=25%in systemd means a quarter of one core, not a quarter of the machine. That unit shipped through the release installer, the deb, the AUR package, and Homebrew (the NixOS module already omitted it), so every packaged install ran a 60fps compositor plus in-process Servo on a quarter core. The daemon idles near 330MB RSS, which leaves the 512M ceiling one busy scene away from an OOM kill. Performance ceilings are a product baseline, so the caps go rather than get raised.The README, download page, and both install guides told macOS readers to download
Hypercolor-<version>.dmgfrom the releases page, but no release since v0.3.2 carries a macOS asset and the tap cask is pinned there.🛠️ How it works
release-credentialsprobes the seven secrets and selects both release matrices from.github/release-matrix.json. Entries markedsigning: true(the four macOS lanes) are dropped when any secret is missing and the marker never reaches the matrix.build-native-appandbuild-releasetake theirincludefrom that output, so a credential-less run never schedules a macOS runner and never hits the signing wrapper that would exit 1. With every secret present the lanes are exactly what #285 defined.update-homebrewasks the GitHub Release which assets exist. All four macOS assets (two standalone tarballs, two DMGs) advance the formula'son_macosblock and the cask together; none keeps the tap's current macOS stanzas, read back from the live formula with their ownversionline; a partial set fails the job, so a broken macOS publish cannot advance the tap. The renderer enforces the same all-or-nothing rule on its CLI.create-releaseadds only the assets an existing release does not already carry, so a re-run leaves the published Linux and Windows digests alone (a rebuild is not byte-identical, and the tap formula, AUR, and Nix pins point at the first run's checksums). The PyPI publish skips an already-published version and npm already does, so the tag lane is safe to re-dispatch withrelease_artifacts: fullonce the secrets exist. Public CI still never publishes an unsigned macOS artifact in either mode; the unsigned--no-signbuild remains anoss-ci-*fixture.🧪 Validation
node --testoverrelease-workflow,macos-release,macos-ci-coverage,homebrew-formula, andresolve-release-version: 30 tests pass. The new tests execute the workflow shell directly. The credential probe runs against the real matrix file with secrets present and absent, and the test asserts which targets survive. The Homebrew checksum and render steps run against a fixture tap in three scenarios (full macOS set, Linux only, partial set) and the test checks the rendered formula, the untouched cask, and the refusal. The Release report step runs with complete and missing secrets.cargo test -p hypercolor-app --test packaging_tests: 53 pass. Three of them asserted the old inline matrix and the placeholder-free template; they now read the matrix file and the carry-forward template.rust-testgates both release builders, so these had to move with the workflow.actionlinton both workflows is clean; both parse as YAML.node --check scripts/homebrew-formula.mjspasses.just docs-buildbuilds 95 pages andcd docs && zola checkpasses.An independent verification agent reviewed the diff and re-ran the checks above. Its first pass failed on the three Rust assertions and on a re-run path that clobbered every asset; both are fixed in the last two commits and the notes below record the rest.
Not exercised: an actual tag run. The credential-less path is proven by executing the workflow shell locally, not by a GitHub run. The first real proof is the 0.5.2 dry run followed by the cut.
Added or updated tests
Added or updated docs (README, AGENTS.md, relevant spec, or guide)
just verifypasses locally (not applicable; no Rust changes)just denypasses (not applicable; no dependency changes)just ui-testandjust ui-buildpass (not applicable)just sdk-lint,just sdk-check, andjust sdk-buildpass (not applicable)just python-verifypasses (not applicable)just compat-checkpasses (not applicable)just docs-buildpasses (required for docs or README changes)cd docs && zola checkpasses (required for docs link/content changes)Packaging scripts were syntax-checked (required for
scripts/orpackaging/)just e2e-buildpasses with the normal Servo stack (not applicable)just e2e-build-cpupasses when validating the CPU smoke fallback (not applicable)just e2epasses against the Servo stack (not applicable)Tested on real hardware, simulator, or e2e harness (not applicable; workflow, packaging, and docs only)
Notes for reviewers
Start with the probe step in
release-credentialsand theDownload release tarballs and compute checksumsstep inupdate-homebrew; those two decide everything else. The matrix JSON keeps the exact entries #285 defined, including the multi-lineartifact-pathvalues, so the diff there is a move rather than a rewrite.The re-run path was the verifier's other catch: the first version clobbered every asset, which would have replaced the Linux and Windows files with different digests after the tap, AUR, and Nix had already pinned the originals. Uploading only missing assets keeps a re-run additive.
Where signing happens is a separate decision this PR does not make. #285 signs in public CI with repository secrets; spec 67 section 2 says Apple credentials live only in the proprietary release system. Both paths work with this change, because a signed macOS set published on the release is all the tap job looks for.
🤖 Generated with Claude Code
https://claude.ai/code/session_013dXbUNEe4yxrGhQLXbzRou