Skip to content

Run the macOS binaries job on macos-latest-xlarge - #127

Closed
Bencheng21 wants to merge 3 commits into
mainfrom
test-macos-xlarge-runner
Closed

Bencheng21 wants to merge 3 commits into
mainfrom
test-macos-xlarge-runner

Conversation

@Bencheng21

@Bencheng21 Bencheng21 commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Run goreleaser-binaries on a larger Apple Silicon runner.

macos-latest has 3 vCPUs and GoReleaser sizes its build semaphore from
runtime.GOMAXPROCS(0), so the fourth darwin target queues behind the first
three. macos-latest-xlarge (6-core M1) clears the queue.

Measurements

goreleaser-binaries wall-clock in baton-github-test, successful runs only:

runner n avg min max
macos-latest-xlarge 2 3.99 min 205s 274s
macos-latest (current) 34 5.29 min 218s 462s
macos-latest-large (Intel) 1 6.87 min 412s 412s
macos-26-intel 1 12.82 min 769s 769s

~24% faster than the current default, and the Intel tiers are both worse than
the standard runner, so they are benchmark-only.

Cost

This is not a free change. Larger runners are billed on public repos — they get
no free-minutes allowance — so the 77% of macOS release minutes that currently
cost nothing become billable.

From the August usage report, org-wide release.yaml:

minutes cost
today, macos-latest 2,239 $138.82 gross → $31.31 net (1,734 min free)
macos-latest-xlarge @ $0.16/min ~1,690 (24% faster) ~$270/mo, none free

goreleaser-binaries is 40% of goreleaser wall-time but 84% of its cost, since
it is the only job on macOS.

Changes

  • macos_runner input, default macos-latest-xlarge.
  • Allowlist validation in validate-inputs. This job holds the Apple signing
    certificate and assumes the artifacts AWS role, so the runner label is a trust
    decision; only GitHub-hosted macOS labels are accepted.
  • Report runner hardware diagnostic step recording core count and CPU brand,
    so the tier is measured rather than inferred.

Rollout

Tagged v4.5.0. Callers pin @v4, so this reaches all 244 baton repos only
once the floating v4 tag is moved — deliberately a separate step.

Bencheng21 and others added 3 commits September 22, 2026 17:23
**Why**

The release critical path is goreleaser-binaries, and its dominant cost is Go
compilation. macos-latest has 3 vCPUs and GoReleaser builds one target per core,
so with four targets the fourth queues behind the first three.

This is measurable and universal. Across the most recent successful release of
nine connectors, exactly three targets start together and macos-arm64 waits:

    connector          4th target starts   macos-amd64 post-hook   delta
    baton-hubspot                   108s                    108s    0.1s
    baton-snowflake                 117s                    118s    0.8s
    baton-slack                     160s                    162s    2.9s
    baton-salesforce                162s                    165s    2.4s
    baton-zoom                      169s                    170s    1.0s
    baton-github                    176s                    177s    0.9s
    baton-jira                      192s                    194s    1.9s
    baton-aws                       200s                    201s    1.1s
    baton-okta                      331s                    335s    3.7s

The gon post-hook fires the instant a build finishes, so the fourth target
provably starts when the first frees its slot rather than running concurrently.

**What this changes**

- Adds a macos_runner input, defaulting to macos-latest-xlarge (Apple Silicon M2,
  5 vCPU). Five slots for four targets removes the queueing entirely.
- validate-inputs restricts the value to GitHub-hosted Apple Silicon labels. This
  job holds the Apple signing certificate and assumes the artifacts AWS role, so
  the runner it lands on is a trust decision; a free-form label would let a caller
  point it at a runner they control.

Intel labels are deliberately excluded. macos-latest-large is the 12 vCPU option,
but it would change the codesigning host architecture and move the Homebrew prefix
from /opt/homebrew to /usr/local, which the gon install step depends on.

**What this does not claim**

The saving is not predicted here. The logs show when each build starts but not when
the two linux builds finish, so per-core scaling cannot be derived from them; the
only defensible claim is that the queueing is real and five slots removes it.
Treat this as the experiment that measures it.

Larger runners bill at a higher per-minute rate, and this job runs on every
connector release, so the default should be reviewed against actual spend once the
compile phase has been measured on the new runner.

**Validation**

- Parsed .github/workflows/release.yaml with PyYAML; confirmed the input default
  and that the job resolves runs-on from it.
- Exercised the allowlist against macos-latest, macos-latest-xlarge,
  macos-15-xlarge (accepted) and macos-latest-large, macos-13, self-hosted, and a
  shell-injection attempt (rejected).
- scripts/test-normalize-release-options.sh, scripts/test-derive-iam-role-name.sh,
  scripts/test-release-config-templates.py, go build ./...

Not validated: no release has been run on the new runner.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Records core count, CPU model and RAM at the top of goreleaser-binaries so the
build semaphore size stops being an inference.

GoReleaser sets ctx.Parallelism from runtime.GOMAXPROCS(0) (cmd/release.go:133)
and uses it as the build semaphore (internal/pipe/build/build.go:43), so the
runner's core count decides how many of the four targets compile at once. Across
30 sampled connector releases, 29 admitted three targets and queued the fourth
for 106-233s; one (baton-servicedesk-plus) admitted all four within 0.5ms on the
same runner image, version and provisioner. GitHub bills the standard macOS tier
as "3-core or 4-core", so a mixed fleet is the surviving explanation, but no
release log records the actual hardware.

This step costs a second and makes the correlation measurable.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The macOS binaries job holds the signing certificate, so the runner label
stays allowlisted. macos-latest-large is Intel rather than Apple Silicon,
which moves the Homebrew prefix and the codesigning host, so it is allowed
for benchmarking runs but is not a release default.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Bencheng21 Bencheng21 closed this Sep 23, 2026
@Bencheng21 Bencheng21 changed the title Test macos xlarge runner Run the macOS binaries job on macos-latest-xlarge Sep 23, 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