Skip to content

build: Linux packages, and the Steadybit apt and yum repositories - #75

Merged
achoimet merged 12 commits into
mainfrom
build/linux-packages
Sep 29, 2026
Merged

achoimet merged 12 commits into
mainfrom
build/linux-packages

Conversation

@achoimet

Copy link
Copy Markdown
Member

Adds .deb and .rpm packages for the CLI, with publishing to Steadybit's own apt/yum repositories at packages.steadybit.com (the ones the agent comes from) ready to switch on.

What's in it

  • goreleaser nfpms: a steadybit-cli package, named like steadybit-agent; the command is still steadybit. It holds:

    • /usr/bin/steadybit;
    • bash, zsh and fish completions in the distributions' standard locations;
    • the license.

    The files are steadybit-cli_{amd64,arm64}.{deb,rpm} with no version in the name, so the releases/latest/download/… URLs stay stable.

  • Signed with the agent's key (MAVEN_GPG_PRIVATE_KEY / _PASSWORD, org secrets this repo can read). A local snapshot builds unsigned.

  • Release job: attaches the packages to the GitHub release, and would publish them to deb-public / yum-public through steadybit/.github/actions/gar-upload-linux-packages, the same action the extensions use.

  • New linux-packages job (every run except tags and the daily schedule):

    • builds a snapshot;
    • installs the .deb on Ubuntu and the .rpm in a fedora:latest container, and runs steadybit -V;
    • uploads to deb-dev / yum-dev on main and on manual runs, as the extensions do.

    Pull requests build unsigned packages and upload nothing.

Blocked on Google Cloud access. A manual run of this branch built, signed, installed and ran both packages. The upload was refused:

Permission 'iam.serviceAccounts.getAccessToken' denied

The workload identity provider behind GCP_ARTIFACT_REGISTRY_IDENTITY_PROVIDER doesn't trust steadybit/cli; it evidently allows specific repositories. Both uploads therefore run only when the repository variable PUBLISH_LINUX_PACKAGES is true, so merging breaks neither main nor releases. To switch on:

  1. A Google Cloud admin gives steadybit/cli access to the upload service account: a roles/iam.workloadIdentityUser binding for the repository's principal set, or an entry in the provider's attribute condition, as done for the extensions.
  2. Set PUBLISH_LINUX_PACKAGES=true in this repository's variables. Start CI by hand on main to test the upload against the dev repositories.
  3. Then add the repository installs to the README:
    # Debian, Ubuntu
    sudo mkdir -p /etc/apt/keyrings
    curl -fsSL https://europe-west1-apt.pkg.dev/doc/repo-signing-key.gpg | sudo tee /etc/apt/keyrings/steadybit.asc >/dev/null
    printf 'Types: deb\nURIs: https://packages.steadybit.com\nSuites: deb-public\nComponents: main\nSigned-By: /etc/apt/keyrings/steadybit.asc\n' | sudo tee /etc/apt/sources.list.d/steadybit.sources >/dev/null
    sudo apt-get update && sudo apt-get install steadybit-cli
    # Fedora, RHEL, Amazon Linux
    printf '[steadybit]\nname=steadybit\nbaseurl=https://packages.steadybit.com/yum-public\nenabled=1\ngpgcheck=0\n' | sudo tee /etc/yum.repos.d/steadybit.repo >/dev/null
    sudo dnf install steadybit-cli
    These are the repository definitions get.steadybit.com/agent-linux.sh writes.

Until then, the README documents installing the attached .deb/.rpm.

Testing

  • goreleaser check passes.
  • A local snapshot contains the files listed above, and its control data is right (package, maintainer, homepage).
  • In CI: packages built and signed, installed and run on Ubuntu 24.04 and Fedora.
  • The signing passphrase goes in NFPM_PASSPHRASE: the extensions' NFPM_DEFAULT_PASSPHRASE only applies to package configs without an id.

Linux users had Homebrew, a download or go install, none of which their system
keeps up to date. goreleaser now builds signed `steadybit-cli` .deb and .rpm
packages, with shell completions, attaches them to every release, and a stable
release publishes them to packages.steadybit.com next to the agent's packages,
with the same signing key and upload action the extensions use.

A new job builds the packages on every other run, installs the .deb on Ubuntu
and the .rpm on Fedora and runs them. On main, and when started by hand, it also
uploads them to the dev repositories, so the upload is exercised before a
release depends on it. Pull requests build them unsigned and upload nothing.
…reads

goreleaser reads NFPM_<ID>_PASSPHRASE and then NFPM_PASSPHRASE. The
extensions' packages have no id, hence their NFPM_DEFAULT_PASSPHRASE; the CLI's
are named steadybit, so the generic variable is the one that reaches them.
The workload identity provider the extensions upload through does not trust
steadybit/cli yet, so the upload is refused. Both uploads now wait for the
repository variable PUBLISH_LINUX_PACKAGES, and main and releases keep working
until then: the packages are still built, tested and attached to the release.
The heading had been renamed to v6.1.0, which moved the v6.0.1 fix into the next release's
notes. The Linux packages get their own v6.1.0 section above it.
…ead it

Their zsh only looks in /usr/share/zsh/site-functions, so the rpm's completion in
vendor-completions, which is Debian's directory, was never loaded. The deb keeps
vendor-completions.
The same, shorter than the conditional on .Env it replaces in both places.
All snapshots were 6.0.2-next, so after the first upload the dev repositories rejected
each later one, as updated packages must bear a new version, and the upload still
reported success. The commit timestamp makes each version newer than the last, as in
the extensions: the deb is 6.0.2~<timestamp>-next and the rpm 6.0.2~<timestamp>_next-1,
both sorting before the 6.0.2 release.
The signing key was written to gpg.key in the checkout, and goreleaser refuses to
release from a tree with untracked files, so every tag would have failed. Both jobs now
write it to $RUNNER_TEMP and remove it after goreleaser, whatever the outcome, and
/gpg.key is git-ignored in case it ever lands in the checkout again.

The public upload ran before the major tag was moved, so a failing upload left v6 where
it was and skipped verify-action. It moves to a job of its own after the release, which
downloads the signed packages from it, installs the amd64 .deb and checks that it reports
the tag's version before uploading: the install checks otherwise only ever ran on
unsigned snapshots.

The production key signed snapshots of any branch started by hand. Only main is signed
and uploaded to the dev repositories now; other refs build unsigned and upload nothing.
And, as docker-build, linux-packages waits for api-compatibility, so nothing reaches the
dev repositories from a build whose checks fail.
…release

Without -f, curl saves a 404 page as the package and apt or dnf then fails on it with a
confusing error. Releases before v6.1.0 carry no packages.
@achoimet
achoimet merged commit c48a94e into main Sep 29, 2026
10 checks passed
@achoimet
achoimet deleted the build/linux-packages branch September 29, 2026 13:26
@github-actions github-actions Bot locked and limited conversation to collaborators Sep 29, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant