CLI release assets¶
This document names the files a CapsCode CLI release (v<version>) publishes and
says how scripts/install.sh and capscode update --cli find and check them.
The release workflow (.github/workflows/release-cli.yml, logic in
scripts/release/) and both clients follow it. The channel manifest that points
clients at a release is described in channel-format.md.
Assets¶
Every asset is attached to the GitHub release for tag v<version> and downloaded
from https://github.com/<channel>/releases/download/v<version>/<asset>. For
capscode update --cli, <channel> is update.channel (default
sayre4ux/capscode); the installer always uses sayre4ux/capscode. <version>
is the workspace version in Cargo.toml, without the v.
| Asset | Contents |
|---|---|
capscode-<version>-macos-universal |
The CLI for macOS, arm64 and x86_64 in one file (lipo), ad-hoc signed with identifier dev.capscode.cli. No Apple Developer ID, no notarization. |
capscode-<version>-linux-x86_64 |
The CLI for Linux on x86-64, linked against glibc 2.35 or older (runs on Ubuntu 22.04+ and Debian 12+). |
capscode-<version>-linux-aarch64 |
The same for Linux on arm64. |
capscode-<version>-build-context.tar.gz |
The files scripts/build-images.sh needs to build every image, for installs without a checkout (see below). |
capscode-<version>-release-notes.md |
The CHANGELOG.md section for the release; capscode update --cli shows it before asking. |
capscode-<version>-src.tar.gz |
git archive of the tag. |
SHA256SUMS |
SHA-256 of every asset above. |
capscode-<version>-attestation.sigstore.json |
The GitHub artifact attestation bundle covering every asset above, SHA256SUMS included. |
Binaries are bare executables, not archives. There is no Windows build.
SHA256SUMS¶
sha256sum output: one line per asset, <64 lowercase hex>, two spaces, the
asset name, sorted by name. Clients accept * instead of the two spaces, and
refuse a file with a malformed line, a name listed twice, or no line for an asset
they download. Every downloaded file must match its line before anything is
written to its final place.
Attestation¶
actions/attest-build-provenance signs one provenance statement whose subjects
are every asset above. Verify a download with:
gh attestation verify <asset> --repo sayre4ux/capscode \
--signer-workflow sayre4ux/capscode/.github/workflows/release-cli.yml
--signer-workflow pins the release workflow, so an attestation produced by any
other workflow of the repository does not vouch for a release asset.
The image build context¶
Images are never published; every user builds them. The build context tarball
carries exactly what scripts/build-images.sh reads: Cargo.toml, Cargo.lock,
rust-toolchain.toml, LICENSE, crates/, images/, providers/,
scripts/build-images.sh, and scripts/smoke-tui.sh. The gateway image compiles
the broker inside Docker, so a binary install needs no Rust on the host. The
tarball never contains .git, target/, or any file git ignores.
Format: gzip-compressed ustar. Every entry is a regular file under
capscode-<version>-build-context/; there are no directory, link, or device
entries. scripts/release/build-context.sh produces it and
scripts/release/test-build-context.sh checks that it holds every Dockerfile
COPY source.
Clients unpack it to <CapsCode home>/build/<version>/ (the CapsCode home is
$CAPSCODE_HOME, or ~/.capscode). They refuse the whole archive if any entry is
outside the top-level directory, has an absolute path or a .. component, or is
a link or a device file, has more than 20,000 entries, or unpacks to more than
64 MiB, and they unpack into a temporary directory that replaces the final one
only when complete.
The CLI looks for its image build script in this order:
CAPSCODE_BUILD_IMAGES, the path of abuild-images.shto run;<CapsCode home>/build/<own version>/scripts/build-images.sh;- the source checkout the binary was built from, if it still exists and belongs to the current user;
- otherwise it stops and says how to restore the files (rerun the installer).
capscode toolchain build runs the script found this way.
Who downloads what¶
scripts/install.sh (binary install) reads channel.json with a small JSON
parser written in awk (no jq or Python needed). It requires valid JSON with
schema equal to 1, cli.tag equal to v plus cli.version, each field it
reads exactly once, and no escaped keys. It takes the newest version from
cli.version unless --version is given, and refuses a version listed in
cli.yanked_versions either way. It then downloads SHA256SUMS, the binary for
the host, and the build context. With
--verify-attestation it also requires gh attestation verify to accept the
binary and the build context. On macOS it requires codesign --verify --strict
to pass. It runs the binary's --version before installing it.
capscode update --cli downloads the same three files plus the release notes,
using the same HTTPS client and host allowlist as capscode update, with a
64 MiB cap for the binary and 16 MiB for the build context. With
update.verify_with_gh = true it runs the gh attestation verify command above
on the binary and the build context.
Both refuse a version that is not a plain X.Y.Z (no prerelease or build
suffix). A prerelease tag is published as a GitHub prerelease and never written
to channel.json.
Test mirror (CAPSCODE_RELEASE_BASE_URL)¶
For the installer's own tests only, CAPSCODE_RELEASE_BASE_URL replaces
https://github.com/<channel>/releases/download with a mirror laid out the same
way (<base>/v<version>/<asset>, plus <base>/channel.json). It accepts only
https:// and file:// URLs and changes where files come from, never how they
are checked: the SHA256SUMS match, the archive checks, the signature check, and
--verify-attestation all still apply. scripts/test-install.sh uses it.