Skip to content

Roll out a new module version

llms.txtlists every page for an agent
Optional: hand this page to your coding agentThe steps work by hand too.
Show the whole prompt
Read https://intentius.io/terragucci/guides/roll-out-a-module-version/.
Run `npx terragucci rollout <module>` (the preview only), fix any pin it refuses
in a pull request, and print the `--mode apply` command for me to run.
Never apply, approve (a pull request review or `terragucci approve`), override a policy denial (`terragucci override`), use `--mode apply`, or merge; never touch `.chant/allowed_signers` or `chant/lifecycle`.

Every root that pins the module moved to the new version through one pull request per wave.

You need Why
Roots that pin the module exactly by oci:// tag or digest, registry version or git tag a range cannot move (Stages lists the cases)
The new version published (Publish your modules) the rollout pins roots to it
The HCL parser beside terragucci: npm i -D @cdktn/hcl2json the rollout edits each root’s pin with it
A forge token that can open pull requests, in the variable token_env names the apply run and the rollout job open the rollout’s pull requests with it
Optional: waves.canary in terragucci.yml it picks the roots that move first
Optional: rollouts in terragucci.yml a scheduled job opens each next wave, so nobody runs step 5
  1. Preview the rollout.

    Terminal window
    npx terragucci rollout modules/network

    Name the module by path or by source without the pin, and leave out the version to get the newest published. The dry run changes nothing. When pins disagree, --from picks which moves.

    For a module that modules.registry publishes, modules/network also names the calls whose source is its registry address, such as modules.example.com/acme/network/generic, and their version moves. With no version named, the newest the registry lists counts too.

  2. Fix any pin it refuses. The preview lists each pin it cannot move, with a tip:

    The pin Tip
    a range such as ~> 1.4 rollout-floating-pin: pin one version
    set from a variable or a local rollout-literal-pin: write a literal, since a variable’s value is not in the diff
    absent from the source rollout-pin: add a ?ref=, ?tag= or version
    two versions of the module in one directory rollout-one-pin: pin every call at one version

    Do that in its own pull request, then run the preview again.

  3. Open the first wave.

    Terminal window
    npx terragucci rollout modules/network 1.4.0 --mode apply

    --mode apply writes to the forge and runs no terraform apply; roots apply after the merge. It opens one pull request for the canary wave, or the first in dependency order. Only that wave’s files change, and each pin keeps its shape.

    The description of the rollout's wave 1 pull request: modules/service 1.0.0 to 1.1.0 for the four dev service roots, and wave 2 opening once they have merged and appliedThe description of the rollout's wave 1 pull request: modules/service 1.0.0 to 1.1.0 for the four dev service roots, and wave 2 opening once they have merged and applied
  4. Review and merge it. The apply stage runs on the merge commit.

    The pull request's files: each dev service main.tf moves its ref from modules/service/v1.0.0 to v1.1.0The pull request's files: each dev service main.tf moves its ref from modules/service/v1.0.0 to v1.1.0
  5. Let the next wave open. With rollouts set, init writes a job that runs terragucci respond rollout --mode apply on that schedule:

    rollouts: "*/15 * * * *"
    token_env: ROLLOUT_TOKEN

    Each run opens the next wave of every rollout whose last wave merged and applied, so a wave opens within one interval. A rollout with a pull request still open, or one closed unmerged, is left alone.

    Forge Job Token Schedule
    GitHub its own workflow, terragucci-rollout.yml, which you can also start by hand the secret token_env names, else the job’s own; GitHub runs no workflow for a pull request the job’s own token opens, so name a secret holding a token that can push branches and open pull requests the rollouts cron
    Forgejo the same the secret token_env names, else the job’s own the rollouts cron
    GitLab the rollout job in the pipeline the token_env variable a pipeline schedule with that cron and the variable TERRAGUCCI_SCHEDULE set to rollouts; init prints the steps

    token_env is the project’s forge token variable, shared beyond the rollout: on GitLab every job that pushes or opens a merge request reads it, and on GitHub and Forgejo the fmt, tips, version-bump and drift jobs export their own token under that name. respond.rollout: off leaves the rollout job out.

    Without rollouts, run the rollout again after each merge. Each run takes at most one step:

    Terminal window
    npx terragucci rollout modules/network 1.4.0 --mode apply

    Either way, the next wave waits for the last to merge and apply. The apply status it checks is apply/<path> per directory, else terragucci/apply. A pull request closed unmerged or a failed apply stops the rollout. It never merges or writes a default branch.

    Exit code Meaning
    0 a step was taken, or the rollout is complete
    3 a pull request waits for a merge or an apply
    1 the rollout stopped

    From a control repo, wave 1 holds every project’s canaries and later waves follow in config order. Each project gets its own pull request per wave. rollouts is a single repo’s key, since a project’s pipeline sees only its own roots; in a control repo, run terragucci respond rollout --mode apply on a schedule of your own.

The same flow moves a provider in the lock file:

Terminal window
npx terragucci rollout --provider hashicorp/aws 6.68.0 --mode apply

Each lock file is rewritten for that provider alone, and an exact version constraint moves too. The wave stops unless every other provider stays where it was.

terragucci

These docs count page views and clicks with PostHog. They set no cookies, store nothing in your browser, and send nothing when your browser asks not to be tracked.