Skip to content
Releasing the bench CLI

Releasing the bench CLI

A release publishes prebuilt bench binaries for macOS and Linux (x86-64 and arm64) to a GitLab Release. GoReleaser drives it from .goreleaser.yml; the jobs live in .gitlab-ci.yml under the release stage.

One-time setup: the publish token

release:goreleaser needs a token with api scope to create the Release and upload assets. It reads one from the project’s GitLab Secrets Manager as goreleaser_token.

To provision the token, a project owner:

  1. Creates a project access token named goreleaser, with the Developer role and the api scope. Developer is enough to create a Release and publish to the package registry. The existing danger token is configured exactly this way; copy it.
  2. Adds it under Secure > Secrets manager with the name goreleaser_token and Branch set to v*. The job only runs on tag pipelines, where CI_COMMIT_BRANCH is unset, so a secret scoped to main never resolves and the job fails with a 403. v* matches the release tags and nothing else.

Project access tokens expire, and a lapsed one fails the release job at tag time rather than before. GitLab emails project Maintainers and Owners ahead of the token’s expiry, so when the warning arrives, rotate the token and overwrite the secret’s value.

Cutting a release

The binary reports the version from the git tag. The crate manifests don’t affect it, but keep them in step so the source matches the release.

  1. In a merge request, bump version in cli/Cargo.toml and config/Cargo.toml, then run cargo update -w to refresh Cargo.lock. Merge it; the merge commit is what you tag in step 3.

  2. Check that the mock release is green on main. It runs on merge requests touching .goreleaser.yml, .gitlab-ci.yml, or .mise.toml, and builds every archive without publishing. To run it locally on a macOS host:

    goreleaser release --snapshot --clean --skip=publish
  3. Create and push the tag on the bump MR’s merge commit:

    git tag vX.Y.Z <merge-commit-sha>
    git push origin vX.Y.Z
  4. Watch release:goreleaser in the tag pipeline. It builds all four targets and uploads the archives plus checksums.txt.

  5. Verify the published artifacts:

    mise x gitlab:gitlab-org/lab-bench/bench@X.Y.Z -- bench --version

    It should print the tagged version, since the release build stamps BENCH_VERSION from the tag. Any other build reports 0.0.0-dev.

Why the release runs on macOS

The darwin targets link against the macOS SDK, which only Xcode provides; cargo-zigbuild supplies the Linux linker from that same host. So one macOS runner builds all four targets, while a Linux runner could only build two. Splitting the build across two runners and merging the artifacts into a single Release requires GoReleaser Pro.

The tradeoff is a dependency on saas-macos-medium-m1, which is in beta with documented capacity limits. If that pool is exhausted at tag time, retry the job; the tag already exists, so nothing needs recreating.

Notarization

The macOS binaries are not notarized, which needs a paid Apple Developer ID. Downloading them through a browser therefore trips Gatekeeper. mise and curl do not set the quarantine attribute, so the documented install path avoids it entirely.

Last updated on