Skip to content

.stackorder.yaml ​

A .stackorder.yaml in a stack directory declares the stack's dependencies and instances, and overrides root settings for that stack. It is optional; add one only to stacks that have dependencies, instances or overrides.

Example ​

yaml
depends_on:
  - stacks/prod/vpc                       # same repo
  - acme/network-infra//stacks/prod/tgw   # another repo, same installation
tool: terraform                           # override
environment: production                   # override the prefix mapping
apply:
  allowed_teams: [platform-prod]          # replaces the root list for this stack
plan_output: summary                      # this stack's plans hold secrets
ignore_inferred: [stacks/legacy/dns]      # suppress a remote_state edge

A stack with instances:

yaml
backend_config:
  - 'key=kyc/{{ .Instance }}.tfstate'
var_files:
  - "regions/{{ .Instance }}.tfvars"
env:
  TF_VAR_environment: "{{ .Instance }}"
instances:
  staging: {}
  production:
    apply:
      allowed_teams: [platform-prod]

Keys ​

KeyTypeDefaultMeaning
depends_onlist of stack keys[]Stacks this stack depends on. Each entry creates a depends_on edge, which orders applies and propagates change. Entries may be templates.
instanceslist of names, or map of name to overridesnoneThe instances of this directory. It replaces the instances the root from_var_files would derive. See Stack instances.
workspacestringnoneThe Terraform workspace the CLI selects after init. On a stack with instances it is a template, such as "{{ .Instance }}". On a stack without instances, a workspace other than default makes the stack one instance of that name; default, or a value that renders empty, is the same as none.
backend_configlist of strings[]-backend-config values for init, after the root's: name=value, or a file relative to the repository root. See backend_config.
var_fileslist of paths[]-var-file values for plans, after the root's, relative to the stack directory. See var_files.
envmap of name to string or {plan, apply, drift}{}Environment variables for the tool and the hooks, over the root's. See env.
toolterraform or tofuroot toolThe binary this stack runs with.
tool_versionstringroot tool_versionThe tool version for this stack.
environmentstringfrom the root environments mapThe GitHub environment this stack's applies run under. It may be a template.
apply.allowed_teamslist of teamsroot apply.allowed_teamsWho may request an apply that touches this stack, in the same form as the root key. A non-empty list replaces the root list. The server reads it from the default branch.
plan_outputfull or summaryroot plan_outputHow much of this stack's plan reaches the server and the PR comment. A summary on the default branch wins over a pull request's full.
ignore_inferredlist of stack keys[]Inferred reads_state edges to suppress. Each suppressed edge is reported as a warning by the scan. Entries may be templates.

An entry of the instances map may set environment, workspace, backend_config, var_files, env, plan_output, apply.allowed_teams, depends_on and ignore_inferred for that instance.

depends_on entries ​

An entry is a stack key, optionally qualified with a repository:

EntryPoints at
stacks/prod/vpcA stack in the same repository; for a directory with instances, see below
infra/network:productionOne instance of a directory
acme/network-infra//stacks/prod/tgwA stack in another repository covered by the same App installation
acme/network-infra//infra/tgw:productionAn instance in another repository

Paths are repository relative. Leading ./ and trailing / are removed. An entry that is absolute, starts with .., or names a repository that is not owner/repo is rejected.

An entry without a suffix that names a directory with instances resolves to the instance of the same name as the depending instance when the target has one, else to the target's only stack when it has exactly one. Otherwise it is kept as written, with a warning, like any unknown target. infra/kyc:production listing infra/network depends on infra/network:production. See Dependencies between instances.

A cross-repo entry is stored in the graph but cannot order a single-repository run. See Cross-repo dependencies.

How settings merge ​

For each stack, and for each instance of a stack with instances, the effective settings are:

SettingEffective value
tool, tool_versionThe stack's value if set, otherwise the root value.
plan_outputThe instance's value, else the stack's, else the root value.
workspaceThe instance's value, else the stack's; none when neither is set.
environmentThe instance's environment, else the stack's, else the most specific match in the root environments map, else the instance name, else default.
apply.allowed_teamsThe most specific non-empty list: the instance's, else the stack's, else the root list.
backend_configThe root list, then the stack's, then the instance's.
var_filesThe root list, the stack's, the instance's from_var_files file, then the instance's list.
envPer variable name, the instance's value, else the stack's, else the root's.
depends_on, ignore_inferredThe stack's list followed by the instance's; the root file has no equivalent.

A run that touches several stacks requires the commenter to satisfy every affected stack's allowed_teams. To apply a subset, name it: stackorder apply stacks/staging/vpc. For a directory with instances, name each instance, as in stackorder apply infra/kyc:production: a bare directory path names no stack, and the apply is refused.

Inferred edges ​

When a stack reads another stack's state through terraform_remote_state with a matching S3 bucket and key, Stackorder infers a reads_state edge. The backend compared is the stack's effective backend, after its backend_config, so instances with a partial backend "s3" {} block take part. You can:

  • keep it, and let it order applies softly and propagate change;
  • promote it, by listing the other stack in depends_on;
  • suppress it, by listing the other stack in ignore_inferred.

Validation ​

The file is parsed strictly. It is rejected when it has:

  • unknown keys, or a tool or plan_output outside its allowed values;
  • an invalid depends_on entry, or an empty ignore_inferred entry;
  • a workspace containing /, :, a space or a tab, or, on a stack without instances, one that renders to an invalid instance name;
  • an instance name that is not a letter or digit followed by letters, digits, ., _ and -, is longer than 64 characters, or is default in any letter case, a null item in the instances list, or an instance listed twice;
  • a backend_config entry that is empty, has no name before =, or is an absolute file;
  • a var_files entry that is empty or absolute;
  • an env name that is not a valid variable name or is reserved in any letter case, a null env value, an env object with a key other than plan, apply and drift, or one with none of them;
  • a template that does not parse, uses an action or builtin outside the allowed set, fails to render, or renders more than 4096 bytes.

An empty file is valid and changes nothing.