# StellaOps CLI Release Packaging ## Scope - Package and publish StellaOps CLI binaries for all supported OS/arch targets with checksums, signatures, completions, and a container image. - Outputs feed three lanes: (1) public release mirrors, (2) air-gapped/offline kit, (3) internal regression runners. - Source artefacts come from DevOps pipelines (`.gitea/workflows/cli-build.yml`, `.gitea/workflows/cli-chaos-parity.yml`). ## Inputs (expected layout) ``` out/cli// stella-cli-linux-amd64.tar.gz stella-cli-linux-arm64.tar.gz stella-cli-darwin-arm64.tar.gz stella-cli-windows-amd64.zip completions/ bash/stella zsh/_stella fish/stella.fish parity/ parity-report.json sbom/ stella-cli.spdx.json ``` `` must match the git tag and container tag (e.g., `2025.12.0`). ## Packaging steps (deterministic) 1) Set version and workdir ```bash export CLI_VERSION=2025.12.0 export CLI_OUT=out/cli/$CLI_VERSION ``` 2) Generate checksums (sorted, LF endings) ```bash cd "$CLI_OUT" find . -maxdepth 1 -type f \( -name 'stella-cli-*' -o -name '*.zip' \) \ -print0 | sort -z | xargs -0 sha256sum > SHA256SUMS ``` 3) Sign checksum file (cosign keyless or key) ```bash COSIGN_YES=true cosign sign-blob \ --key env://MIRROR_SIGN_KEY_B64 \ --output-signature SHA256SUMS.sig \ --output-certificate SHA256SUMS.pem \ SHA256SUMS ``` 4) Build/push container image (optional if pipeline already produced) ```bash docker build -t registry.local/stella/cli:$CLI_VERSION -f deploy/compose/cli/Dockerfile . docker push registry.local/stella/cli:$CLI_VERSION ``` 5) Produce offline image tar (for airgap kit) ```bash docker pull registry.local/stella/cli:$CLI_VERSION docker save registry.local/stella/cli:$CLI_VERSION \ | gzip -9 > stella-cli-image-$CLI_VERSION.tar.gz ``` 6) Bundle completions ```bash tar -C "$CLI_OUT/completions" -czf stella-cli-completions-$CLI_VERSION.tar.gz . ``` 7) Publish artefact manifest (for mirrors/offline kit) ```bash cat > release-manifest-$CLI_VERSION.json <<'EOF' { "version": "REPLACE_VERSION", "binaries": [ "stella-cli-linux-amd64.tar.gz", "stella-cli-linux-arm64.tar.gz", "stella-cli-darwin-arm64.tar.gz", "stella-cli-windows-amd64.zip" ], "completions": "stella-cli-completions-REPLACE_VERSION.tar.gz", "checksums": "SHA256SUMS", "signatures": ["SHA256SUMS.sig", "SHA256SUMS.pem"], "container": { "image": "registry.local/stella/cli:REPLACE_VERSION", "offline_tar": "stella-cli-image-REPLACE_VERSION.tar.gz" } } EOF sed -i "s/REPLACE_VERSION/$CLI_VERSION/g" release-manifest-$CLI_VERSION.json ``` ## Distribution lanes - **Mirror / public:** upload binaries, completions, SBOM, `SHA256SUMS*`, and `release-manifest-.json` to the mirror bucket; expose via CDN. - **Offline kit:** copy the same files plus `stella-cli-image-.tar.gz` into `out/offline-kit/cli/` before running `ops/offline-kit/scripts/build_offline_kit.sh`. - **Internal runners:** sync `SHA256SUMS` and `SHA256SUMS.sig` to the runner cache; store container tar in the runner image cache path. ## Verification ```bash cd "$CLI_OUT" sha256sum --check SHA256SUMS cosign verify-blob --key env://MIRROR_SIGN_KEY_B64 --signature SHA256SUMS.sig --certificate SHA256SUMS.pem SHA256SUMS ``` ## Rollback / re-spin - To revoke a bad drop, delete the mirror path for that version and reissue `release-manifest-.json` with `"revoked": true` field; keep signatures for audit. - Re-spin by rerunning steps with a new version tag; never overwrite artefacts in-place. ## Evidence to attach in sprint - `SHA256SUMS`, `SHA256SUMS.sig`, `release-manifest-.json`, and offline image tar path uploaded to sprint evidence locker.