- Add build/register for a delegate to record each archive in the tag's release with radicle-artifact, from their own machine - Build the explorer bundle with config/default.json in build/register, and register and seed it as a collection in the same release - Record the CI build that fetch leaves in artifacts/; make build drop it - Add build/attest for other delegates to attest a matching build - Document registration, attestation and how to verify a download
8.8 KiB
Release Process
radicle-httpd and radicle-search are released together from this
workspace: a single tag, a single changelog, and one build run that produces
artifacts for both binaries. They share the same version number, set by the
release tag. On files.radicle.dev each binary gets its own release
folder — releases/radicle-httpd/<version>/ and, as a sibling,
releases/radicle-search/<version>/ — so existing radicle-httpd download URLs
are unaffected and radicle-search is downloaded independently.
The release tooling lives in crates/radicle-httpd/build/.
Scope
Releases cover only the radicle-httpd and radicle-search binaries. The
web front-end (radicle-explorer) is not released this way: it is deployed
continuously (rolling release) and must always remain compatible with the latest
radicle-httpd/radicle-search release. A release also registers the
frontend bundle of the tagged commit with radicle-artifact, see
Publish.
Versioning
Versions follow semantic versioning. The version covers
the HTTP API, the CLI and the config: bump the minor version for additions, and
the major version for removals or changes. Before 1.0, 0.y counts as the
major, so bump 0.y.z to 0.y.(z+1) for additions and to 0.(y+1).0 for
removals or changes. The release tag sets the version; do not change it in
Cargo.toml. See ADR 0001
for which releases explorer supports.
Prerequisites
- Git signing configured via SSH:
git config set gpg.format ssh git config set user.signingKey "$(rad self --ssh-key)" - Working
podmansetup (see Podman Setup below), or Docker - Required tools:
podmanordocker,rad,rad-artifact,sha256sum,curl,jq,ssh,scp,ssh-keygen,node,npm. Installrad-artifactwith:curl -sSf https://files.radicle.dev/releases/radicle-artifact/install | sh - To download the CI build: a Buildkite API token with
read_buildsandread_artifacts
Prepare
Normal patches add their highlights to ## Unreleased in
CHANGELOG.md. Note in each entry whether the change belongs to
radicle-httpd or radicle-search.
Release
-
Update
master:git switch master git pull --ff-only rad master -
Make the release commit. The script renames
## Unreleasedto the version inCHANGELOG.mdanddocs/api-changes.md, and adds a new empty## Unreleasedto each:crates/radicle-httpd/build/prepare <version>Check the diff. Then add the API changes from
docs/api-changes.mdto the new section inCHANGELOG.md. If the release bumps the major, set the target date to drop the previous major in## Supportofdocs/api-changes.md, three months from today. Then commit:git commit -am "httpd: Release <version>" -
Make and sign the tag. The script checks the signing key:
crates/radicle-httpd/build/tag <version> -
Push the commit and the tag. Push only this tag, not
--tags. The push reports that the canonical reference is updated:git push rad master refs/tags/releases/httpd/<version> rad sync --announce -
Optional: create the release in radicle-artifact now, so that it is visible before its archives are registered.
registercreates it otherwise:rad-artifact create releases/httpd/<version>
Build
Pushing the tag starts the 📦 httpd release build step in Buildkite. It builds
the archives in Docker and keeps them as build artifacts. You can also build
them locally. Either way, one build is enough to publish, but a second build in
another environment is recommended: it shows that neither environment changed
the archives.
-
Check out the tag. The scripts read the version from it with
git describe:git switch --detach releases/httpd/<version> -
Get the archives in one of these ways:
-
Download the CI build. This needs a Buildkite API token with
read_buildsandread_artifacts:export BUILDKITE_API_TOKEN=<token> BUILDKITE_ORG=<org> BUILDKITE_PIPELINE=<pipeline> crates/radicle-httpd/build/fetch <version> -
Build locally. A single run compiles the workspace and packages both binaries, one archive per binary per target. It uses podman; set
CONTAINER=dockerto use Docker:crates/radicle-httpd/build/build
Both write to
crates/radicle-httpd/build/artifacts/:radicle-httpd-<version>-<target>.tar.xz(binary + man page)radicle-search-<version>-<target>.tar.xz(binary)
each with a
.sha256alongside. -
-
Recommended: compare a local build with the CI build.
buildoverwritesartifacts/, so build first, then fetch the CI build into another folder:crates/radicle-httpd/build/build crates/radicle-httpd/build/fetch -o crates/radicle-httpd/build/artifacts-ci <version> crates/radicle-httpd/build/compare crates/radicle-httpd/build/artifacts-ciDo not publish if the archives differ.
comparetakes any folder of archives with their.sha256, so the build of another delegate works too.
Publish
-
Sign the archives with your Radicle key. This checks each archive against its
.sha256and writes a.sigalongside:crates/radicle-httpd/build/sign -
Upload. This publishes each binary into its own sibling folder on files.radicle.dev and creates the version-less and
latestsymlinks for both:SSH_LOGIN=<username> crates/radicle-httpd/build/uploadWarning: Uploading immediately publishes the release.
-
Register the archives with radicle-artifact, in the release of the tag. This records each archive's files.radicle.dev URL and
sha256. If you publish the archives thatfetchdownloaded intoartifacts/, it also records their Buildkite build. It also builds the explorer frontend bundle from the checked out tag withconfig/default.json, registers it as the collectionradicle-explorerand seeds it from your local artifact node. This needsnodeandnpm, in the version of.nvmrc, and no untracked files inconfig/, such aslocal.json. Running it again changes nothing:crates/radicle-httpd/build/register
Attest (recommended)
Other delegates check the release by building it themselves. attest compares
the CIDs of your build with the registered ones, and attests them only if all
match:
git switch --detach releases/httpd/<version>
crates/radicle-httpd/build/build
crates/radicle-httpd/build/attest
If your build differs, find out why before anyone uses the release. If the
release is wrong, withdraw its archives with
rad-artifact redact releases/httpd/<version> --cid <cid> -m <reason>.
Announce
-
Mark the previous release as resolved in Zulip
#Announcements -
Create a new announcement with the following template.
<commit>is the 8-character ID of the tagged commit, which the build also writes toradicle-httpd.json:git rev-parse --short=8 'releases/httpd/<version>^{commit}'Topic:
radicle-httpd + radicle-search <version>Message:
# 👾 radicle-httpd + radicle-search <version> `radicle-httpd` and `radicle-search` <version> (<commit>) are released. ## Installation Download binaries from: - https://files.radicle.dev/releases/radicle-httpd/<version> - https://files.radicle.dev/releases/radicle-search/<version> - https://radicle.dev/download Check a download with `rad-artifact verify --repo rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5 <archive>`, after `rad seed rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5`. ## Changelog <copy the <version> section from CHANGELOG.md> ## Checksums ``` <copy output from crates/radicle-httpd/build/checksums> ``` Attested by: <the DIDs in `rad-artifact show releases/httpd/<version>`, if any>
Notes
Important:
- macOS binaries are unsigned and not notarized; download via CLI only
- The build always runs in a
linux/arm64container, with the base images and zig pinned, so that builds on different hosts give the same bytes. It runs natively on Apple silicon and on thelarge_linux_armBuildkite queue, and under emulation on amd64 hosts
Podman Setup
We use podman for reproducible builds across machines. It's preferred over
Docker because it runs without a daemon and doesn't require root access.
On first run, you may need to configure UID/GID ranges:
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER
podman system migrate