From 106450e7646f561a8b7eef0397041de5afa3a60a Mon Sep 17 00:00:00 2001 From: subencheng Date: Tue, 22 Sep 2026 20:09:01 -0700 Subject: [PATCH 1/2] Admit all four binary targets instead of queueing the fourth **Why** GoReleaser sizes its build semaphore from the CPU count. cmd/release.go does: ctx.Parallelism = runtime.GOMAXPROCS(0) if options.parallelism > 0 { ctx.Parallelism = options.parallelism } and internal/pipe/build/build.go passes that straight into the limiter: g := semerrgroup.New(ctx.Parallelism) macos-latest has 3 vCPUs and the binaries job builds four targets (linux amd64/arm64, darwin amd64/arm64), so the fourth waits for a free slot. This is measurable and near-universal. Across 30 sampled connector releases the gap between consecutive build starts is sharply bimodal: gaps 1->2 and 2->3 are at most 12.9ms (60 measurements), while gap 3->4 is 106-233s in 29 of 30 cases. Nothing falls in between. On baton-datadog the fourth target idled 11m40s, and the build stage took 13m13s of a 16m job. The single exception, baton-servicedesk-plus, admitted all four within 0.5ms on an identical runner image, image version, provisioner, workflow ref and caller config -- consistent with GitHub billing the standard macOS tier as "3-core or 4-core", i.e. a mixed fleet. **What this changes** - Passes -p 4 to the binaries GoReleaser invocation, overriding the CPU-derived default so all four targets start immediately. - Adds a step recording core count, CPU model and RAM. Without it a run cannot be read correctly: on a 4-core machine all four targets start regardless, which would mask the flag's effect entirely. Deliberately left alone: runs-on stays macos-latest, so this is measurable against the existing baseline with no billing change. Larger runners are not free for public repositories and 160 of the 521 baton repos are public, so the runner-size route forfeits a free tier that this change does not touch. **What this does not claim** This removes queueing, not CPU shortage. Four builds would share three cores rather than three sharing three; total CPU is unchanged. Measured locally, four cold cross-compiles of a connector need ~392 CPU-seconds and reach 8.2x parallelism when given 12 cores, with peak RSS under 1GB -- so the work is CPU-bound and genuinely wants more cores than this provides. The point is to separate the two effects. If -p 4 recovers most of the time, the fix is a flag. If it does not, the shortage is proven rather than assumed, which is the evidence the runner-size and job-split proposals currently lack. **Validation** - Parsed release.yaml with PyYAML; confirmed args, runs-on and step order. - Re-checked the GORELEASER_CURRENT_TAG pin on all four GoReleaser steps. - scripts/test-normalize-release-options.sh, test-derive-iam-role-name.sh, test-release-config-templates.py, go build ./... Not validated: no release has run with this flag. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/release.yaml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3225ddb..c935235 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -313,6 +313,16 @@ jobs: binaries_checksums: ${{ steps.output-checksums.outputs.checksums }} released_at: ${{ steps.release-meta.outputs.released_at }} steps: + # Records the core count so a run can be read correctly: GitHub bills the + # standard macOS tier as "3-core or 4-core", and a 4-core runner would admit + # all four targets even without -p, masking the flag's effect. + - name: Report runner hardware + shell: bash + run: | + echo "ncpu=$(sysctl -n hw.ncpu) logical=$(sysctl -n hw.logicalcpu) physical=$(sysctl -n hw.physicalcpu)" + echo "cpu=$(sysctl -n machdep.cpu.brand_string 2>/dev/null || echo unknown)" + echo "mem_bytes=$(sysctl -n hw.memsize)" + - name: Checkout caller repo uses: actions/checkout@v5 with: @@ -417,12 +427,15 @@ jobs: role-to-assume: arn:aws:iam::025044153841:role/${{ steps.role-names.outputs.gha_artifacts_role_name }} aws-region: us-west-2 + # -p 4: GoReleaser defaults its build semaphore to runtime.GOMAXPROCS(0) + # (cmd/release.go), which is 3 on macos-latest. With four targets the fourth + # queues behind the first three. Pinning to the target count admits them all. - name: Run GoReleaser uses: goreleaser/goreleaser-action@v6 with: workdir: _caller version: "~> v2.13" - args: release --clean --config ../_workflows/_generated/.goreleaser.binaries.yaml + args: release --clean -p 4 --config ../_workflows/_generated/.goreleaser.binaries.yaml env: GITHUB_TOKEN: ${{ secrets.RELENG_GITHUB_TOKEN }} GORELEASER_CURRENT_TAG: ${{ inputs.tag }} From 82350fe457738d5b408bab451ce24e1feb6594fd Mon Sep 17 00:00:00 2001 From: subencheng Date: Tue, 22 Sep 2026 21:09:03 -0700 Subject: [PATCH 2/2] Pin the binaries build semaphore to -p 3 Forces the queueing condition so its cost can be measured on a runner that would not otherwise exhibit it. GoReleaser defaults ctx.Parallelism to runtime.GOMAXPROCS(0), and the standard macOS fleet is mixed -- GitHub bills it as "3-core or 4-core". Measured across 30 connector releases, 29 admitted three of the four targets and queued the fourth for 106-233s, but baton-github-test consistently lands on 4-core machines and starts all four within 1.4ms. On that repo a higher limit is a no-op, so the queueing cost cannot be observed. Pinning to 3 reproduces the majority condition on any machine, making the two cases comparable on the same repo: -p 3 (this branch) vs default (4 slots on that hardware) A measured v0.1.141 run on macos-latest-xlarge reported ncpu=5 and completed building binaries in 124s, against a 99-100s baseline on macos-latest with all four targets already concurrent -- no improvement, because that connector was never queueing. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/release.yaml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c935235..72ee3fc 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -427,15 +427,17 @@ jobs: role-to-assume: arn:aws:iam::025044153841:role/${{ steps.role-names.outputs.gha_artifacts_role_name }} aws-region: us-west-2 - # -p 4: GoReleaser defaults its build semaphore to runtime.GOMAXPROCS(0) - # (cmd/release.go), which is 3 on macos-latest. With four targets the fourth - # queues behind the first three. Pinning to the target count admits them all. + # -p pins GoReleaser's build semaphore, which otherwise defaults to + # runtime.GOMAXPROCS(0) (cmd/release.go). The standard macOS fleet is mixed + # (GitHub bills it as "3-core or 4-core"), so the number of the four targets + # that run concurrently varies by whichever machine a release lands on. + # Pinning it makes the release reproducible instead of a hardware lottery. - name: Run GoReleaser uses: goreleaser/goreleaser-action@v6 with: workdir: _caller version: "~> v2.13" - args: release --clean -p 4 --config ../_workflows/_generated/.goreleaser.binaries.yaml + args: release --clean -p 3 --config ../_workflows/_generated/.goreleaser.binaries.yaml env: GITHUB_TOKEN: ${{ secrets.RELENG_GITHUB_TOKEN }} GORELEASER_CURRENT_TAG: ${{ inputs.tag }}