Releases and verification
Every release is built by the release workflow from a v* tag and published in three
forms: a container image, a Helm chart and static Linux binaries. Each is signed with
Sigstore keyless signing, so you can check that what you
run was built by this repository’s release workflow from that tag and not altered
since. The release notes on GitHub come from
CHANGELOG.md.
The first published release is v0.2.0.
What a release publishes
| Artifact | Where | Platforms |
|---|---|---|
| Container image | ghcr.io/zerosandonesllc/ridm:{version} | linux/amd64, linux/arm64 |
| FIPS 140-3 image | ghcr.io/zerosandonesllc/ridm:{version}-fips (FIPS 140-3) | linux/amd64, linux/arm64 |
| Helm chart | oci://ghcr.io/zerosandonesllc/charts/ridm, and ridm-{version}.tgz on the GitHub release | |
| Static binaries | ridm-{version}-linux-amd64.tar.gz, ridm-{version}-linux-arm64.tar.gz on the GitHub release | linux x86_64, aarch64 |
| SBOM | attached to each image (BuildKit’s attestation, and an SPDX document attested with cosign), and ridm-{version}.spdx.json and ridm-{version}-fips.spdx.json on the GitHub release | |
| Checksums | SHA256SUMS and its Sigstore bundle SHA256SUMS.sigstore.json on the GitHub release |
Image tags
A release 1.2.3 is tagged 1.2.3, 1.2 and latest, and the FIPS image 1.2.3-fips,
1.2-fips and latest-fips. A pre-release such as
0.2.0-rc.1 gets only its own tag and never moves latest or a minor tag. The image is
one multi-arch index; Docker, containerd and Kubernetes pick the architecture.
Deploy by digest rather than by tag: tags move, a digest names exactly one image. The release notes give the digest, and so does
docker buildx imagetools inspect ghcr.io/zerosandonesllc/ridm:1.2.3
In the Helm chart, set image.digest to it; see Kubernetes (Helm).
The Helm chart
helm install ridm oci://ghcr.io/zerosandonesllc/charts/ridm --version 1.2.3 -f values.yaml
The chart’s version is the release’s version, and its image tag defaults to the same.
Static binaries
Each tarball holds ridm-api (the server, with the UI compiled in), ridm (the admin
CLI), LICENSE, README.md and CHANGELOG.md. Both binaries are statically linked
against musl and run on any Linux of their architecture, with no libc or OpenSSL
requirement; the server uses mimalloc, since musl’s own allocator scales poorly across
threads.
tar -xzf ridm-1.2.3-linux-amd64.tar.gz
sudo install -m 0755 ridm-1.2.3-linux-amd64/ridm-api ridm-1.2.3-linux-amd64/ridm /usr/local/bin/
The server is configured by environment variables exactly as in the image
(Server configuration), and runs migrations with
ridm-api migrate as the schema owner. Under systemd, a unit along these lines keeps it
confined:
[Unit]
Description=rIDM
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/local/bin/ridm-api
EnvironmentFile=/etc/ridm/ridm.env
# Secrets as files, read through the *_FILE variables:
LoadCredential=master_key:/etc/ridm/master_key
Environment=MASTER_KEY_FILE=%d/master_key
DynamicUser=yes
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
CapabilityBoundingSet=
Restart=on-failure
TimeoutStopSec=30
[Install]
WantedBy=multi-user.target
Verifying a release
Install cosign 3 or later (the release workflow signs with cosign 3, whose Sigstore bundle format older versions do not read). Every signature was made by the release workflow with its GitHub identity, so verification names that workflow and GitHub’s token issuer:
IDENTITY='^https://github.com/ZerosAndOnesLLC/rIDM/\.github/workflows/release\.yml@refs/tags/v'
ISSUER=https://token.actions.githubusercontent.com
The image:
cosign verify ghcr.io/zerosandonesllc/ridm:1.2.3 \
--certificate-identity-regexp "$IDENTITY" --certificate-oidc-issuer "$ISSUER"
The FIPS image is signed the same way: verify ghcr.io/zerosandonesllc/ridm:1.2.3-fips
with the same command.
Its SBOM (an SPDX document, attested by the same identity):
cosign verify-attestation --type spdxjson ghcr.io/zerosandonesllc/ridm:1.2.3 \
--certificate-identity-regexp "$IDENTITY" --certificate-oidc-issuer "$ISSUER" \
| jq -r '.payload' | base64 -d | jq '.predicate.packages | length'
The chart:
cosign verify ghcr.io/zerosandonesllc/charts/ridm:1.2.3 \
--certificate-identity-regexp "$IDENTITY" --certificate-oidc-issuer "$ISSUER"
The binaries and everything else on the GitHub release: verify the checksum file’s signature, then the files against it:
cosign verify-blob SHA256SUMS --bundle SHA256SUMS.sigstore.json \
--certificate-identity-regexp "$IDENTITY" --certificate-oidc-issuer "$ISSUER"
sha256sum --check --ignore-missing SHA256SUMS
A check that fails means the artifact was not produced by this repository’s release
workflow for a v* tag, or was changed afterwards. Do not run it.
How a release is cut
For maintainers, in
CONTRIBUTING.md:
bump the version everywhere it lives, move the changelog’s Unreleased notes under the
new version, merge, then publish a GitHub release for the tag (gh release create). The
workflow refuses a tag that disagrees with any version in the tree or has no changelog
section, and runs the heavy test suites (end-to-end, packaging, Helm, FIPS image,
conformance, fuzzing) as a gate before anything is built or published. Dispatched from a
branch, it rehearses the release from that branch without publishing anything.