Azure DevOps: Getting variable value by concatenating other variables'value as task input - azure-devops

I have my release pipeline Variables tab set like:
I would like to access my123 variable in task's display name by concatenating initialVariable's result.
Outputs
I have tried so far referencing only initialVariable and it returned proper value in Job's display name.
But when I try to create my123 value by using initialVariable(=123), I am not getting proper value (was hoping that $(initialVariable) would convert to 123 and $(my123) would get proper "finalValue").

Azure DevOps: Getting variable value by concatenating other variables'value as task input
This is a known issue. Because the value of nested variables (like $(my$(initialVariable)) are not yet supported in the build/release pipelines.
Check my other thread for some details.
The workaround is add a Run Inline Powershell task to set the variable based on the input pipeline variables, just like Josh answered.
For you case, I test it by following Powershell scripts:
if ($(initialVariable)-eq "123")
{
Write-Host "##vso[task.setvariable variable=my123]finalvalue"
}
else
{
Write-Host "##vso[task.setvariable variable=my123]otherValue"
}
Then we could get the variable my123 based on the value of variable initialVariable in following task, I add command line task to display the value:
In the result, the value in the command line task is correct finalvalue. But the display name is still $(my123):
Important:
That is also the question in your comment. This behavior is expected. That because the variable in the display name is just to get the predefined value. It's static acquisition, not dynamic. The variable my123 is assigned when running powershell. The static variable my123 in the display name does not go in to the environment where the powershell code is running.
So, the variable my123 in the title could not get the value in the task powershell. But other task could use it very well.
Hope this answer clean your puzzle.

It's ugly, but...
Like I mentioned in my comment, I don't think you're going to get this to work in the UI by default.
Luckily you can use PowerShell to hack this together if your REALLY need the ability to address a variable name based on the value of another variable.
All the variables (secrets are handled a little differently) in your build or release pipeline definition are made available to your powershell script FILE (not inline) via environment variables (ie. $env:initialVariable).
Suppose your situation is thus:
selector = selectable1 //this is the value that can change
selectable1 = theFirstSelection
selectable2 = theSecondSelection
selectable3 = theThirdSelection
In this case (assuming I understand your request) you want to be able to change the value of the selector and force tasks to access the appropriate selectable variable.
So...
Define a new variable in your pipeline.
selector = selectable1 //this is the value that can change
selected = "" //this is the variable you use in your tasks
selectable1 = theFirstSelection
selectable2 = theSecondSelection
selectable3 = theThirdSelection
Write a VariableSelection.ps1 script. This powershell script will be what you need to run to assign the value of $(selected) before it gets used.
# VariableSelection.ps1
Write-Host "select variable: $env:selector"
$selectedValue = (gci env:"$env:selector").value
Write-Host "##vso[task.setvariable variable=selected]$selectedValue"
Note: it is my observation that if you write this script inline, it will not work b/c the environment variable functionality is different for scripts run from a file.
Given the value of $(selector) is selectable2, when the script is run, then the value of the $(selected) will be theSecondSelection.
Example in a Pipeline
Powershell
YAML
# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml
trigger:
- master
pool:
name: Hosted VS2017
variables:
- name: "selector"
value: "var1"
- name: "selected"
value: ""
- name: "var1"
value: "var1_value"
- name: "var2"
value: "var2_value"
steps:
- task: PowerShell#2
inputs:
filePath: '$(build.sourcesdirectory)/varSelector.ps1'
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
Write-Host "env:selected: $env:selected"
Write-Host "selected: $(selected)"
Results

Related

Creating build Variables for azure devops build pipeline from external file through Terraform

I am creating Azure devops build pipeline through terraform and want my build variables to get passed through an external file while the build gets created. The same terraform code will be used to create pipelines of different templates, so accordingly the variables will also change, so inorder to make it reusable for all pipelines i want my terraform codes to take the build pipelines variables from external file and create it. Can't go with variable groups as well. So if any other process please advice.
Any help or advice would be really appreciated.
resource "azuredevops_build_definition" "build" {
project_id = azuredevops_project.project.id
name = "Sample Build Definition"
path = "\\ExampleFolder"
ci_trigger {
use_yaml = true
}
variable {
name = "PipelineVariable"
value = "Go Microsoft!"
}
variable {
name = "PipelineSecret"
secret_value = "ZGV2cw"
is_secret = true
}
the variables that above passed should instead get passed from external file.
You just need to define terraform variables for the values you require and use them in the resource:
variable "buildinfo"{ type = string default = "my value" }
and in the resource you just use:
.... value = var.buildinfo ....
you can pass the variable value for each run with a tfvars file or in your pipeline variables if you use a CI
you could do it like this:
Terraform:
variable "PipelineVariable"" {
}
Then define variables in the Pipeline like TF_VAR_PipelineVariable or in any stage you call a file (example file: .env) with source .env:
.env:
export TF_VAR_PipelineVariable=CONTENT

variable in deployment job doesnt extend value

I am having trouble getting a deployment job in a template to expand a variable it is given via a parameter. Ive used some short hand stuff below.
If you want to see the code, there is a prototype that shows the problem at https://github.com/ausfestivus/azureDevOpsPrototypes
The pipeline looks like this:
stage00
buildjob00
task produces output vars (name: taskName.VAR_NAME)
buildjob01
task is able to reference the variable and retrieve/display the variable value via
dependency notation. [dep.buildjob00.taskName.VAR_NAME]
template:
parameters:
bunchOfVarsAsSequenceFormat:
var1: [dep.buildjob00.taskName.VAR_NAME]
var2: [dep.buildjob00.taskName.VAR_NAME]
template contains:
buildjob02
this build job will see the variables values fine
deplomentjob00
this deploy job will see the variable names but contain empty values
Apologies if this is not well explained, hopefully the above prototype helps illustrate it better than the pseudo code above.
What a super help you shared your YAML scripts here! Otherwise, it's too difficult to understand your structure:-)
To display the variable in tmpl: deploy, you need change its corresponding dependsOn as job00, rather than templateJob.
- deployment: templateDeploy
displayName: 'tmpl: deploy'
continueOnError: false
dependsOn: job00
Then you would see the value could display successfully:

How to receive Revision in Azure Pipelines YAML build definition

I created a new build with Azure Pipelines (Azure DevOps) and it worked really well.
Usually, you use $(Rev:.r) to get the revision in the build. Unfortunately, it seems the variable isn't replaced/set in the build steps. The only place where you can use it is the name: property in the YAML document.
Now I set it in the name and extract it in some PowerShell, which isn't necessary if you can get it via an environment variable.
How do I get the Revision (like $(Rev)) in the new builds (outside of the name: property in the YAML document)?
(The Build Agents running on-premise, inside Docker - but this shouldn't affect the things above)
You can't get the revision number without parsing, it is not stored as a separate field somewhere or in an environment variable.
The $(Rev:.r) portion instructs Azure DevOps to come up with the first number that makes the build number unique (and, in that specific example, put a dot in front of it).
Like you said, the only way is to use PowerShell script to get the value:
$buildNumber = $Env:BUILD_BUILDNUMBER
$revision= $buildNumber.Substring($buildNumber.LastIndexOf('.') + 1)
Edit:
You can install the Get Revision Number extension that does it.
Another possible solution to the above problem could be to use counter expression for ex: we difine the variable and use it in a task to build nuget package.
variables:
counterVar: $[counter($(versionVariable),0)]
.......
- task: CmdLine#2
inputs:
script: >
nuget pack ClassLibrary1/ClassLibrary1.csproj
-OutputDirectory $(Build.ArtifactStagingDirectory)
-NonInteractive
-Properties Configuration=release
-Version $(versionVariable).$(counterVar)
-Verbosity Detailed
-IncludeReferencedProjects
Here versionVariable is a custome variable defined in pipelines->variables.And the seed value is 0(2nd param to counter).
It works as below
Let's assume the versionVariable is 1.19
Build Run 1 counterVar will be 0.
Build Run 2 counterVar will be 1.
Now say we change the versionVariable to 1.20
Build Run 3 counterVar will be 0.
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops
Check the counter expression in above link it reset its value for diff prefix.
P.S. Benefit of using counter over $(Rev:r) is that it can start from 0 unlike $(Rev:r)

Passing variables between PS stages on different agents in jenkins pipeline

I have a jenkins pipeline with two (powershell) stages, each running on a different node/slave.
I'm trying to set a variable during the first stage (on node 1) and use it afterwards on the next stage (on node 2) - however, I couldn't find a way to pass this variable between them.
It's worth clarifying that this variable is being set dynamically in stage 1, meaning that solutions like declaring an env:var using script or def or environment didn't help (I tried many combinations) - the value can vary every time I run the pipeline.
I tried setting a new value for env var in stage 1, but it looks like it only affects its value in the context of the running stage.
(yes, it must be in powershell and on different nodes)
this is the basic idea of the pipeline (which doesn't work)
pipeline {
agent { label 'Node1' }
stages{
stage('Calculate'){
steps {
git changelog: false, credentialsId: 'user', poll: false, url: 'https://mygit.com/myrepo.git'
powershell '''
$currentVersion=[version]$(git describe --tags)
$newVersion=New-Object -TypeName System.Version($currentVersion.Major, $currentVersion.Minor, $currentVersion.Build, ($currentVersion.Revision + 1))
'''
}
}
stage('Act'){
agent { label 'Node2' }
steps {
powershell "Write-Host $env:newVersion"
}
}
}
}
Any ideas?
Thanks!
In my scripts I define a var above the pipeline tag and then I use
returnValue = powershell returnStdout: true, script: '...'
to generate my Powershell output.
'returnStdout: true'
is the key to receive your output from your PowerShell script.
In another stage I use bat to call a PowerShell script and sned my var to it:
bat "powershell -File script.ps1 ${returnValue}"
Hope that helps.
Greetings

How to replace variables of JSON file in Team Services?

I'm stuck with a release variable substitution of an angular project. I have a settings.json file which I would like to replace some variables:
{
test : "variable to replace"
}
I tried to find some custom task on the marketplace but all of the tasks seems to work only with xml files for the web.config.
I use the "Replace tokens" from the Marketplace https://marketplace.visualstudio.com/items?itemName=qetza.replacetokens
You define the desired values as variables in the Release Definition and then you add the Replace Tokens task and configure a wildcard path for all target text files in your repository where you want to replace values (for example: **/*.json). The token that gets replaced has configurable prefix and postfix (default are '#{' and '}#'). So if you have a variable named constr you can put in your config.json
{
"connectionstring": "#{constr}#"
}
and it will deploy the file like
{
"connectionstring": "server=localhost,user id=admin,password=secret"
}
The IIS Web App Deploy Task in VSTS Releases has JSON variable substitution under *File Transforms & Variable Substitution Options.
Provide a list of json files and JSONPath expressions for the variables that need replacing
For example, to replace the value of ‘ConnectionString’ in the sample below, you need to define a variable as ‘Data.DefaultConnection.ConnectionString’ in the build/release definition (or release definition’s environment).
{
  "Data": {
    "DefaultConnection": {
      "ConnectionString": "Server=(localdb)\SQLEXPRESS;Database=MyDB;Trusted_Connection=True"
    }
  }
}
You can add a variable in release variables Tab, and then use PowerShell task to update the content of your settings.json.
Assume the original content is
{
test : "old
}
And you want to change it to
{
test : "new"
}
So you can replace the variable in json file with below steps:
1. Add variable
Define a variable in release variable tab with the value you want to replace with (variable test with value new):
2. Add PowerShell task
Settings for powershell task:
Type: Inline Script.
Inline Script:
# System.DefaultWorkingDirectory is the path like C:\_work\r1\a, so you need specify where your appsettings.json is.
$path="$(System.DefaultWorkingDirectory)\buildName\drop\WebApplication1\src\WebApplication1\appsettings.json"
(Get-Content $path) -replace "old",$(test) | out-file $path