9

I am setting up an Azure pipeline for a Node app with Jest being used to test APIs and integration. The source code lives on Azure DevOps and the code is deployed in Azure Portal. When I run the tests, it fails in the pipeline as the .env is never checked in the remote repository. The environment variables are living in the Azure Portal in runtime though configuration so the pipeline cannot really access it.

What is some ways to have access or create new location for the environment variables in order for my tests to run the the virtual machine?

My current solution (which I don't know if its right) is to create a variable group and redefine all my environment variables so the pipeline can read the variables also described here: https://damienaicheh.github.io/azure/devops/2019/09/04/how-to-use-variables-inside-your-azure-devops-builds-en.html

My questions are:

  1. Is this correct? Any of the stored variables here have nothing to do with the build neither they are inputs to run commands, rather all my environment variables are required inside the source code so I can test in a virtual machine (Ex: base_url, apiKeys, etc).
  2. If this is right, how can I possible avoid re-writting and re-assigning all the value in the pipeline? Can I source the entire variable group and the source code can interpret? I want to avoid like this
- env
  - API_KEY: $(apiKey)
  - MAPS_KEY: $(mapsKey)  
  - CLIENT_KEY: $(clientKey)  
  - CLIENT_SECRET: $(clientSecret)
  - 
  -
  - and so on... 


// looking for something like this
   -env: myVariableGroup
  1. Any leads to a post, articles to a better solution? I was thinking of using key vault but I think it will essentially the same that I have to import one-by-one.
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Marvin
  • 213
  • 1
  • 3
  • 9

1 Answers1

14

Pipeline variables are mapped to env variables automatically so no need to extra work. There is only one exception - secrets. You must mapped them explicitly

steps:
- script: echo $MYSECRET
  env:
    MYSECRET: $(Foo)

So all values from declaration, group or template are mapped to env vars

vars.yaml

variables:
  variableFromTemplate: 'valueFromTemplate'

build.yaml

variables:
  - group: PROD
  - name: variableFromDeclaration
    value: 'valueFromDeclaration'
  - template: vars.yaml  

pool:
  vmImage: 'ubuntu-latest'

steps:
- script: env | sort
- script: | 
    echo $VARIABLEFROMDECLARATION
    echo $VARIABLEFROMGROUP
    echo $VARIABLEFROMTEMPLATE
- pwsh: |
    
    $url = "https://dev.azure.com/thecodemanual/$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)?api-version=5.1"
    $build = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Bearer $env:MY_SECRET"}
    Write-Host "Pipeline = $($build | ConvertTo-Json -Depth 100)"

    $status = $build.status
    Write-Host $status
  name: initial
  env: 
    MY_SECRET: $(System.AccessToken)

enter image description here

enter image description here

So for each step you need to define secrets in env section. As a workaround you my try use container jobs and define env mapping on container level.

resources:
  containers:
  - container: string  # identifier (A-Z, a-z, 0-9, and underscore)
    image: string  # container image name
    options: string  # arguments to pass to container at startup
    endpoint: string  # reference to a service connection for the private registry
    env: { string: string }  # list of environment variables to add
    ports: [ string ] # ports to expose on the container
    volumes: [ string ] # volumes to mount on the container
    mapDockerSocket: bool # whether to map in the Docker daemon socket; defaults to true
    mountReadOnly:  # volumes to mount read-only - all default to false
      externals: boolean  # components required to talk to the agent
      tasks: boolean  # tasks required by the job
      tools: boolean  # installable tools like Python and Ruby
      work: boolean # the work directory
Krzysztof Madej
  • 32,704
  • 10
  • 78
  • 107
  • Thanks! It looks like it make sense, I can access the variables but not the secret. However, even when I explicitly define the secret, It prints as ***** as it is not accessible in task. https://github.com/microsoft/azure-pipelines-agent/issues/145 – Marvin Sep 24 '20 at 01:27
  • 1
    Printing `***` is expected. Azure DevOps doesn't allow you to put your secret in the logs. There is a way to trick that, but you shouldn't. I extended my example to show you that mapping secrets works. I added example which you may also run with some changes like organization and project and check it out. – Krzysztof Madej Sep 25 '20 at 04:39
  • If not using docker containers, are there no other possible way to access the secret variables from the library to the app level? I've tried setting the task.setvariables as well but it seems like the variables are only accessible on the build scope. – Marvin Oct 01 '20 at 00:39
  • They are through env variables, and as we need we need to map them explicitly. But you know they are env variables, they are not going to be replaced in you code when you read them. So when you take your poackage outside of this env and run somewhere else you need to set env variables there. @Marvin does my answer help you solve your issue? – Krzysztof Madej Oct 01 '20 at 04:26