Detailed-exitcode not returning “2” when changes detected

Running in Azure DevOps. Set the TF cli args for plan as an env variable and running TF plan in Linux bash script task.

Seems the detailed-exitcode is not being picked up and always returning “0” regardless if changes are detected or not.

Trying to set up conditions on TF apply tasks to skip if no changes are detected.

Any ideas ? Tried setting the exitcode flag directly on the command line as well but no difference.

Using latest TF cli client.

The code in Terraform for handling -detailed-exitcode is really pretty trivial.

I’m not saying it’s impossible that there’s a bug somewhere, but unless you provide some pretty thorough details about how you are invoking Terraform, and resulting outputs, it’s easier to believe that something is incorrect in how you are invoking Terraform, and the -detailed-exitcode feature just isn’t being turned on.

Things that you haven’t shown that would be useful:

  • Exact Terraform version
  • Exact Terraform command line
  • Exact Terraform output

You should attempt to reproduce the behaviour outside of Azure DevOps. If you’re able to successfully demonstrate it in a simple shell session, it’ll be a lot easier to share that with this forum, or in a bug report. If you find everything works normally in a simple shell session, but not in Azure DevOps, you’ll have a working and non-working example, and can try to find the problem by looking at the differences.

It seems to work fine for me, running Terraform 1.4.6:

$ terraform plan -detailed-exitcode ; echo $?

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # null_resource.foobar will be created
  + resource "null_resource" "foobar" {
      + id = (known after apply)

Plan: 1 to add, 0 to change, 0 to destroy.


Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply"

Thanks for the prompt reply. Back to work this morning, here are the details.

Running TF 1.46… detailed-exitcode works locally…

> terraform plan -out=plan.tfplan ; echo $?
> Plan: 3 to add, 0 to change, 2 to destroy.
> Saved the plan to: plan.tfplan
> To perform exactly these actions, run the following command to apply:
>     terraform apply "plan.tfplan"
> Releasing state lock. This may take a few moments...
> 2


> Caching tool: terraform 1.4.6 x64
> Prepending PATH environment variable with directory: /opt/hostedtoolcache/terraform/1.4.6/x64
> Verifying Terraform installation...
> /opt/hostedtoolcache/terraform/1.4.6/x64/terraform version
> Terraform v1.4.6 on linux_amd64

Bash script running TF plan:

> cd ./${{ parameters.component_folder_path }}
>               echo "Current directory: $(pwd)"
>               echo "Running plan with $(TF_CLI_ARGS_PLAN) options..."
>               terraform plan -out=$(tfplanfile_name)
>               exitcode=$?
>               echo "Detailed exitcode"
>               echo $exitcode
>               # on changes detected, succeed; otherwise fail
>               if [ $exitcode -eq 2 ]; then 
>                  echo '##vso[task.setvariable variable=changesDetected]true'
>               fi

Output of the above:

> Current directory: /agent/_work/1/s/non-prod/035-app-common-services
> Running plan with '-input=false -no-color -compact-warnings -detailed-exitcode' options...
> Plan: 1 to add, 0 to change, 0 to destroy.
> Detailed exitcode
> 0
> Finishing: Plan common-services

I was able to get this working ok locally… something in the ADO variable group, which injects the variables as env variables is causing an issue…

I’ll start digging into that

That said, I’m still seeing colored output

I think Terraform CLI might be expecting your environment variable to be called TF_CLI_ARGS_plan, with plan in lowercase, because that’s the true name of the subcommand you are running. (terraform PLAN would not be accepted by Terraform.)

With that said: since your script is written to depend on -detailed-exitcode being set, architecturally it is probably more readable to place that particular option directly inline in the command you are running:

echo "Running plan with $(TF_CLI_ARGS_plan) options..."
terraform plan -out="$(tfplanfile_name)" -detailed-exitcode

…that way the option which turns that on is defined closer to the code that’s using it, so future maintenance is less likely to accidentally break this and make $exitcode show as zero.

I think I remember learning at some point that some part of Azure is designed to only support environment variables with names written entirely in uppercase, despite that being a faulty assumption for software running on Unix systems where environment variable names are case-sensitive… but I’m not sure if it was Azure DevOps in particular which had that limitation. If you have trouble defining an environment variable named exactly TF_CLI_ARGS_plan in Azure DevOps, I’d suggest renaming this environment variable to something specific to your Azure DevOps job and then assigning its value to the name Terraform is expecting “just in time” when running Terraform.

For example, if you define an environment variable in your Azure DevOps job called TERRAFORM_PLAN_ARGS then you could run Terraform like this in your script:

TF_CLI_ARGS_plan="$TERRAFORM_PLAN_ARGS" terraform plan -out="$(tfplanfile_name)" -detailed-exitcode
1 Like

Using these in variable groups, and Azure devops uppercases them when setting them up in the environment.

That said, I had no need really, as you pointed out, to set these in the env tf_cli_args as I was only using the options in a specific location in code… I’m using yaml templates so the plan is only being called from one place, and used by multiple pipelines.

In-lining the options directly on the command line with the tf plan got it working. And as you said, more readable.

Thanks again