Dismiss approval before plan
The plan action dismisses approvals immediately after running terraform plan, forcing reviewers to approve after seeing the plan results.
This feature is enabled by default, but it can be disabled.
dismiss_approval_before_plan:
enabled: true # true by default
When a PR created by an app such as Renovate results in "No Change", approvals are not dismissed.
This is to avoid blocking automatic merging of such PRs.
The apps are configured by auto_apps.logins. For details, see Auto Apps (Renovate, Dependabot).
Skip dismissing approvals if the plan result is unchanged
The plan action doesn't dismiss approvals if the plan result is the same as the previous plan of the target on the pull request's head branch. For example, when a pull request branch is updated with the base branch and the plan result doesn't change, approvals are kept. This feature is enabled by default, but it can be disabled.
dismiss_approval_before_plan:
skip_if_unchanged:
enabled: true # true by default
# Optional. The AWS KMS HMAC key to hash the plan result.
aws_kms_key_id: arn:aws:kms:us-east-1:123456789012:key/xxx
# Optional. The region of the KMS key.
# By default, the region in the key ARN, or the region from the environment (AWS_REGION etc).
aws_region: us-east-1
How the plan result is compared
The plan action doesn't store or read the plan file or the plan JSON to compare plan results, so this works with plan files in S3 where the plan workflow can't read the plan file.
Instead, it computes a one-way hash of the plan result and stores it in the plan metadata artifact (terraform_plan_meta_<target>).
Then it compares the hash with the one in the metadata artifact of the latest previous workflow run of the target on the same head branch.
The hash is computed from the following things that affect apply:
resource_changesofterraform show -jsonwhose actions aren'tno-op(plus moved and imported resources)output_changesofterraform show -jsonwhose actions aren'tno-op- the providers of the resource changes (
provider_name) - the target and whether the plan is a destroy plan
- the git tree object id of the working directory at
HEAD. It covers files that aren't in the plan result, such as scripts run by provisioners - the content of
.terraform.lock.hclin the working directory at plan time. It covers the selected providers even if the lock file isn't committed. Terraform guarantees that apply uses the same providers as the plan file
Fields that change even if the plan result is the same, such as timestamp, terraform_version, and prior_state, are excluded.
Approvals are dismissed as before in the following cases:
- the plan result has changed
- no previous plan hash is found (the first run, the artifact expired, and so on)
- the hash couldn't be computed or the previous hash couldn't be got
Files outside the working directory, such as local modules and scripts in other directories, aren't covered unless they change the plan result. If you need to dismiss approvals when such files change, enable the branch protection rule (or ruleset) "Dismiss stale pull request approvals when new commits are pushed" too.
Hash method
- With
aws_kms_key_id, the hash is an HMAC-SHA256 generated by the AWS KMS key, including sensitive values. The key never leaves AWS KMS, and people without access to the key can't brute-force values from the hash. Changes of only sensitive values are also detected. - Without
aws_kms_key_id, sensitive values are masked and then the result is hashed with SHA-256. Sensitive values can't be brute-forced from the hash, but changes of only sensitive values aren't detected and approvals aren't dismissed. Note that such changes are displayed as(sensitive value)in the plan result, so reviewers can't see them anyway.
Tfaction doesn't support passing a raw HMAC key via GitHub Secrets, because code running in the plan workflow could exfiltrate the key.
To use AWS KMS, create a KMS key whose key spec is HMAC_256 and key usage is GENERATE_VERIFY_MAC, and allow the IAM role of the plan workflow to call kms:GenerateMac on the key.
kms:VerifyMac isn't needed.
Required permissions
The plan workflow lists and downloads artifacts of previous workflow runs, so the GitHub token needs the actions:read permission.
Without the permission, approvals are dismissed as before and a warning is output.
To disable this feature, set enabled to false:
dismiss_approval_before_plan:
skip_if_unchanged:
enabled: false