This is one of a suite of terraform related actions - find them at dflook/terraform-github-actions.
This action applies a terraform plan.
The default behaviour is to apply the plan that has been added to a PR using the terraform-plan action.
If the plan is not found or has changed, then the apply action will fail.
This is to ensure that the action only applies changes that have been reviewed by a human.
You can instead set auto_approve: true which will generate a plan and apply it immediately, without looking for a plan attached to a PR.
This a demo of the process for apply a terraform change using the dflook/terraform-plan and dflook/terraform-apply actions.
To make best use of this action, require that the plan is always reviewed before merging the PR to approve. You can enforce this in github by going to the branch settings for the repo and enable protection for the master branch:
- Enable 'Require pull request reviews before merging'
- Check 'Dismiss stale pull request approvals when new commits are pushed'
- Enable 'Require status checks to pass before merging', and select the job that runs the plan.
- Enable 'Require branches to be up to date before merging'
These input values must be the same as any terraform-plan for the same configuration. (unless auto_approve: true)
-
pathPath to the terraform root module to apply
- Type: string
- Optional
- Default: The action workspace
-
workspaceTerraform workspace to run the apply in
- Type: string
- Optional
- Default:
default
-
labelA friendly name for the environment the terraform configuration is for. This will be used in the PR comment for easy identification.
It must be the same as the
labelused in the correspondingterraform-plancommand.- Type: string
- Optional
-
variablesVariables to set for the terraform plan. This should be valid terraform syntax - like a variable definition file.
with: variables: | image_id = "${{ secrets.AMI_ID }}" availability_zone_names = [ "us-east-1a", "us-west-1c", ]
Variables set here override any given in
var_files. This can be used with remote backends such as Terraform Cloud/Enterprise, with variables set in the remote workspace having precedence.- Type: string
- Optional
-
var_fileList of tfvars files to use, one per line. Paths should be relative to the GitHub Actions workspace
with: var_file: | common.tfvars prod.tfvars
This can be used with remote backends such as Terraform Cloud/Enterprise, with variables set in the remote workspace having precedence.
- Type: string
- Optional
-
backend_configList of terraform backend config values, one per line.
with: backend_config: token=${{ secrets.BACKEND_TOKEN }}
- Type: string
- Optional
-
backend_config_fileList of terraform backend config files to use, one per line. Paths should be relative to the GitHub Actions workspace
with: backend_config_file: prod.backend.tfvars
- Type: string
- Optional
-
replaceList of resources to replace, one per line.
Only available with terraform versions that support replace (v0.15.2 onwards).
with: replace: | kubernetes_secret.tls_cert_public kubernetes_secret.tls_cert_private
- Type: string
- Optional
-
targetList of resources to apply, one per line. The apply operation will be limited to these resources and their dependencies.
with: target: | kubernetes_secret.tls_cert_public kubernetes_secret.tls_cert_private
- Type: string
- Optional
-
auto_approveWhen set to
true, generated plans are always applied.The default is
false, which requires plans to have been approved through a pull request.- Type: bool
- Optional
- Default: false
-
parallelismLimit the number of concurrent operations
- Type: number
- Optional
- Default: The terraform default (10)
-
var⚠️ Deprecated: Use thevariablesinput instead.Comma separated list of terraform vars to set.
This is deprecated due to the following limitations:
- Only primitive types can be set with
var- number, bool and string. - String values may not contain a comma.
- Values set with
varwill be overridden by values contained invar_files - Does not work with the
remotebackend
You can change from
vartovariablesby putting each variable on a separate line and ensuring each string value is quoted.For example:
with: var: instance_type=m5.xlarge,nat_type=instance
Becomes:
with: variables: | instance_type="m5.xlarge" nat_type="instance"
- Type: string
- Optional
- Only primitive types can be set with
-
json_plan_pathThis is the path to the generated plan in JSON Output Format The path is relative to the Actions workspace.
This is not available when using terraform 0.11 or earlier. This also won't be set if the backend type is
remote- Terraform does not support saving remote plans. -
text_plan_pathThis is the path to the generated plan in a human-readable format. The path is relative to the Actions workspace. This won't be set if
auto_approveis true while using aremotebackend. -
failure-reasonWhen the job outcome is
failure, this output may be set. The value may be one of:apply-failed- The Terraform apply operation failed.plan-changed- The approved plan is no longer accurate, so the apply will not be attempted.
If the job fails for any other reason this will not be set. This can be used with the Actions expression syntax to conditionally run steps.
-
Terraform Outputs
An action output will be created for each output of the terraform configuration.
For example, with the terraform config:
output "service_hostname" { value = "example.com" }
Running this action will produce a
service_hostnameoutput with the same value. See terraform-output for details.
-
GITHUB_TOKENThe GitHub authorization token to use to fetch an approved plan from a PR. The token provided by GitHub Actions can be used - it can be passed by using the
${{ secrets.GITHUB_TOKEN }}expression, e.g.env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
The token provided by GitHub Actions will work with the default permissions. The minimum permissions are
pull-requests: write. It will also likely needcontents: readso the job can checkout the repo.You can also use a Personal Access Token which has the
reposcope. This must belong to the same user as the token used by the terraform-plan action- Type: string
- Optional
-
TERRAFORM_CLOUD_TOKENSAPI tokens for terraform cloud hosts, of the form
<host>=<token>. Multiple tokens may be specified, one per line. These tokens may be used with theremotebackend and for fetching required modules from the registry.e.g for terraform cloud:
env: TERRAFORM_CLOUD_TOKENS: app.terraform.io=${{ secrets.TF_CLOUD_TOKEN }}
With Terraform Enterprise or other registries:
env: TERRAFORM_CLOUD_TOKENS: | app.terraform.io=${{ secrets.TF_CLOUD_TOKEN }} terraform.example.com=${{ secrets.TF_REGISTRY_TOKEN }}
- Type: string
- Optional
-
TERRAFORM_SSH_KEYA SSH private key that terraform will use to fetch git module sources.
This should be in PEM format.
For example:
env: TERRAFORM_SSH_KEY: ${{ secrets.TERRAFORM_SSH_KEY }}
- Type: string
- Optional
-
TERRAFORM_PRE_RUNA set of commands that will be ran prior to
terraform init. This can be used to customise the environment before running terraform.The runtime environment for these actions is subject to change in minor version releases. If using this environment variable, specify the minor version of the action to use.
The runtime image is currently based on
debian:bullseye, with the command run usingbash -xeo pipefail.For example:
env: TERRAFORM_PRE_RUN: | # Install latest Azure CLI curl -skL https://aka.ms/InstallAzureCLIDeb | bash # Install postgres client apt-get install -y --no-install-recommends postgresql-client
- Type: string
- Optional
-
TERRAFORM_HTTP_CREDENTIALSCredentials that will be used for fetching modules sources with
git::http://,git::https://,http://&https://schemes.Credentials have the format
<host>=<username>:<password>. Multiple credentials may be specified, one per line.Each credential is evaluated in order, and the first matching credentials are used.
Credentials that are used by git (
git::http://,git::https://) allow a path after the hostname. Paths are ignored byhttp://&https://schemes. For git module sources, a credential matches if each mentioned path segment is an exact match.For example:
env: TERRAFORM_HTTP_CREDENTIALS: | example.com=dflook:${{ secrets.HTTPS_PASSWORD }} github.com/dflook/terraform-github-actions.git=dflook-actions:${{ secrets.ACTIONS_PAT }} github.com/dflook=dflook:${{ secrets.DFLOOK_PAT }} github.com=graham:${{ secrets.GITHUB_PAT }}
- Type: string
- Optional
This example workflow runs for every push to master. If the commit came from a PR that has been merged, applies the plan from the PR.
name: Apply
on:
push:
branches:
- master
jobs:
apply:
runs-on: ubuntu-latest
name: Apply approved plan
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: terraform apply
uses: dflook/terraform-apply@v1
with:
path: my-terraform-configThis example workflow runs for every push to master. Changes are planned and applied.
name: Apply
on:
push:
branches:
- master
jobs:
apply:
runs-on: ubuntu-latest
name: Apply terraform
steps:
- name: Checkout
uses: actions/checkout@v2
- name: terraform apply
uses: dflook/terraform-apply@v1
with:
path: my-terraform-config
auto_approve: trueThis example workflow runs every morning and updates a TLS certificate if necessary.
name: Rotate certs
on:
schedule:
- cron: "0 8 * * *"
jobs:
apply:
runs-on: ubuntu-latest
name: Rotate certs
steps:
- name: Checkout
uses: actions/checkout@v2
- name: terraform apply
uses: dflook/terraform-apply@v1
with:
path: my-terraform-config
auto_approve: true
target: |
kubernetes_secret.tls_cert_public
kubernetes_secret.tls_cert_privateThis workflow applies a plan on demand, triggered by someone
commenting terraform apply on the PR. The plan is taken
from an existing comment generated by the dflook/terraform-plan
action.
name: Terraform Apply
on: [issue_comment]
jobs:
apply:
if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, 'terraform apply') }}
runs-on: ubuntu-latest
name: Apply terraform plan
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v2
with:
ref: refs/pull/${{ github.event.issue.number }}/merge
- name: terraform apply
uses: dflook/terraform-apply@v1
with:
path: my-terraform-configThis example retries the terraform apply operation if it fails.
name: Apply plan
on:
push:
branches:
- master
jobs:
plan:
runs-on: ubuntu-latest
name: Apply terraform plan
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: terraform apply
uses: dflook/terraform-apply@v1
continue-on-error: true
id: first_try
with:
path: terraform
- name: Retry failed apply
uses: dflook/terraform-apply@v1
if: ${{ steps.first_try.outputs.failure-reason == 'apply-failed' }}
with:
path: terraform
auto_approve: true