Skip to content

cub changeworkflow create

cub changeworkflow create

Create a new change workflow or bulk create change workflows

Synopsis

Create a new change workflow, or bulk create change workflows by cloning existing ones.

SINGLE CHANGEWORKFLOW CREATION:

A ChangeWorkflow says how a change is promoted: the ordered stages it moves through, which Spaces each stage selects, and the gates that have to pass before it enters one. Give the stages with --stage, or write the whole workflow in a file and pass it with --filename.

A stage selects its Spaces with a "WhereSpace" expression over Spaces, among the Spaces the change order being promoted is headed for: the change order says where a rollout goes, and the workflow says in what order. Nothing else is implied, so one workflow can govern the rollouts of many components; a stage can name a component, but that ties the workflow to it. A stage named with --stage selects "Labels.Stage = ''", which is what "cub variant create --stage" labels a variant's Space with. A stage that selects its Spaces some other way is written in a file.

The gates a stage can declare are: Validated no Unit the change changed, in any Space of the stage before, has ValidationErrors on what a release of it would bundle there Released every Space of the stage before has released the change; a Space with no release target has nothing to release, so it passes Healthy every Space of the stage before reports it Synced, Succeeded and Healthy

--prerequisites is one set of gates, given to every stage after the first and to the final stage. A stage's gates are its entry gates: they are checked over the stage before it, and the first stage's over the space the change order was created in, where the change already is -- which is why the flag leaves the first stage without them. The final stage's are what the last stage must satisfy for the rollout to read as completed, which no promotion can gate because no hop is left. A rollout whose stages gate differently from one another sets each stage's gates with --stage-prerequisites, and which Spaces it selects with --stage-where-space.

A workflow with no stages governs ChangeSets rather than ChangeOrders: its Final prerequisites must hold in every Space the ChangeSet was opened in for the ChangeSet to close ("cub changeset create --change-workflow"). Create one with --final-prerequisites and no --stage, declaring any custom or attestation prerequisite it names with --custom-prerequisite or --attestation-prerequisite. Validated, custom and attestation prerequisites can gate closing a ChangeSet; Released and Healthy cannot, since a change is released only after its ChangeSet has closed.

Single Examples:

  # From flags. Each --stage names one stage, given in the order a change is promoted through
  # them, and --prerequisites gates every one after the first alike.
  cub changeworkflow create --space workflows myapp-main-line \
    --stage dev --stage staging --stage prod \
    --prerequisites Released,Healthy

  # From a file, or from stdin with --from-stdin
  cub changeworkflow create --space workflows myapp-main-line --filename workflow.yaml

  # Then create a change order governed by it
  cub changeorder create --space myapp-base bump-base-image \
    --change-workflow workflows/myapp-main-line

  # A workflow with no stages, which gates closing a ChangeSet on its Units validating
  # and on an approval
  cub changeworkflow create --space workflows changeset-review \
    --attestation-prerequisite one-approver --attestation-prerequisite-count one-approver=1 \
    --final-prerequisites "Validated;one-approver"
  cub changeset create --space myapp-base tls-rollout --change-workflow workflows/changeset-review

A workflow file holds the entity, so its fields are the ones "cub changeworkflow get -o json" prints:

  Stages:
    - Name: dev
      WhereSpace: "Labels.Stage = 'dev'"
    - Name: prod
      WhereSpace: "Labels.Stage = 'prod'"
      Prerequisites: [Released, Healthy, code-freeze, two-approvers]
      ReleasePrerequisites: [release-manager]
  Final:
    Prerequisites: [Released, Healthy]
  CustomPrerequisites:
    - Name: code-freeze
      Expression: "cel:Space.Annotations['code-freeze'] != 'true'"
  AttestationPrerequisites:
    - Name: two-approvers
      Count: 2
      Description: two approvals of the change in staging, by people who did not write it
    - Name: release-manager
      FromUserIDs: [9b2c0f3e-5d7a-4a61-8f0e-2b6d1c4e7a90]
      MaxAge: 72h

An attestation prerequisite requires Attestations (see "cub attestation") of each Revision a gate reads: Count distinct users recording a Pass, of Type Approval unless another is named. By default an author of the change does not count (AllowAuthors), and an unrevoked Fail blocks (IgnoreFail). A stage's Prerequisites read what a release of the change would bundle in the stage before, for the Units it changed; its ReleasePrerequisites, which may name only attestation prerequisites, read what a release of the change order in one of the stage's spaces bundles. "cub variant approve" records approvals.

BULK CHANGEWORKFLOW CREATION:

When no positional arguments are provided, bulk create mode is activated. This mode clones existing change workflows and creates multiple new ones with optional modifications.

Cloning is how a workflow shape is shared across components: a workflow names no component, so a clone governs whatever component's change orders name it.

Bulk Create Examples:

  # Give every team's workflow space a copy of the standard rollout
  cub changeworkflow create --changeworkflow myapp-main-line \
    --dest-space payments-workflows,search-workflows

  # Clone the workflows of one space into every space a where expression selects
  cub changeworkflow create --space workflows --where "Slug LIKE '%-main-line'" \
    --where-space "Labels.Kind = 'workflows'"

  # Clone with a name prefix, and label the clones
  cub changeworkflow create --changeworkflow myapp-main-line \
    --dest-space workflows --name-prefix canary- --label "Rollout=canary"
cub changeworkflow create [<slug>] [flags]

Options

      --allow-exists                                           Allow creation of resources that already exist
      --annotation strings                                     annotations in key=value format; can separate by commas and/or use multiple instances of the flag
      --attestation-prerequisite stringArray                   one attestation prerequisite of the ChangeWorkflow, as <name> (repeatable). On an update the ones named are the ones it has, in that order: one it had before keeps its other fields
      --attestation-prerequisite-allow-authors stringArray     AllowAuthors of one attestation prerequisite, as <name>=true|false (repeatable; <name>=- clears it). Count an attester who wrote a Revision of the change
      --attestation-prerequisite-count stringArray             Count of one attestation prerequisite, as <name>=<value> (repeatable; <name>=- clears it). How many distinct attesters must record a Pass on each Revision
      --attestation-prerequisite-description stringArray       Description of one attestation prerequisite, as <name>=<value> (repeatable; <name>=- clears it). What the requirement is for, in the author's words
      --attestation-prerequisite-distinct-groups stringArray   DistinctGroups of one attestation prerequisite, as <name>=true|false (repeatable; <name>=- clears it). Require an attester from each group of FromGroupIDs, which it requires
      --attestation-prerequisite-from-group-ids stringArray    FromGroupIDs of one attestation prerequisite, as <name>=<value>[;<value>...] (repeatable; <name>=- clears it). The Groups whose members' Attestations count, beside the Users FromUserIDs names
      --attestation-prerequisite-from-user-ids stringArray     FromUserIDs of one attestation prerequisite, as <name>=<value>[;<value>...] (repeatable; <name>=- clears it). The Users whose Attestations count
      --attestation-prerequisite-ignore-fail stringArray       IgnoreFail of one attestation prerequisite, as <name>=true|false (repeatable; <name>=- clears it). Count only passes
      --attestation-prerequisite-max-age stringArray           MaxAge of one attestation prerequisite, as <name>=<value> (repeatable; <name>=- clears it). How old an Attestation may be and still count, as a duration such as 72h
      --attestation-prerequisite-type stringArray              Type of one attestation prerequisite, as <name>=<value> (repeatable; <name>=- clears it). The Attestation Type that counts
      --changeworkflow strings                                 target specific change workflows by slug or UUID for bulk create (can be repeated or comma-separated)
      --custom-prerequisite stringArray                        one custom prerequisite of the ChangeWorkflow, as <name>=<expression> (repeatable). On an update the ones named are the ones it has, in that order: one it had before keeps its other fields
      --custom-prerequisite-description stringArray            Description of one custom prerequisite, as <name>=<value> (repeatable; <name>=- clears it). What the gate checks, in the author's words
      --delete-gate strings                                    delete gates in key[=true] format; can separate by commas and/or use multiple instances of the flag
      --dest-space strings                                     destination spaces for bulk create (can be repeated or comma-separated)
      --display-name string                                    friendly name for the entity, which need not be unique or URL-safe; an entity without one is shown by its slug
      --dry-run                                                report what the command would write, and write nothing
      --filename string                                        Read the ConfigHub entity's fields, as YAML or JSON, from file, URL (https://), or stdin (-), as --from-stdin does; mutually exclusive with --from-stdin
      --filter string                                          Filter entity to apply to the list. Specify as 'space/filter' for cross-space filters or just 'filter' for current space. Supports both slugs and UUIDs. The filter will be combined with any --where clause using AND logic. Examples: "production-filters/security-check", "my-filter-uuid", "validation-rules"
      --filter-space string                                    filter entity containing WHERE expression to select destination spaces for bulk create (slug or UUID)
      --filter-unit string                                     filter, by slug or UUID, over Units selecting those to create from, with --from-backing-units
      --final-prerequisites string                             gates the last stage must satisfy for the rollout to read as completed, as <name>[;<name>...] (use '-' to clear)
      --from-backing-units                                     create a ChangeWorkflow from each ConfigHub/YAML Unit --where-unit, --filter-unit and --space select that describes one, in the Unit's space, with the Unit as its backing Unit
      --from-stdin                                             Read the ConfigHub entity's fields, as YAML or JSON, from stdin; merged with command arguments on create, and merged with command arguments and existing entity on update. A field the entity does not have, or one only the server sets, is refused; cub <entity> explain lists the fields
  -h, --help                                                   help for create
      --hidden-reason string                                   hide the entity, giving the reason as a name such as Archived: lists and bulk operations leave it out unless --include-hidden names the reason (use '-' to clear, which shows the entity again)
      --include-hidden string[="*"]                            Also select hidden entities, to list or to act on: those hidden for the given HiddenReasons, comma-separated, as in --include-hidden=BackingUnit, or for any reason when given no value or "*". ConfigHub/YAML Units, which hold the configuration of other entities, are hidden with the reason BackingUnit. A --where naming entities by Slug or ID selects them whether hidden or not
      --label strings                                          labels in key=value format; can separate by commas and/or use multiple instances of the flag
      --name-pattern string                                    a pattern string for name generation of clones, prefix 'template:' to use a Go template with .SourceEntitySlug to access the original ChangeWorkflow and .Labels to access variant labels, example: 'template:{{.SourceEntitySlug}}-{{.Labels.env}}'
      --name-prefix strings                                    name prefixes for bulk create (can be repeated or comma-separated)
  -o, --output string                                          Output format. One of: json, yaml, name, wide, mutations, jq=<expr>, yq=<expr>, custom-columns=<spec>
      --patch-existing                                         with --from-backing-units, patch a ChangeWorkflow a selected Unit already backs with what the Unit holds that it has not taken yet, rather than report that the Unit backs it
      --permission strings                                     permission in format Action:UserIDOrUsername, Action:group:GroupSlugOrID for a group you belong to, or Action:serviceaccount:ServiceAccountSlugOrID (e.g., Manage:user@example.com, View:group:platform, View:serviceaccount:deploy-bot, can be repeated)
      --prerequisites strings                                  gates given to every stage after the first and to the final stage (can be repeated or comma-separated): Validated, Released, Healthy. A stage's gates are checked over every Space of the stage before it, and the first stage's over the change order's own space, which is why the first stage is not given them. A custom prerequisite is declared with --custom-prerequisite and gated on by name
      --quiet                                                  No default output.
      --set stringArray                                        set a field of the ChangeWorkflow by its path, as <path>=<value> (repeatable). A path is field names separated by dots; a list element is addressed as ?<key>=<value> or by position, as in Stages.?Name=prod.WhereSpace, and is added if it is not there. A list of plain values separates them with ';'; an object or a list of objects is given as YAML or JSON. A reference is given as it is elsewhere, by slug, <space>/<slug> or ID. With --patch, only a path with no list element in it
      --stage strings                                          name of one stage of the workflow (can be repeated or comma-separated), given in the order a change is promoted through them. A stage selects the Spaces labeled "Labels.Stage = '<name>'", which is what "cub variant create --stage" sets; --stage-where-space selects a stage's Spaces some other way
      --stage-prerequisites stringArray                        Prerequisites of one stage, as <name>=<value>[;<value>...] (repeatable; <name>=- clears it). The stage's entry gates, each naming a built-in check or one declared in CustomPrerequisites
      --stage-release-prerequisites stringArray                ReleasePrerequisites of one stage, as <name>=<value>[;<value>...] (repeatable; <name>=- clears it). Gates on publishing a Release for a change order in one of the stage's Spaces, each naming one declared in AttestationPrerequisites
      --stage-where-space stringArray                          WhereSpace of one stage, as <name>=<value> (repeatable; <name>=- clears it). Selects the stage's Spaces: a where expression over Spaces, intersected with the change order's InScopeSpaceIDs
      --unset stringArray                                      clear a field of the ChangeWorkflow by its path, or remove the list element the path ends at (repeatable)
      --variant-labels strings                                 labels for bulk create in the format of key1=value1|value2,key2=value1|value2|value3
      --verbose                                                Detailed output, additive with default output
      --where string                                           Filter expression using SQL-inspired syntax. Supports conjunctions with AND. String operators: =, !=, <, >, <=, >=, LIKE, NOT LIKE, ILIKE, ~~, !~~, ~, ~*, !~, !~*. Pattern matching with LIKE/ILIKE uses % and _ wildcards. Regex operators (~, ~*, !~, !~*) support POSIX regular expressions. A related entity is referenced by prefix, as in "UpstreamUnit.Slug = 'base'"; when the reference names a list, a * segment matches any element, as in "FromLink.*.Slug = 'upgrade-app'". Examples: "Slug LIKE 'app-%'", "DisplayName ILIKE '%backend%'", "Slug ~ '^[a-z]+-[0-9]+$'"
      --where-space string                                     where expression to select destination spaces for bulk create
      --where-unit string                                      where expression over Units selecting those to create from, with --from-backing-units
      --with-backing-units                                     give each ChangeWorkflow the bulk operation writes a backing Unit if it has none: a ConfigHub/YAML Unit holding its configuration, kept in step with it

Options inherited from parent commands

      --component string   the Component of --variant, when that names the variant alone; --variant <component>/<variant> says the same in one flag
      --context string     The context to use for this command
      --debug              Debug output
      --space string       space to operate in, by slug or UUID. Omitted, a list or bulk operation spans the organization and a single entity is named as <space>/<slug>; "*" means the same as omitting it
      --variant string     variant to operate in, as <component>/<variant>, or as <variant> with --component: the space naming that Component whose Variant label is <variant>. The same scope as --space, named by what it is rather than by the space's slug; the two cannot be combined

SEE ALSO