Core release operations¶
Goal¶
Publish one stable Colossus version as six GitHub CLI archives, a signed Windows x64
Desktop installer, Linux Control Plane bundles and images, six VS Code packages,
two reviewed bootstrap installers,
@obscuritylabs/colossus-sdk on npm, obscuritylabs-colossus-sdk on PyPI, and
sdk/go/vX.Y.Z from the same immutable source commit. Stable releases require Azure
Artifact Signing for the Windows executables and installer. They do not include a
macOS Desktop artifact until Apple signing and notarization are configured.
Prerequisites¶
Complete these account-owned steps before publishing the first stable draft:
- Create the GitHub environment
sdk-production. Require an operator review, prevent self-review where the organization supports it, restrict deployment to protected release tags, and keep environment secrets empty. The publisher uses GitHub OIDC, not stored npm or PyPI credentials. - Confirm Actions may create tags with the workflow
GITHUB_TOKEN. The publisher grantscontents: writeandid-token: writeonly to its protected publication job. - Confirm control of the npm
@obscuritylabsscope. npm trusted publishers are configured from an existing package's settings; npm does not offer PyPI-style pending publishers. If@obscuritylabs/colossus-sdkdoes not yet exist, reserve it once with an intentionally non-release bootstrap version using an interactive maintainer login, then configure its trusted publisher before publishing a real Colossus version. -
In the npm package's Trusted Publisher settings, configure:
-
organization or user:
obscuritylabs - repository:
Colossus - workflow filename:
publish-sdk.yml - environment:
sdk-production - allowed action:
npm publish
After a trusted publication succeeds, disallow token-based publication and revoke
any bootstrap automation token. The public repository allows npm to attach a
provenance statement to each trusted OIDC publication; keep --provenance enabled.
- The normalized PyPI name
colossus-sdkbelongs to an unrelated project. Create a pending trusted publisher for the unclaimed projectobscuritylabs-colossus-sdkwith ownerobscuritylabs, repositoryColossus, workflowpublish-sdk.yml, and environmentsdk-production. The installed import remainscolossus_sdk.
Publisher configuration fields are case-sensitive. A missing or mismatched publisher fails at the registry without exposing a reusable credential.
Steps¶
Prepare a stable version¶
The following identities must all be the same stable X.Y.Z value:
[workspace.package].versionand all exact internal dependency versions;- the npm package and lockfile;
- the Python distribution;
- TypeScript, Python, and Go SDK user-agent versions;
- the
CHANGELOG.mdheading; and - the requested
vX.Y.Ztag.
Release SDK compatibility is pinned to the most recent earlier stable vX.Y.Z
tag reachable from the release commit. It never uses a moving branch as the
compatibility baseline. Package builds use the release commit timestamp as
SOURCE_DATE_EPOCH and the same pinned Node, npm, Python, Go, and Rust toolchain so the
protected publisher can reproduce every candidate byte. The release packager also
normalizes the Python source archive's order, ownership, permissions, and timestamps;
setuptools does not apply SOURCE_DATE_EPOCH to all sdist metadata itself.
All internal Rust packages must retain publish = false.
Set workspace.metadata.release.publish-sdks in Cargo.toml for each release:
true allows coordinated SDK registry publication; false publishes the application
artifacts without SDK registry publication. Both modes build and verify SDK candidate
archives with aligned versions.
The publisher reads this required boolean from the immutable release tag and blocks
its privileged publication job when false, including manual recovery requests. Missing
or malformed policy fails validation. Check the release tag's Cargo.toml for the
effective policy.
Regenerate the SDK input digest after changing package metadata, then run the completion gates:
./sdk/scripts/install-codegen-tools
./sdk/scripts/generate
cargo xtask check rust
cargo xtask pr --base origin/main
Validate the hosted stable path from the release branch before merging. Manual dispatch cannot create a GitHub Release or publish a registry package:
For a stable target this proves release readiness, all six native CLI jobs, SDK
generation and tests, package construction, intrinsic package metadata, the candidate
manifest, and checksums. Signed Windows jobs are skipped because manual dispatch cannot
enter the tag-scoped release-signing environment. Download the
colossus-sdk-release Actions artifact if manual package inspection is needed.
Manual validation uses the GitHub compiler cache. After tag validation, the six CLI
jobs and stable SDK candidate read and write the shared R2 compiler cache when
enabled. The sccache-r2-write environment must allow protected v* tags; see
CI/CD. The signed Windows Desktop job retains its
signing environment, and the macOS Desktop build remains credential-free.
Create and approve the release¶
After the reviewed version commit is on main, create an annotated tag:
The tag workflow creates a draft only after the six CLI archives, signed Windows x64 Desktop installer, and immutable SDK candidate pass. Before publishing the draft, verify that it contains exactly:
- six CLI archives and six adjacent
.sha256files; colossus-install.shandcolossus-install.ps1, each with an adjacent.sha256;- one npm
.tgz; - one Python wheel and one source distribution;
colossus-sdk-vX.Y.Z-manifest.json; andcolossus-sdk-vX.Y.Z-SHA256SUMS;- a signed
Colossus-Desktop-STABLE-vX.Y.Z-x86_64-pc-windows-msvc-setup.exe, its.sha256, sealed bundle manifest, and provenance JSON. - two
Colossus-Control-Plane-TAG-TARGET.tar.gzserver/web/deployment bundles and their checksums, for Linux x64 and arm64; - two matching
.docker.tar.gzoffline image archives and their checksums; and - six
Colossus-VSCode-TAG-PLATFORM.vsixpackages with checksums, for Linux, macOS, and Windows x64/arm64.
The complete stable release has 45 assets. Ordinary previews have 42; previews built from an unchanged stable source version have 38 because they omit bootstrap installers. Control Plane and VSIX jobs are required by the release gate for every channel. The extension retains its independently versioned package metadata; release filenames identify the shared source tag.
Publishing the stable draft triggers publish-sdk.yml. For a release whose policy
allows SDK publication, approve its one
sdk-production deployment. The job reverifies the exact release assets against the
colossus-sdk-release artifact of the successful release.yml run for the tag, so
release-asset write access alone cannot substitute bytes that the tag never produced;
a recomputed manifest and checksum file do not satisfy this comparison. Inside the
protected environment it independently rebuilds the SDK packages from the exact stable
tag and requires every release asset byte to match. It then reconciles npm and PyPI,
publishes only missing bytes, and finally creates the annotated sdk/go/vX.Y.Z tag on
the core tag's commit.
Expected result¶
The stable GitHub Release contains the six CLI archives and checksums, the two
repository-owned bootstrap installers and checksums, the five immutable SDK candidate
files, four signed Windows Desktop assets, Linux Control Plane bundles and offline
images, and six platform-specific VSIX packages with checksums. The Windows CLI
archives contain signed executables. Publishing also starts the separate Control
Plane image publisher. When publish-sdks is true, the protected publisher releases the same
version to npm and PyPI and creates the Go module tag at the identical source commit.
When publish-sdks is false, SDK candidate validation passes and the SDK publication
job is skipped; no SDK registry packages or Go module tag are created.
Verification¶
For releases with SDK publication enabled, also check the registries:
npm view @obscuritylabs/colossus-sdk@X.Y.Z version dist.tarball
python -m pip index versions obscuritylabs-colossus-sdk
go list -m github.com/obscuritylabs/colossus/sdk/go@vX.Y.Z
For those releases, verify that git rev-list -n 1 vX.Y.Z and
git rev-list -n 1 sdk/go/vX.Y.Z are identical. A stable core GitHub Release must not
contain an unsigned Desktop asset. The Desktop update-channel workflow runs only for a
separately produced stable release that contains a verified stable.json asset.
Confirm that the public bootstrap route resolves to the newly published, byte-identical
release asset:
curl -fsSL \
https://github.com/obscuritylabs/Colossus/releases/latest/download/colossus-install.sh \
-o /tmp/colossus-install.sh
sh /tmp/colossus-install.sh --version vX.Y.Z --dry-run --yes
The Verify public distribution workflow also runs automatically when the stable draft
is published. It uses no repository token, compares the exact-tag and latest bootstrap
bytes, verifies the bootstrap sidecar, performs a clean direct install on macOS, Linux,
and Windows, validates the receipt, and runs structured update discovery. Do not treat
the release as installation-ready until all three jobs pass.
Generate the exact Homebrew formula only from the published macOS checksum sidecars:
node scripts/ci/render-homebrew-formula.mjs \
--version X.Y.Z \
--assets PATH_TO_RELEASE_ASSETS \
--output colossus.rb
Review the generated formula, verify brew test colossus, and publish it to
obscuritylabs/homebrew-tap only after the public-distribution workflow passes. The
formula installs prebuilt upstream bytes and adds only an advisory Homebrew ownership
marker; it never writes a direct-install receipt. Update the version and four platform
hashes in flake.nix from the same published sidecars, refresh flake.lock only when
the nixpkgs input changes, and run nix flake check before merging the package metadata.
Package definitions in the release-preparation commit therefore continue to identify
the latest already-published stable release; never guess the next release's hashes.
After the public distribution jobs pass, update the root README,
CLI installation guide,
installation options, and
installation lifecycle only if the final
commands differ from the reviewed bootstrap contract. Confirm that the README's
latest/download commands, the review-before-running flow, exact-version flags,
colossus update, Nix ownership, manual archive verification, and uninstall guidance
all remain represented before closing a distribution epic.
Failure path¶
Registries and Git tags cannot be updated atomically. If one external system fails, rerun the protected publisher against the already-published GitHub Release:
The recovery path independently rebuilds the packages from the exact tag and refuses
publication unless every byte matches the immutable GitHub Release candidate. It
accepts an existing version only when the registry bytes match the release manifest,
publishes missing PyPI files with skip-existing, and accepts an existing Go tag only
when it resolves to the recorded source commit. Any conflicting immutable version or
tag fails closed; investigate it instead of changing or overwriting the release.
Recovery also requires the trusted colossus-sdk-release artifact for the tag. That
artifact is retained for fourteen days, so after it expires rerun the tag's release.yml
run before dispatching the publisher:
Next step¶
After the first coordinated stable release succeeds, keep the registry trusted-publisher
settings and sdk-production environment protected, and use this same candidate-first
flow for later stable versions.
Developer Previews and Desktop¶
Annotated vX.Y.Z-preview.N tags retain the ad-hoc signed, unnotarized macOS Desktop
Developer Preview and add a signed Windows Desktop Developer Preview. They do not build
stable SDK registry candidates or publish npm, PyPI, or Go versions. Both Windows
channels use manual updates until a separate Tauri updater key and feed are configured.
For a test build from main without a coordinated version bump, a preview tag may also
identify its exact stable source version: for example, v0.11.2-preview.1 may build
source version 0.11.2. The normal main-ancestry, release-readiness, signing, and
Desktop smoke gates still apply. The release is a prerelease and does not publish SDKs.
Its binaries and CLI archive names retain the source version; install Desktop from the
attached installer or app archive and extract CLI archives manually. These test releases
omit the four bootstrap installer assets because bootstrap installation requires the
tag and binary versions to match. Stable tags and already-versioned preview sources
still require an exact version match.
Control Plane containers and VS Code packages¶
The native Linux release jobs build the pinned deploy/control-plane/Dockerfile,
smoke its actual non-root image with a read-only filesystem and no network, and package
matching server/web bytes plus an offline docker load archive. Both architectures
are retained in the successful tag run's Actions artifacts and attached to the release.
Publishing the reviewed release starts Publish Control Plane image. It uses the
protected-main publisher, verifies the annotated tag's ancestry and successful tag
build, and compares every server/image release asset against the independently retained
Actions candidate. Recomputed mutable release checksums alone cannot authorize
substituted bytes. It publishes only those tested images at
ghcr.io/obscuritylabs/colossus-control-plane:TAG, then verifies the Linux amd64/arm64
manifest index by digest. Conflicting existing version tags are refused; matching
reruns reuse existing bytes. No moving latest alias is published.
The publisher requires Docker API 1.46 or later and explicitly pushes each executable platform manifest before assembling the index from immutable manifest digests. It verifies the remote manifest's config digest against the trusted offline archive, then pulls the immutable executable digest so Docker validates the actual layers and root filesystem before advertising the index. This supports both classic and containerd image stores. Containerd's parent index and default build attestations remain in the offline archive; they are omitted from the published executable image index.
Verify both the publication evidence and an anonymous digest pull before advertising
the image. The first GHCR package must be public for anonymous on-prem installation.
For an interrupted publication, rerun the publisher from main with the exact tag:
Trusted server candidates are retained for 30 days; if they have expired, the publisher
fails rather than trusting release sidecars. Restore a successful exact-tag build
before retrying. Offline installs can instead verify and load the attached
Colossus-Control-Plane-TAG-TARGET.docker.tar.gz archive.
The release builds platform-specific VSIX packages using the locked native keyring
archive and verifies its registry integrity before packaging. Install the matching
asset with code --install-extension PATH_TO_VSIX. This does not publish to the VS Code
Marketplace. Source/browser and native worker acceptance remain distinct checks; a
cross-packaged native binding is not a claim of native acceptance on that platform.
Documentation container¶
The separate documentation-candidate.yml tag workflow builds and HTTP smoke-tests
the canonical documentation image on native Linux amd64 and arm64. It retains the
actual tested offline images and candidate manifests binding the annotated tag, source
commit, archive hashes, and non-root image config digests. Candidate artifacts expire
after 30 days; mutable Release sidecars cannot substitute for this source evidence.
Publishing the reviewed stable or preview Release starts documentation-image.yml.
The publisher runs from one resolved protected-main revision and requires successful
exact-tag release.yml and documentation candidate runs before publishing
ghcr.io/obscuritylabs/colossus-documentation:TAG. It publishes only the tested
executables and verifies their immutable config/layers and final amd64/arm64 index.
It refuses conflicting existing version tags; matching reruns reuse existing images.
No moving latest alias or extra CLI Release assets are produced.
To recover an interrupted publication:
If the candidate artifacts expired, first rerun the original successful exact-tag Documentation image candidate workflow run, then retry publication:
gh run rerun DOCUMENTATION_CANDIDATE_RUN_ID
gh run watch DOCUMENTATION_CANDIDATE_RUN_ID --exit-status
gh workflow run documentation-image.yml --ref main -f tag=TAG
Inspect the retained publication evidence, confirm the first GHCR package is public, and verify an anonymous pull by its recorded index digest before advertising the image. Package visibility and a successful authenticated push do not prove anonymous availability. For example, use a temporary empty Docker configuration for the pull:
documentation_auth=$(mktemp -d)
docker --config "$documentation_auth" pull \
ghcr.io/obscuritylabs/colossus-documentation@sha256:RECORDED_INDEX_DIGEST
rm -r "$documentation_auth"
See documentation hosting for the portable /docs/
mount, Kubernetes deployment, and browser/agent search. The canonical GitHub Pages
publication continues independently.
Windows Artifact Signing authority¶
The tag-scoped release-signing GitHub environment is federated to the Azure app
registration with subject
repo:obscuritylabs/Colossus:environment:release-signing. The app needs the
Artifact Signing Certificate Profile Signer role on the colossus-code-sign
Artifact Signing account. The workflow reads the repository secrets
AZURE_CLIENT_ID, AZURE_TENANT_ID, and AZURE_SUBSCRIPTION_ID through
azure/login with GitHub OIDC. It signs with the colossus Public Trust profile
at the East US endpoint and an RFC 3161 timestamp. No certificate private key is
exported into GitHub.
The x64 signing runner signs both Windows CLI architectures after their native build and smoke tests, then recomputes each ZIP checksum. For Desktop it signs the sidecar and CLI before the bundle manifest is hashed. Tauri patches the manifest-bound app for NSIS, then invokes the Azure signer for the patched app, NSIS support DLLs, temporary PE uninstaller, and installer. Every installed binary must verify as Obscurity Labs LLC with a timestamp before release upload. A passing GitHub signing smoke run is recorded in the release PR; ordinary branch and manual validation builds do not receive signing authority.
Release asset OCI images¶
Publish Colossus release image packages every uploaded asset of an already-published
stable or preview release into one data-only OCI artifact. It runs on release
publication, or an operator can backfill an exact tag from main:
The destination is obscuritylabs/colossus-release on Docker Hub when both
DOCKERHUB_USERNAME and DOCKERHUB_PASSWORD repository secrets are configured and
authenticate successfully. DOCKERHUB_PASSWORD should contain a dedicated Docker Hub
access token authorized to push that repository, not an interactive account password.
auto falls back to ghcr.io/obscuritylabs/colossus-release when those credentials
are absent or login fails. registry=dockerhub fails instead of falling back;
registry=ghcr explicitly selects GitHub Container Registry. A later push/RBAC denial
fails visibly; rerun with registry=ghcr to select that alternative explicitly.
GHCR uses the job-scoped GITHUB_TOKEN with packages: write; no personal token or
copied secret from another repository is required. On first GHCR publication, confirm
the package visibility is public in the package settings before advertising anonymous
downloads. The package is linked to this repository using the standard source annotation.
See GitHub's Container Registry administration guide
for package visibility and repository access controls.
Each image has exactly the requested vX.Y.Z or vX.Y.Z-preview.N tag. The workflow
never moves latest, a stable/preview alias, or an existing conflicting version tag.
An identical rerun verifies and reuses the existing digest. Repository writers must
retain this single-publisher workflow and must not independently overwrite its tags;
registry tags themselves are mutable, so air-gap records should use the manifest digest.
There is no base image, operating system, executable entrypoint, or platform selection.
This is an ORAS artifact, not a runnable Docker FROM scratch root filesystem:
- OCI image manifest v1.1, artifact type
application/vnd.colossus.release.v1; - one raw blob per original release asset at
assets/<original-filename>; release-inventory.jsonwith release ID, tag, source commit, channel, publication time, and every asset's ID, size, and SHA-256 digest;- deterministic ordering and creation annotation, with no downloaded archive extraction or executable invocation.
The publisher downloads anonymously from fixed GitHub HTTPS origins, bounds redirects,
time and bytes, requires GitHub's SHA-256 for every asset, checks supplied checksum
documents, and rechecks the release snapshot before publication. Limits are 256 assets,
2 GiB per asset, and 8 GiB total. Legacy assets without GitHub digests are rejected.
For publication, both test and publishing jobs check out the same resolved commit of
protected main; the requested release tag selects data only, never publisher code.
The job then pulls the published manifest by digest and compares the complete inventory
and every asset again. Its summary and retained evidence contain the digest and pull
command, never registry credentials. Desktop signing warnings remain unchanged: moving
release bytes into OCI does not sign or notarize them. This whole-release format is
separate from the Agent Plugin OCI profile and is not accepted by plugins install.
Retrieve the release files or carry the entire OCI layout into a disconnected registry:
oras pull ghcr.io/obscuritylabs/colossus-release:v0.10.10-preview.12 \
--output release-assets
oras cp --to-oci-layout \
ghcr.io/obscuritylabs/colossus-release:v0.10.10-preview.12 \
./release-layout:v0.10.10-preview.12
oras cp --from-oci-layout ./release-layout:v0.10.10-preview.12 \
registry.example/colossus-release:v0.10.10-preview.12
Use the digest-pinned reference from the successful job instead of the tag when recording an immutable transfer. ORAS is sufficient; Docker Desktop or a container daemon is not required. Verify locally without registry publication:
node --test scripts/ci/release-oci.test.mjs
node scripts/ci/release-oci-roundtrip.mjs
node scripts/ci/release-oci.mjs prepare v0.10.10-preview.12 /tmp/new-release-output
The round-trip check requires ORAS 1.3.4 and opens no socket. CI pins the ORAS installer action and verifies the downloaded CLI checksum; it runs the contracts and real local OCI round trip before any job receives registry write permission.