Custom Workflows

Custom workflows can be defined to override the default commands that Atlantis runs.

Usage

Custom workflows can be specified in the Server-Side Repo Config or in the Repo-Level atlantis.yaml files.

Notes

  • If you want to allow repos to select their own workflows, they must have the allowed_overrides: [workflow] setting. See server-side repo config use cases for more details.
  • If in addition you also want to allow repos to define their own workflows, they must have the allow_custom_workflows: true setting. See server-side repo config use cases for more details.

Use Cases

.tfvars files

Given the structure:

.
└── project1
    ├── main.tf
    ├── production.tfvars
    └── staging.tfvars

If you wanted Atlantis to automatically run plan with -var-file staging.tfvars and -var-file production.tfvars you could define two workflows:

# repos.yaml or atlantis.yaml
workflows:
  staging:
    plan:
      steps:
      - init
      - plan:
          extra_args: ["-var-file", "staging.tfvars"]
    # NOTE: no need to define the apply stage because it will default
    # to the normal apply stage.
    
  production:
    plan:
      steps:
      - init
      - plan:
          extra_args: ["-var-file", "production.tfvars"]

Then in your repo-level atlantis.yaml file, you would reference the workflows:

# atlantis.yaml
version: 3
projects:
# If two or more projects have the same dir and workspace, they must also have
# a 'name' key to differentiate them.
- name: project1-staging
  dir: project1
  workflow: staging
- name: project1-production
  dir: project1
  workflow: production

workflows:
  # If you didn't define the workflows in your server-side repos.yaml config,
  # you would define them here instead.

When you want to apply the plans, you can comment

atlantis apply -p project1-staging

and

atlantis apply -p project1-production

Where -p refers to the project name.

Adding extra arguments to Terraform commands

If you need to append flags to terraform plan or apply temporarily, you can append flags on a comment following --, for example commenting:

atlantis plan -- -lock=false

If you always need to do this for a project's init, plan or apply commands then you must define a custom workflow and set the extra_args key for the command you need to modify.

# atlantis.yaml or repos.yaml
workflows:
  myworkflow:
    plan:
      steps:
      - init:
          extra_args: ["-lock=false"]
      - plan:
          extra_args: ["-lock=false"]
    apply:
      steps:
      - apply:
          extra_args: ["-lock=false"]

Custom init/plan/apply Commands

If you want to customize terraform init, plan or apply in ways that aren't supported by extra_args, you can completely override those commands.

In this example, we're not using any of the built-in commands and are instead using our own.

# atlantis.yaml or repos.yaml
workflows:
  myworkflow:
    plan:
      steps:
      - run: terraform init -input=false -no-color
      
      # If you're using workspaces you need to select the workspace using the
      # $WORKSPACE environment variable.
      - run: terraform workspace select -no-color $WORKSPACE
      
      # You MUST output the plan using -out $PLANFILE because Atlantis expects
      # plans to be in a specific location.
      - run: terraform plan -input=false -refresh -no-color -out $PLANFILE
    apply:
      steps:
      # Again, you must use the $PLANFILE environment variable.
      - run: terraform apply -no-color $PLANFILE

Terragrunt

Atlantis supports running custom commands in place of the default Atlantis commands. We can use this functionality to enable Terragrunt.

You can either use your repo's atlantis.yaml file or the Atlantis server's repos.yaml file.

Given a directory structure:

.
└── live
    ├── prod
    │   └── terragrunt.hcl
    └── staging
        └── terragrunt.cl

If using the server repos.yaml file, you would use the following config:

# repos.yaml
repos:
- id: "/.*/"
  workflow: terragrunt
workflows:
  terragrunt:
    plan:
      steps:
      - run: terragrunt plan -no-color -out=$PLANFILE
    apply:
      steps:
      - run: terragrunt apply -no-color $PLANFILE

If using the repo's atlantis.yaml file you would use the following config:

version: 3
projects:
- dir: live/staging
  workflow: terragrunt
- dir: live/prod
  workflow: terragrunt
workflows:
  terragrunt:
    plan:
      steps:
      - run: terragrunt plan -no-color -out $PLANFILE
    apply:
      steps:
      - run: terragrunt apply -no-color $PLANFILE

NOTE: If using the repo's atlantis.yaml file, you will need to specify each directory that is a Terragrunt project.

WARNING

Atlantis will need to have the terragrunt binary in its PATH. If you're using Docker you can build your own image, see Customization.

Running custom commands

Atlantis supports running completely custom commands. In this example, we want to run a script after every apply:

# repos.yaml or atlantis.yaml
workflows:
  myworkflow:
    apply:
      steps:
      - apply
      - run: ./my-custom-script.sh

Notes

  • We don't need to write a plan key under myworkflow. If plan isn't set, Atlantis will use the default plan workflow which is what we want in this case.
  • A custom command will only terminate if all output file descriptors are closed. Therefore a custom command can only be sent to the background (e.g. for an SSH tunnel during the terraform run) when its output is redirected to a different location. For example, Atlantis will execute a custom script containing the following code to create a SSH tunnel correctly: ssh -f -M -S /tmp/ssh_tunnel -L 3306:database:3306 -N bastion 1>/dev/null 2>&1. Without the redirect, the script would block the Atlantis workflow.

Custom Backend Config

If you need to specify the -backend-config flag to terraform init you'll need to use a custom workflow. In this example, we're using custom backend files to configure two remote states, one for each environment. We're then using .tfvars files to load different variables for each environment.

# repos.yaml or atlantis.yaml
workflows:
  staging:
    plan:
      steps:
      - run: rm -rf .terraform
      - init:
          extra_args: [-backend-config=staging.backend.tfvars]
      - plan:
          extra_args: [-var-file=staging.tfvars]
  production:
    plan:
      steps:
      - run: rm -rf .terraform
      - init:
          extra_args: [-backend-config=production.backend.tfvars]
      - plan:
          extra_args: [-var-file=production.tfvars

NOTE

We have to use a custom run step to rm -rf .terraform because otherwise Terraform will complain in-between commands since the backend config has changed.

You would then reference the workflows in your repo-level atlantis.yaml:

version: 3
projects:
- name: staging
  dir: .
  workflow: staging
- name: production
  dir: .
  workflow: production

Reference

Workflow

plan:
apply:
Key Type Default Required Description
plan Stage steps: [init, plan] no How to plan for this project.
apply Stage steps: [apply] no How to apply for this project.

Stage

steps:
- run: custom-command
- init
- plan:
    extra_args: [-lock=false]
Key Type Default Required Description
steps array[Step] [] no List of steps for this stage. If the steps key is empty, no steps will be run for this stage.

Step

Built-In Commands: init, plan, apply

Steps can be a single string for a built-in command.

- init
- plan
- apply
Key Type Default Required Description
init/plan/apply string none no Use a built-in command without additional configuration. Only init, plan and apply are supported

Built-In Command With Extra Args

A map from string to extra_args for a built-in command with extra arguments.

- init:
    extra_args: [arg1, arg2]
- plan:
    extra_args: [arg1, arg2]
- apply:
    extra_args: [arg1, arg2]
Key Type Default Required Description
init/plan/apply map[extra_args -> array[string]] none no Use a built-in command and append extra_args. Only init, plan and apply are supported as keys and only extra_args is supported as a value

Custom run Command

Or a custom command

- run: custom-command
Key Type Default Required Description
run string none no Run a custom command

Notes

  • run steps are executed with the following environment variables:
    • WORKSPACE - The Terraform workspace used for this project, ex. default.
      • NOTE: if the step is executed before init then Atlantis won't have switched to this workspace yet.
    • ATLANTIS_TERRAFORM_VERSION - The version of Terraform used for this project, ex. 0.11.0.
    • DIR - Absolute path to the current directory.
    • PLANFILE - Absolute path to the location where Atlantis expects the plan to either be generated (by plan) or already exist (if running apply). Can be used to override the built-in plan/apply commands, ex. run: terraform plan -out $PLANFILE.
    • BASE_REPO_NAME - Name of the repository that the pull request will be merged into, ex. atlantis.
    • BASE_REPO_OWNER - Owner of the repository that the pull request will be merged into, ex. runatlantis.
    • HEAD_REPO_NAME - Name of the repository that is getting merged into the base repository, ex. atlantis.
    • HEAD_REPO_OWNER - Owner of the repository that is getting merged into the base repository, ex. acme-corp.
    • HEAD_BRANCH_NAME - Name of the head branch of the pull request (the branch that is getting merged into the base)
    • BASE_BRANCH_NAME - Name of the base branch of the pull request (the branch that the pull request is getting merged into)
    • PROJECT_NAME - Name of the project configured in atlantis.yaml. If no project name is configured this will be an empty string.
    • PULL_NUM - Pull request number or ID, ex. 2.
    • PULL_AUTHOR - Username of the pull request author, ex. acme-user.
    • USER_NAME - Username of the VCS user running command, ex. acme-user. During an autoplan, the user will be the Atlantis API user, ex. atlantis.
    • COMMENT_ARGS - Any additional flags passed in the comment on the pull request separated by commas, ex. atlantis plan -- arg1 arg2 will result in COMMENT_ARGS=arg1,arg2.
  • A custom command will only terminate if all output file descriptors are closed. Therefore a custom command can only be sent to the background (e.g. for an SSH tunnel during the terraform run) when its output is redirected to a different location. For example, Atlantis will execute a custom script containing the following code to create a SSH tunnel correctly: ssh -f -M -S /tmp/ssh_tunnel -L 3306:database:3306 -N bastion 1>/dev/null 2>&1. Without the redirect, the script would block the Atlantis workflow.
  • If a workflow step returns a non-zero exit code, the workflow will stop.