be9inn3r
be9inn3r

Reputation: 113

Output variable not working as expected in bash (azure pipelines)

I am new in Azure Pipelines.

topic 1:

I am trying to set my terraform pipeline in Azure Devops Pipelines to be set as: when TF Plan job finishes and has the result like "Changes detected", then to run the TF Apply job. If the TF Plan job contains "No changes" in the -out=terraform.plan , the job should finish and then Tf Apply job should be skipped.

I am trying to use that specific variable ##vso [task.setvariable var=myvar;]abc but in my context is not working.

Why? I tried a lot of methods to export somehow a variable and to use the variable between jobs (Use outputs in a different stage) but not working.

My case and problem is below:

- task: AzureCLI@2
  name: A
  displayName: "Run tf ${{ parameters.action }}"
  inputs:
    scriptType: 'bash'
    scriptLocation: 'inlineScript'
    inlineScript: |
      if [ ${{ parameters.action }} = "plan" ]; then
          echo "Running terraform plan..."
          terraform azure plan -out=terraform.plan
          changes=$(terraform show -no-color terraform.plan | grep -E "No changes.")
          echo "Checking for Changes variable [$changes]"
          if [ -n "$changes" ]; then
            echo "No changes detected. Exiting without further actions."
            echo '##vso[task.setvariable variable=anyTfChanges]'$changes
            echo "anyTfChanges $anyTfChanges"
            exit 0
          else
            echo "Changes detected. Setting/exporting anyTfChanges=True"
            echo '##vso[task.setvariable variable=anyTfChanges]'$changes
          fi
      else
          echo "Value of anyTfChanges is $anyTfChanges"
          echo "Running terraform apply..."
          terraform apply -input=false -auto-approve
      fi

    addSpnToEnvironment: true
    workingDirectory: '${{ parameters.workingDirectory }}'

The problem is that even if I use bash script (scriptType: 'bash'), the command echo '##vso[task.setvariable variable=anyTfChanges]'$changes is not interpreted as I wish and it is not setting a variable.

I have tried to see why? I think that because I use task: AzureCLI@2 and when the job starts in pipeline, it says:

Pool: Azure Pipelines
Image: ubuntu-20.04
Queued: Just now [manage parallel jobs]
Agent: Azure Pipelines 2
Started: Just now

The problem can be Agent used? Have anyone used this ##vso command in this type how I have?

I tried with to export by simple bash command, but not working to reference that variable for the Apply job. I see in this case ##vso [task.setvariable var=myvar]abc is the option to achieve my goal (to skip apply job if plan has "no changes" in azure pipelines).

Upvotes: 1

Views: 717

Answers (1)

Scott Richards
Scott Richards

Reputation: 766

When you create a variable in task using ##vso[task.setvariable variable=anyTfChanges]'$changes, the variable will only become available on subsequent steps in the same yaml job.

Two sidenotes to your question based on your code snippet:

  • the syntax you are using to reference the created variable in your code snippet is incorrect. To reference the variable in script, one option you can use is $(varName).
  • your logic flow seems a bit strange. anyIfChanges is defined in the if part of your if/else statement. You are also trying to reference the variable created in the if in your else segment. This will not work.

See example yaml below on when varTwo becomes available:

variables:
- name: varOne
  value: value1 

steps:
- task: AzureCLI@2
  displayName: "Create and print vars test"
  inputs:
    azureSubscription: $(serviceConnection)
    scriptType: 'bash'
    scriptLocation: 'inlineScript'
    inlineScript: |

        echo '##vso[task.setvariable variable=varTwo]'value2

        echo $(varOne)    # Output = value1
        echo $(varTwo)    # Output = varTwo: command not found

- task: AzureCLI@2
  displayName: "Print vars test"
  inputs:
    azureSubscription: $(serviceConnection)
    scriptType: 'bash'
    scriptLocation: 'inlineScript'
    inlineScript: |

        echo $(varOne)    # Output = value1
        echo $(varTwo)    # Output = value2

If you want to make your variable available in different jobs and stages, you can add ;isOutput=true. Read on how to do that here.

Upvotes: 0

Related Questions