Skip to content

Commit 8ac3171

Browse files
dkijaniaclaude
andcommitted
release: musl static build + publish to 5 codenames
Two coupled changes: * Build the four release binaries with `--target x86_64-unknown-linux-musl`. Static linking removes the glibc floor entirely, so one .deb runs on bullseye (glibc 2.31) through noble (2.39) without "version GLIBC_X.Y not found" surprises. Possible because all four crates already use rustls (no OpenSSL linkage to break under musl). * Loop the upload across `bullseye focal jammy noble bookworm`. Same .deb gets registered under each codename in `packages.o1test.net`; deb-s3 happily handles the repeated upload, and the underlying object in S3 is identical (just referenced from five Packages indices). To keep build-deb.sh from caring whether the binaries live under `target/release/` or `target/<triple>/release/`, it now respects an optional CARGO_TARGET env var that selects the subdir. Default behaviour (no env var) is unchanged, so the package workflow keeps working as-is — only release.yml opts into the musl path. Release-notes body updated: the install snippet now leads with "replace <CODENAME> with one of: bullseye focal jammy noble bookworm" instead of pinning bookworm, and explicitly mentions the build is musl-static so users understand why one .deb works everywhere. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a42d82e commit 8ac3171

2 files changed

Lines changed: 80 additions & 30 deletions

File tree

.github/workflows/release.yml

Lines changed: 55 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -40,27 +40,33 @@ jobs:
4040
with:
4141
submodules: recursive
4242

43-
- name: Install Rust
43+
- name: Install Rust + musl target
44+
# Static-linking against musl removes the glibc floor entirely:
45+
# one binary that runs on any Linux x86_64. The four crates
46+
# already use rustls (no OpenSSL link), so musl Just Works.
4447
uses: dtolnay/rust-toolchain@stable
48+
with:
49+
targets: x86_64-unknown-linux-musl
4550

4651
- name: Cache cargo
4752
uses: Swatinem/rust-cache@v2
4853
with:
49-
# Cargo workspaces this build touches. Without this the
50-
# action looks for a Cargo.toml at the repo root, which we
51-
# don't have, and skips caching with a confusing error.
5254
workspaces: |
5355
release-manager
5456
mina-bench-upload
5557
buildkite-cache-manager
5658
deb-toolkit
57-
key: release-${{ github.ref_name }}
59+
# Cache key includes the target triple so the musl build's
60+
# cache doesn't collide with the default-host build cache
61+
# used elsewhere.
62+
key: release-musl-${{ github.ref_name }}
5863

59-
- name: Install Debian build tools
64+
- name: Install Debian + musl build tools
6065
run: |
6166
sudo apt-get update
6267
sudo apt-get install -y --no-install-recommends \
63-
fakeroot dpkg-dev build-essential pkg-config libssl-dev
68+
fakeroot dpkg-dev build-essential pkg-config libssl-dev \
69+
musl-tools
6470
6571
- name: Strip leading `v` from tag for the Debian version string
6672
# Debian version strings are looser than semver but we still
@@ -69,17 +75,26 @@ jobs:
6975
id: ver
7076
run: echo "version=${GITHUB_REF_NAME#v}" >> "${GITHUB_OUTPUT}"
7177

72-
- name: Build the four release binaries
73-
# Same lock-file policy as the package workflow: in-tree crates
74-
# use `--locked`; the deb-toolkit submodule's lockfile is
75-
# gitignored upstream so we let cargo resolve it fresh.
78+
- name: Build the four release binaries (musl static)
79+
# `--target x86_64-unknown-linux-musl` produces fully static
80+
# binaries — no glibc dependency, so a single .deb is
81+
# installable on bullseye / focal / jammy / noble / bookworm
82+
# alike. The lock-file policy is the same as package.yml:
83+
# in-tree crates use --locked, the deb-toolkit submodule
84+
# gitignores its lockfile upstream so we let cargo resolve.
85+
env:
86+
TARGET: x86_64-unknown-linux-musl
7687
run: |
77-
(cd release-manager && cargo build --release --locked)
78-
(cd mina-bench-upload && cargo build --release --locked)
79-
(cd buildkite-cache-manager && cargo build --release --locked)
80-
(cd deb-toolkit && cargo build --release)
88+
(cd release-manager && cargo build --release --locked --target "$TARGET")
89+
(cd mina-bench-upload && cargo build --release --locked --target "$TARGET")
90+
(cd buildkite-cache-manager && cargo build --release --locked --target "$TARGET")
91+
(cd deb-toolkit && cargo build --release --target "$TARGET")
8192
8293
- name: Assemble .deb via deb-toolkit
94+
# build-deb.sh respects CARGO_TARGET to look in
95+
# `target/<triple>/release/` instead of `target/release/`.
96+
env:
97+
CARGO_TARGET: x86_64-unknown-linux-musl
8398
run: packaging/build-deb.sh "${{ steps.ver.outputs.version }}" ./out
8499

85100
- name: Sanity-check the produced .deb
@@ -104,9 +119,14 @@ jobs:
104119
105120
## Install
106121
122+
The .deb is a fully static musl build — one binary that runs on
123+
\`bullseye\`, \`focal\`, \`jammy\`, \`noble\`, and \`bookworm\`. Pick
124+
the codename matching your distro for the apt source line:
125+
107126
\`\`\`bash
108-
# Debian, via the apt repo (preferred):
109-
echo "deb [trusted=yes] http://packages.o1test.net bookworm stable" \\
127+
# Debian, via the apt repo (preferred). Replace <CODENAME> with
128+
# one of: bullseye focal jammy noble bookworm
129+
echo "deb [trusted=yes] http://packages.o1test.net <CODENAME> stable" \\
110130
| sudo tee /etc/apt/sources.list.d/mina-release-toolkit.list
111131
sudo apt-get update && sudo apt-get install mina-release-toolkit
112132
@@ -150,15 +170,25 @@ jobs:
150170
- name: Install deb-s3
151171
run: sudo gem install deb-s3
152172

153-
- name: Publish .deb to packages.o1test.net
173+
- name: Publish .deb to packages.o1test.net (all codenames)
174+
# The musl static .deb runs on every Debian/Ubuntu release we
175+
# care about (bullseye through noble), so we publish the same
176+
# artifact under each codename. deb-s3 happily re-uploads to
177+
# multiple codenames as separate logical entries even though
178+
# the underlying file in S3 is identical.
154179
env:
155180
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
156181
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
157182
run: |
158-
deb-s3 upload \
159-
--bucket=packages.o1test.net \
160-
--s3-region=us-west-2 \
161-
--codename=bookworm \
162-
--component=stable \
163-
--preserve-versions \
164-
./out/mina-release-toolkit_${{ steps.ver.outputs.version }}_amd64.deb
183+
set -euo pipefail
184+
DEB="./out/mina-release-toolkit_${{ steps.ver.outputs.version }}_amd64.deb"
185+
for codename in bullseye focal jammy noble bookworm; do
186+
echo "=== uploading to ${codename}/stable ==="
187+
deb-s3 upload \
188+
--bucket=packages.o1test.net \
189+
--s3-region=us-west-2 \
190+
--codename="${codename}" \
191+
--component=stable \
192+
--preserve-versions \
193+
"${DEB}"
194+
done

packaging/build-deb.sh

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,31 @@ OUTPUT_DIR="$2"
2929
ARCH="${ARCH:-amd64}"
3030

3131
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
32-
DEB_TOOLKIT_BIN="${REPO_ROOT}/deb-toolkit/target/release/deb-toolkit"
32+
33+
# When CARGO_TARGET is set (e.g. `x86_64-unknown-linux-musl` for a
34+
# static glibc-free build), cargo places its output under
35+
# `target/<TRIPLE>/release/` instead of the default `target/release/`.
36+
# We follow the same convention for all four crates so a single env
37+
# var swaps "default native build" for "musl static build" without
38+
# changing any other code.
39+
TARGET_SUBDIR="release"
40+
if [[ -n "${CARGO_TARGET:-}" ]]; then
41+
TARGET_SUBDIR="${CARGO_TARGET}/release"
42+
fi
43+
44+
bin_path() {
45+
# $1 = crate dir, $2 = binary name
46+
echo "${REPO_ROOT}/$1/target/${TARGET_SUBDIR}/$2"
47+
}
48+
49+
DEB_TOOLKIT_BIN="$(bin_path deb-toolkit deb-toolkit)"
3350

3451
if [[ ! -x "${DEB_TOOLKIT_BIN}" ]]; then
3552
echo "deb-toolkit release binary not found at ${DEB_TOOLKIT_BIN}." >&2
3653
echo "Run 'cargo build --release' in deb-toolkit/ first." >&2
54+
if [[ -n "${CARGO_TARGET:-}" ]]; then
55+
echo "(CARGO_TARGET=${CARGO_TARGET} is set; pass --target ${CARGO_TARGET} to cargo build.)" >&2
56+
fi
3757
exit 1
3858
fi
3959

@@ -43,10 +63,10 @@ fi
4363
STAGING="$(mktemp -d)"
4464
trap 'rm -rf "${STAGING}"' EXIT
4565

46-
install -D -m 0755 "${REPO_ROOT}/release-manager/target/release/release-manager" "${STAGING}/usr/bin/release-manager"
47-
install -D -m 0755 "${REPO_ROOT}/mina-bench-upload/target/release/mina-bench-upload" "${STAGING}/usr/bin/mina-bench-upload"
48-
install -D -m 0755 "${REPO_ROOT}/buildkite-cache-manager/target/release/buildkite-cache-manager" "${STAGING}/usr/bin/buildkite-cache-manager"
49-
install -D -m 0755 "${DEB_TOOLKIT_BIN}" "${STAGING}/usr/bin/deb-toolkit"
66+
install -D -m 0755 "$(bin_path release-manager release-manager)" "${STAGING}/usr/bin/release-manager"
67+
install -D -m 0755 "$(bin_path mina-bench-upload mina-bench-upload)" "${STAGING}/usr/bin/mina-bench-upload"
68+
install -D -m 0755 "$(bin_path buildkite-cache-manager buildkite-cache-manager)" "${STAGING}/usr/bin/buildkite-cache-manager"
69+
install -D -m 0755 "${DEB_TOOLKIT_BIN}" "${STAGING}/usr/bin/deb-toolkit"
5070

5171
mkdir -p "${OUTPUT_DIR}"
5272

0 commit comments

Comments
 (0)