Skip to content

ci(release): cut macOS/web build time in release pipeline - #271

Merged
dviejokfs merged 3 commits into
mainfrom
perf/release-pipeline-speedup
Jul 11, 2026
Merged

dviejokfs merged 3 commits into
mainfrom
perf/release-pipeline-speedup

Conversation

@dviejokfs

@dviejokfs dviejokfs commented Jul 10, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • build-darwin-amd64 cross-compiles x86_64-apple-darwin from an Apple Silicon runner (macos-14) instead of running natively on macos-15-intel. On the last real release (v0.1.0-beta.42), the Intel job took 72m46s vs 40m52s for the arm64 job — GitHub's Intel macOS pool is smaller/older hardware. openssl (via openssl-src, vendored) and jemalloc (via cc-rs) already build from source per-target, so there's no system-lib arch-mismatch risk cross-linking. Validated: the cross-compiled job completed in 42m33s in the dry-run below, and the resulting binary runs correctly.
  • Added a build-web-assets job that builds the web console dist/ + captcha WASM once (on ubuntu-latest) and uploads it as an artifact, instead of each of the 4 platform jobs independently running bun install + wasm-pack + rsbuild build for identical, platform-independent output. Each platform job now downloads the artifact and sets SKIP_WEB_BUILD=1 so crates/temps-cli/build.rs embeds the pre-built dist/ instead of rebuilding it. Measured redundant cost of the wasm-pack step alone (per job, last release): Linux amd64 1m55s, Linux arm64 1m33s, macOS arm64 3m19s, macOS Intel 7m26s — now paid once instead of 4x.
  • Three follow-on fixes, all found by actually running workflow_dispatch --dry_run to validate the above (all pre-existing bugs, unrelated to the perf change, but blocking a safe/complete dry-run):
    1. create-release always called gh release create, so a dry-run against a branch would mint a real GitHub Release named after that branch.
    2. build-and-push-docker's push was hardcoded true (unlike the sandbox/gateway image jobs, which already gate on dry_run), so any workflow_dispatch — dry-run or not — overwrote the real ghcr.io/.../temps:beta-linux-{amd64,arm64} tags, which create-docker-manifest then merges into the :beta channel tag operators can pin to.
    3. VERSION="${GITHUB_REF#refs/tags/v}" (3 call sites) only strips the tag prefix on a real tag push; on workflow_dispatch it left a /-containing branch ref in VERSION, which crashed sed in the Homebrew formula step and would've produced invalid Docker tags in the other two sites.

Expected effect: total release wall-clock drops from ~72m (bounded by the old Intel job) to ~42m (bounded by the darwin jobs, both now similar), plus removes ~14min of aggregate redundant CI compute across the 4 platform jobs.

Test plan

  • YAML validated locally
  • Validated end-to-end via workflow_dispatch --dry_run=true:
    • First run (29087021926): all 4 platform builds + web-assets succeeded (darwin-amd64 cross-compiled in 42m33s, darwin-arm64 in 43m12s); surfaced the create-release/build-and-push-docker/VERSION bugs above.
    • Second run (29089590515, after fixing those): fully green, all 16 jobs succeeded, Create Docker Manifest correctly skipped. Confirmed via logs that create-release hit the dry-run guard and did not call gh release create. Confirmed via gh release list that no spurious release exists on the repo.
  • Confirmed temps --version works on the cross-compiled macOS amd64 binary: downloaded the artifact, verified its sha256, confirmed via file it's a genuine Mach-O 64-bit executable x86_64, and ran it under Rosetta — temps-cli 0.1.0-beta.43-0d954d8 built 2026-07-10 11:16:53 UTC.

- build-darwin-amd64 now cross-compiles x86_64-apple-darwin from an
  Apple Silicon runner (macos-14) instead of running natively on
  macos-15-intel. GitHub's Intel macOS pool measured ~2x the
  wall-clock of the arm64 pool for this job (72m46s vs 40m52s on the
  last release). OpenSSL (openssl-src) and jemalloc build from source
  per-target already, so there's no arch-mismatch risk cross-linking.
- Add a build-web-assets job that builds the web console dist/ and
  captcha WASM once (on ubuntu-latest) and uploads it as an artifact,
  instead of every one of the 4 platform jobs independently running
  bun install + wasm-pack + rsbuild build for identical,
  platform-independent output. Each platform job now downloads the
  artifact and sets SKIP_WEB_BUILD=1 so build.rs embeds the
  pre-built dist instead of rebuilding it.
@github-actions

github-actions Bot commented Jul 10, 2026 •

Copy link
Copy Markdown

📓 Changelog preview

This is what your commits will add to the generated CHANGELOG.md at release time (via git-cliff). Do not edit CHANGELOG.md by hand — it is generated from your Conventional Commit messages.

## [Unreleased]

### CI

- **release:** Cut macOS/web build time in release pipeline

### Fixed

- **release:** Make workflow_dispatch dry-run actually safe
- **release:** Avoid slash-containing VERSION breaking workflow_dispatch runs

Found while trying to validate the perf changes in this PR via a
workflow_dispatch dry-run: the pipeline's own comment promises dry-run
'skip pushes, only build to verify the pipeline works', but two jobs
didn't honor that.

- create-release always ran 'gh release create', so a dry-run dispatch
  against a branch would mint a real GitHub Release object named after
  that branch.
- build-and-push-docker's push was hardcoded to true (unlike the
  sandbox/gateway image jobs, which already gate on dry_run), so any
  workflow_dispatch -- dry-run or not -- overwrote the real
  ghcr.io/.../temps:beta-linux-{amd64,arm64} tags, which
  create-docker-manifest then merges into the :beta channel tag
  operators can pin to.

Gate both behind the same dry_run check the sandbox/gateway jobs
already use, and skip create-docker-manifest entirely on a dry-run
since its source tags won't exist.
…ch runs

Found by actually running the dry-run triggered to validate the
previous two commits: the run's 4 build jobs (including the
cross-compiled darwin-amd64 target) all succeeded, but create-release
crashed one step later --

  sed: -e expression #1, char 20: unknown option to `s'

VERSION=${GITHUB_REF#refs/tags/v} only strips the tag prefix on a
real tag push. On workflow_dispatch, GITHUB_REF is refs/heads/<branch>,
which doesn't match that prefix, so VERSION is left as the literal
ref path -- e.g. 'refs/heads/perf/release-pipeline-speedup'. The
embedded '/' then collides with sed's own 's/.../.../ ' delimiter in
the Homebrew formula step, and would also produce an invalid (slash
containing) Docker tag component in the two 'Extract version' steps
that feed image tags.

Same fix at all 3 sites: workflow_dispatch gets a synthetic
dryrun-<run_id> version instead. Tag-push behavior is unchanged.
@dviejokfs
dviejokfs merged commit 8900d1b into main Jul 11, 2026
32 checks passed
@dviejokfs
dviejokfs deleted the perf/release-pipeline-speedup branch July 20, 2026 13:40
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