cub variant promote
cub variant promote
Promote a variant space to match its upstream space
Synopsis
Promote variant spaces to match changes in their upstream spaces.
A space must have been created by "cub variant create", which stamps an "UpstreamSpaceID" annotation recording the upstream space it was cloned from. The server reconciles each variant with that upstream:
- Upgrade every unit whose upstream unit has advanced, merging the upstream changes. A unit whose upstream was emptied is emptied, and an empty unit whose upstream has content again is revived.
- Clone any units added to the upstream space since the variant was created or last promoted, linking each clone to its upstream unit. When the variant space has a Namespace label, which "cub variant create --namespace" sets, set-namespace places the clones, and revived units, in that namespace.
- Copy the upstream space's links, other than UpgradeUnit links, that the variant does not have yet, from the variant's copy of each unit, retargeting a link to the downstream copy of the unit it points at when that unit is in the upstream space. That covers a link added upstream between units the variant already has, not only the links of the units just added. A link that already points into this variant is left alone rather than copied into it. A link the variant has with no record of being copied, connecting the same units the same way, is adopted as the copy rather than duplicated. A copied link whose upstream link has since been deleted is reported as orphaned and left in place.
Promoting again changes nothing. Use --dry-run to preview what would be upgraded and added, and add -o mutations to see the changes, including the content of the units that would be added. To apply exactly what was previewed, pass the dry run's Plan (-o jq=.Plan) as --expected-plan: nothing is written if the promotion would now do anything different.
The spaces to promote are the positional space, or those --where-space and --filter-space select, or those a change order is headed for. Selectors combine: naming a stage and --where-space promotes the spaces of that stage the expression selects. Spaces are promoted in upstream order, so a variant is promoted after a selected variant it takes from.
An upgrade re-runs the upstream's recorded function invocations against each unit where it can -- so a change lands where the unit's own structure puts it -- and records one revision per upstream revision that has an effect, carrying that revision's change description. --squash gives up both: the range arrives as one rebased diff in one revision.
--change-order promotes a named change rather than everything the upstream has reached. The
change order fixed its range when it was created, so the upgrade stops where it ends, a unit
it does not cover is passed over, and a unit that has merged past where it starts is an error
rather than a merge of a different range. A unit short of where it starts has not merged some
upstream revisions that are not the change order's -- typically ones a link in the upstream
space, such as a TransformPaths link, wrote after the unit last merged. --prior-revisions says
what to do with them: Include (the default) merges them first, as revisions that do not carry
the change order; Skip leaves them out, as though the unit had already merged them; Error
refuses, naming the unit, the link, and each revision. A unit it covers but has no changes for is marked and not
changed: its start and end tags land on the same revision. That is what lets
"cub release publish --revision ChangeOrder:
- Units are cloned first, at the revision the change order starts from, and then upgraded through the change with everything else. A unit created upstream after the change order was fixed is outside it: those are listed rather than cloned, and promoting without --change-order adds them.
- The promotion is undone in one step, however many revisions it made:
"cub variant demote
--change-order / ", once the change order has an AbortedReason saying the change is not coming. - Promoting is idempotent. A unit already carrying the change order's end tag has taken the change and is passed over, so running a promotion that landed partway again finishes it. An aborted change order is not promoted anywhere.
A change order with UpdateType Invoke propagates differently and reads the same. Its change is one invocation, run in each space rather than merged from an upstream: nothing is cloned, and the space need not be a variant of anything.
A change order created under a ChangeWorkflow is promoted through its stages, and the server enforces each stage's entry gates -- evaluated over every space of the stage before it, and the first stage's over the change order's own space -- for every client. Without a space or selector, --change-order advances the change into the next stage it has not reached; --target-stage names the stage instead. Naming a stage says where the change is headed, not that it may skip what precedes it. --force promotes past gates that do not hold, requires --force-reason, and is recorded on the change order.
The writes take the options a unit update does, and every write of the promotion carries them: the upgrades, the set-namespace on added and revived units, and a change order's invocation. --protect records the paths each write changes as protected local overrides, and is refused on a promotion that merges -- one without --change-order, or of an UpgradeUnit or MergeUnits change order -- since merges are what protection holds paths against. --clearance names the guarded reasons the writes are cleared for, and a guarded path it does not cover is withheld and reported as a conflict; --guard records reasons on the paths written, which a later operation must be cleared for, this promotion's later writes included, so --clearance has to cover them; --subgroup is recorded on each write's mutations. --tag marks the revision each unit the promotion writes is left at, added units included, and leaves units it does not change untagged. It cannot be used with --change-order, whose own tags mark what it promotes, and a variant with a unit to write that the tag already marks is not promoted.
A stage is promoted one variant at a time and can land partway. A variant that fails is reported and the ones after it are still promoted. Running the stage again repairs it.
Examples:
# Promote a variant to match its upstream
cub variant promote web-prod
# Preview the changes, including the mutations
cub variant promote web-prod --dry-run -o mutations
# Promote every variant of a component
COMPONENT_ID=$(cub component get web -o jq=.Component.ComponentID)
cub variant promote --where-space "ComponentID = '$COMPONENT_ID' AND Labels.Variant != 'base'"
# Promote, recording the whole range as one revision per unit
cub variant promote web-prod --squash
# Promote one named change, leaving later upstream changes behind
cub variant promote web-prod --change-order release-42
# Promote a change that is an invocation rather than an upstream merge
cub variant promote web-prod --change-order platform/bump-api-image
# Promote that change into every variant of a stage of its change workflow
cub variant promote --change-order web-base/release-42 --target-stage staging
# Preview what promoting the whole stage would do
cub variant promote --change-order web-base/release-42 --target-stage staging --dry-run
# Advance the change to the next stage it has not reached
cub variant promote --change-order web-base/release-42
# Promote past a stage's gates, recording why
cub variant promote --change-order web-base/release-42 --target-stage prod --force --force-reason "incident 1234"
# Promote within a changeset, with a change description
cub variant promote web-prod --changeset release-2024-06 --change-desc "Promote to prod"
# Promote, tagging what it writes and taking guarded paths owned by the platform team
cub variant promote web-prod --tag web-base/release-2024-06 --clearance owner=platform
cub variant promote [<variant>] [flags]
Options
--change-desc string change description recorded on the upgraded and cloned units
--change-order string change order to promote instead of everything the upstream has reached: it supplies the range, units it does not cover are passed over, a unit that has merged past where it starts is an error, and one short of it is handled as --prior-revisions says. A bare slug resolves in the upstream space of the space being promoted, or in the selected space otherwise. Units the variant does not have yet are cloned at the change order's start and then upgraded through it; ones created upstream after the change order was fixed are outside it and are listed rather than cloned
--changeset string changeset to associate the upgraded and cloned units with
--clearance stringArray class of guarded reason this change is cleared for, as KEY, KEY=VALUE[;VALUE...], KEY!=VALUE[;VALUE...], or !KEY to refuse any path carrying KEY (repeatable). A guarded path this does not cover is not written, and the withheld change is reported as a conflict
--dry-run preview the units that would be upgraded and added without changing anything
--expected-plan string the Plan a --dry-run of the same promotion returned; nothing is written if the promotion would now do anything different
--filter-space string filter over spaces selecting the spaces to promote
--force promote past ChangeWorkflow gates that do not hold; requires --force-reason, and is recorded on the change order
--force-reason string why the gates are overridden; required with --force
--guard stringArray reason to record on the paths this change writes, as KEY=VALUE (repeatable). A later operation must be cleared for it before overwriting those paths, this one included, so --clearance has to cover it. Adds and overwrites only; retiring a guard is cub unit set-guard --remove-guard
-h, --help help for promote
--include-config-data return the configuration each unit write produces, or with --dry-run would produce, as ConfigData in structured output (-o json, -o yaml, -o jq=...)
-o, --output string Output format. One of: json, yaml, name, wide, mutations, jq=<expr>, yq=<expr>, custom-columns=<spec>
--prior-revisions string with --change-order, what to do for a unit that has not merged as far as the change order's start on its upstream: Include (the default) merges the upstream revisions before the start first, as revisions that do not carry the change order; Skip merges only the change order's range, as though the unit had already merged as far as its start, and those revisions do not arrive later; Error refuses, naming the unit, the link, and the revisions; All merges them as Include does and also marks every unit the change does not change at its head, so the next promotion brings it up to this space. Defaults to the change order's PriorRevisions
--protect record the paths each write of the promotion changes as protected local overrides, so a later merge from upstream does not overwrite them; only with a change order that is promoted by invocation or by Insert, Upsert, or TransformPaths links, since a promotion that merges is what protection holds paths against
--quiet No default output.
--squash merge each unit's range as one rebased diff in one revision instead of walking it: by default a promotion re-runs the upstream's recorded function invocations against each unit where it can, and records one revision per upstream revision that has an effect there
--subgroup string category recorded on the mutations of each write of the promotion: alphanumeric, at most 64 characters
--tag string tag (slug, space/slug, or UUID) to put on the revision each unit the promotion writes is left at; not with --change-order, whose own tags mark what it promotes
--target-stage string stage of the change order's ChangeWorkflow to promote into, promoting every variant the stage selects: it requires --change-order, the gates of the stage before are checked once for the whole stage, and a variant that fails is reported without stopping the ones after it. A space or --where-space narrows the stage. Without it, --change-order alone advances the change into the first stage it has not reached
--verbose Detailed output, additive with default output
--where-space string where expression selecting the spaces to promote, instead of naming one
Options inherited from parent commands
--context string The context to use for this command
--debug Debug output
SEE ALSO
- cub variant - Variant commands