Search code examples
.netpowershellazure-devopsazure-pipelinescicd

Azure DevOps Pipelines: Environment Variables Not Available in dotnet test Command


I'm using Azure DevOps and have an AzureCLI task set up to run integration tests with the dotnet test command. I'm encountering an issue where environment variables set in the task do not seem to be available when dotnet test is executed.

Here is the relevant part of my pipeline configuration:

- task: AzureCLI@2
  displayName: 'Run Integration Tests Inside AZ CLI'
  inputs:
    azureSubscription: ${{ parameters.azureServiceConnection }}
    scriptType: pscore
    scriptLocation: 'inlineScript'
    addSpnToEnvironment: true
    inlineScript: |
      # Commands to set environment variables
      Write-Host "##vso[task.setvariable variable=TENANT_ID;issecret=true]$(tenantId)"
      ...

      $env:TENANT_ID = "$(tenantId)"
      ...

      # Running dotnet test
      dotnet test --configuration $(buildConfiguration) ...

The variables like TENANT_ID are set using ##vso[task.setvariable] and also attempted to be set in the script's session scope using $env: for use in the same script. However, these variables do not seem to be accessible or correctly passed to the dotnet test command.

What could be causing this issue, and how can I ensure that these environment variables are correctly passed to and accessible by the dotnet test command within the same Azure CLI task?

Please note, I require the dotnet test to be inside of the AzureCLI@2 task, to make use of the new AzurePipelinesCredential from the Azure Identity SDK and I would like to have these variables be kept as secret (masked / redacted from logs)


Solution

  • Using pipeline variables set with task.setvariable

    You cannot use a variable set with task.setvariable logging command in the same task where it was set.

    The variable is exposed to the following tasks as an environment variable:

    - task: AzureCLI@2
      displayName: 'Set pipeline variables'
      inputs:
        azureSubscription: ${{ parameters.azureServiceConnection }}
        scriptType: pscore
        scriptLocation: 'inlineScript'
        addSpnToEnvironment: true
        inlineScript: |
    
          # Commands to set environment variables
          Write-Host "##vso[task.setvariable variable=TENANT_ID;issecret=true]$(tenantId)"
          
          ... other commands here
    
    - task: AzureCLI@2
      displayName: 'Run Integration Tests Inside AZ CLI'
      inputs:
        azureSubscription: ${{ parameters.azureServiceConnection }}
        scriptType: pscore
        scriptLocation: 'inlineScript'
        addSpnToEnvironment: true
        inlineScript: |
    
          # Using Powershell syntax to access the variable set in previous task
          # For demonstration purpose only.
          # Value is available as a secret, so its output will be masked
          Write-Host "Tenant ID: " + $Env:TENANT_ID 
    
          # Using macro syntax to access the variable set in previous task
          # For demonstration purpose only.
          # Value is available as a secret, so its output will be masked
          Write-Host "Tenant ID: " + $(TENANT_ID)
          ...
    
          # Running dotnet test
          dotnet test --configuration $(buildConfiguration) ...
    

    Using AzureCLI@2 task with addSpnToEnvironment: true

    When using an AzureCLI@2, if you want to access the service principal details in the script you don't need to set pipeline variables - unless you need to use these details in other tasks as well.

    You can use the servicePrincipalId, servicePrincipalKey or idToken, and tenantId variables in your script.

    Example:

    - task: AzureCLI@2
      displayName: 'Run Integration Tests Inside AZ CLI'
      inputs:
        azureSubscription: ${{ parameters.azureServiceConnection }}
        scriptType: pscore
        scriptLocation: 'inlineScript'
        addSpnToEnvironment: true
        inlineScript: |
    
          # Accessing one of the variables that are accessible with addSpnToEnvironment: true
          # For demonstration purpose only.
          # Value is available as a secret, so its output will be masked
          Write-Host "Service Principal ID: " + $env:servicePrincipalId 
    
          ... other commands here
    

    This is honored only when the Azure endpoint has service principal authentication scheme or workload identity federation authentication scheme.