Release API
Release is an API entity for point-in-time snapshots of configuration to be applied.
Commands
The cub release subcommands publish, list, get, withdraw, and delete Releases. A Release bundles the Units in a Space that are assigned to the Space's release Target, captured at a point in time, and served as an immutable, read-only OCI bundle. For the complete flag reference, see the cub release CLI docs.
Publish
cub release publish <space-slug>
Creates a Release of <space-slug>, bundling the Units assigned to the Space's release Target and making it available via the OCI server. By default each Unit is captured at its head Revision; pass --revision to instead pin each Unit to the highest-numbered Revision carrying a Tag (a Unit with no matching tagged Revision falls back to its head Revision).
Each Unit's Revision is selected by Tag, so the value given to --revision has to resolve to one Tag. A Tag itself does; so do the boundaries of a ChangeSet and a ChangeOrder, which is how a whole change is released rather than a revision number that means something different in every Unit:
| Form | What it selects |
|---|---|
<slug> or Tag:<slug> |
the Revision that Tag marks |
ChangeSet:<slug> |
where a closed ChangeSet ended |
Before:ChangeSet:<slug> |
the state it started from |
ChangeOrder:<slug> |
where the change arrived |
Before:ChangeOrder:<slug> |
the state before it |
A revision number, a Revision ID, and the named revisions each pick out a Revision of one Unit, so they are not accepted.
# Bundle each Unit at the Revision tagged "v1.2.0"
cub release publish --revision v1.2.0 my-space
# Bundle each Unit at the Revision a promoted change arrived at
cub release publish --revision ChangeOrder:web-base/release-v452 my-space
# Release the state a promotion started from, to roll it back
cub release publish --revision Before:ChangeOrder:web-base/release-v452 my-space
--label, --annotation, and --delete-gate set the Release's metadata at publish time; cub release update can change it afterwards.
Withdraw
cub release withdraw <release-id>
Takes a Release out of service: it is no longer published for download, so its OCI endpoint stops serving it. The Release itself is retained — withdrawing is un-publishing, not deleting — so it remains listable and inspectable, and the record of what was published survives.
The Release is located by its globally-unique ID, so --space is not required. If any Unit in the bundle has an outstanding DestroyGate, the withdrawal is blocked until the gate clears.
Delete
cub release delete <release-id>
Removes the Release and its stored bundle, and the release-N Tag it made; a Tag it adopted stays. This is the destructive form; use withdraw when the intent is to stop serving a Release rather than to erase it. The Release is located by its ID, so --space is not required.
A Release marks the Revisions it bundled, and its Tag marks them too, so the delete is refused until --detach removes the marks: cub release delete --detach <release-id>. See deleting referenced entities.
Get
cub release get --space <space-slug> <release-id>
Gets details about a Release. Instead of a release ID, you can identify a Release within a specific --space by OCI reference:
--oci-reference latest— the newest Release published for the Space's release Target.--oci-reference sha256:...— a specific manifest digest.--bundle-digest sha256:...— a specific bundle content digest.
List
cub release list --space <space-slug>
Lists the Releases in a Space, or across all Spaces with --space '*'. Supports the standard --where, --filter, and --contains selectors:
# Find a Release by bundle digest across the whole organization
cub release list --space '*' --where "Digest = 'sha256:...'"
Getting started
In order to publish a Release, you must have an OCI ProviderType Target and a Space with Units ready for deployment. This can be done by the following:
cub space create target-space # holds the Target
cub target create --provider OCI --space target-space oci-example # creates the Target
cub space create --release-target target-space/oci-example app-example # creates the Space
cub variant upload --component app-example --variant base --space app-example ./app-example/
The Target lives in its own Space (target-space) to sidestep an ordering problem: a Space's --release-target must already exist when the Space is created, so the Target can't live in the Space it releases. It names no worker; with none, cub target create defaults to OCI/Any. How a GitOps operator authenticates to pull the Release is covered in GitOps.
The cub variant upload step uploads ./app-example/ as Units in the Space app-example (--component and --variant are required). Note the --release-target option on the Space creation: it sets Space.ReleaseTargetID, which acts as the default Target for Units in that Space. Uploaded Units inherit that Target automatically, so they're picked up by the Release without any per-Unit configuration.
Now that we have a Space populated with Units ready for deployment, we can publish a Release. Use the following:
cub release publish app-example
This will bundle all Units and make them available at Space.ReleaseURL, to fetch that value, use the following:
cub space get app-example -o jq='.ReleaseURL'
The created Release will be available at that value plus the OCI tag latest, or its manifest digest, available via the following command:
cub release list --space app-example
Or if you know the ReleaseID of the Release already, you can do:
cub release get --space app-example <ReleaseID>
Together, the ReleaseURL and latest or a manifest digest can be used to configure an OCI client such as ArgoCD or FluxCD synchronizing the image as an application to be applied to a cluster.
Releasing Updates
Once we have an OCI client synchronizing Releases, we can publish updates from edited Units by running publish once again, like so:
cub release publish app-example
This will bundle the Units at their head Revision, so any updates made, and any Units with no updates since the initial Release, will be bundled. If you want to pin a Release to a specific set of Revisions instead, create a Tag and apply it to those Revisions, like so:
cub tag create v0.1.0
cub unit tag --space app-example --where "Slug LIKE '%'" v0.1.0
cub unit tag requires a selection (--unit, --where, or --filter) and tags each selected Unit's head Revision by default. The --where "Slug LIKE '%'" above matches every Unit in the Space; narrow it (for example --unit my-unit or a label match) to tag only a subset. Then publish a Release pinned to that Tag:
cub release publish --revision v0.1.0 app-example
From there, assuming the OCI client is using the latest OCI tag, the configuration can be automatically synchronized, otherwise, the manifest digest will need to be used.
Taking a Release out of service
If a Release was made erroneously or is later found to have issues, withdraw it. It is un-published — no longer served from its OCI endpoint, so no client can pull it — while the Release itself is retained, so what was published stays on the record:
cub release withdraw <ReleaseID>
Withdrawing does not roll anything back. A GitOps operator following the latest OCI tag needs something to converge on, so publish the previous state as a new Release. --revision Before:ChangeOrder:<slug> names the state a promoted change started from, which is how a rollout is rolled back:
cub release publish --revision Before:ChangeOrder:web-base/release-v452 my-space
To remove a Release and its stored bundle entirely, rather than to stop serving it, use cub release delete <ReleaseID>. A Destroy Gate on any Unit in the bundle blocks withdrawal until it clears.
See tracking and promoting changes for undoing a change that has been promoted into several Spaces.