how to add variables together in VSTS - azure-devops

I want to use a variable which is composed of another vsts variable and text, for instance:
vnetname = $vnet_prefix + "vnetid"
However i get an error saying that "A positional parameter cannot be found that accepts argument +.
Anyone advise?

If you mean use the variable in build/release processes, then you can add a variable like this (reference below screenshot):
vnetname = $(vnet_prefix)_vnetid
Then you can use the variable $vnetname or $(vnetname) directly, see Build variables-Format for how to use the variables in different tools.
Alternatively you can pass the value with Logging Commands:
Copy and paste below strings then save as *.ps1 file:
$value = $env:vnet_prefix + "vnetid"
Write-Host "##vso[task.setvariable variable=vnetname]$value"
Check in the PS file
Add a PowerShell task to run the PS file
Use the variable $vnetname in later steps

Related

Dynamic variable name in VSTS (Azure DevOps) pipeline

I have a pipeline variable called TestVariable.
I can easily access this variable from a PS script like so:
write-host $(TestVariable)
But if the name of that variable was dynamic, is there any way I can access the variable value from PS?
For example, the name of the variable would go into a string variable. I've tried these combinations as experiments...they just return the variable name, not the value (not surprisingly):
$varname="TestVariable"
write-host $($varname)
write-host $("$varname")
write-host $"($varname)"
write-host $("($varname)")
I think the answer is no, but I want to be sure. Any help much appreciated!
Edit - note
Both answers answer the question but don't solve my problem. After trying the solutions I realized I missed an additional complication which the answers don't help with unfortunately. Am noting here in case someone tries to do something similar.
The extra complication is, the value of the variable is set during the release (I'm trying to access ARM template output variables).
I thought I may be able to hit the API and get the 'live' variable value but unfortunately the release data does not exist (from the API) until the release completes.
So when I call this during a release:
https://vsrm.dev.azure.com/{company}/{project}/_apis/release/releases/$($releaseId)?api-version=5.0
I get "Release with ID 38 does not exist".
Late to the party, but figure I'd share.
As mentioned in the Defined Variables doc, pipeline variables are accessible through
the environment variables. While $(varname) gets processed before the task starts, $env:varname can be invoked mid-run. So you can cheat by using:
Write-Host ('$env:'+"$(varname)" | Invoke-Expression)
The task will resolve $(varname) into its value before the task begins. So the script reads as
Write-Host ("$env:TestVariable" | Invoke-Expression)
And it'll spit out the same as calling $(TestVariable).
Though you do need to respect the rules, such as " " and "." -> "_".
Dynamic variable name in VSTS (Azure DevOps) pipeline
Agree with Krzysztof Madej. There is no out of box way to achieve this.
That because the nested variables (like $($varname) are not yet supported in the build pipelines.
To resolve this issue, you could use the Definitions - Get to get the value of Dynamic variable:
GET https://dev.azure.com/{organization}/{project}/_apis/build/definitions/{definitionId}?api-version=5.1
Below is my test powershell script:
$varname="TestVariable"
$url = "https://dev.azure.com/YourOrganizationName/YourtProjectName/_apis/build/definitions/<definitionsId>?api-version=5.0"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
$VFDV= $pipeline.variables.$varname.value
Write-Host This is Value For Dynamic Variable: $VFDV
The output:
Hope this helps.
This is not possible directly in YAML but you can use for instance az cli. With this you can set programatically a variable name a get value of it
$variableName = "some"
az pipelines variable list --org "https://dev.azure.com/thecodemanual" --project "DevOps Manual" --pipeline-name "DevOps Manual-CI" --query ($variableName + '.value')
$variableName = "test"
az pipelines variable list --org "https://dev.azure.com/thecodemanual" --project "DevOps Manual" --pipeline-name "DevOps Manual-CI" --query ($variableName + '.value')
Now you can use this code in a powershell task to fetch value of variable.
Here you have info how to install extension.
I know its too late but I can tell you a perfect solution. as we know all the pipeline variables are available as environment variables so we can access the values as below
var=$(TestVariable)
upper= ${var^^} //convert the variable to uppercase as env variables are upper
echo ${!upper}
Please note the above solution is tested and works in bash only. I haven't written for PS

Can't access build variables from powershell script

I'm trying to use the Build variables in a script. According to this documentation I should be able to use the following:
Write-Host "BUILD_DATE: $Env:BUILD_DATE"
Write-Host "BUILD_REV: $Env:BUILD_REV"
However, I only get the following output
BUILD_DATE:
BUILD_REV:
I've also tried this syntax:
Write-Host "BUILD_DATE: $(Env:BUILD_DATE)"
Write-Host "BUILD_REV: $(Env:BUILD_REV)"
Write-Host "BUILD_DATE: $(Build.Date)"
Write-Host "BUILD_REV: $(Build.Rev)"
But the first segment gives The term 'Env:BUILD_DATE' is not recognized and the second segment gives The term 'Build.Date' is not recognized
How can I use the build variables in my script?
Disclaimer: I know virtually nothing about Azure pipelines, so my answer is based on reading the docs. Do let us know if I got things wrong.
Your first command uses the correct syntax for referencing environment variables in PowerShell (also inside an expandable (double-quoted) string).
(The other commands, based on subexpression operator $(...), mistakenly try to execute commands named Env:BUILD_DAT, ... rather than referencing variables.)
Your problem seems to be that the targeted environment variables do not exist.
The list of predefined variables that are exposed as environment variables does not contain variables named Build.Date / $env:BUILD_DATE and Build.Rev / $env:BUILD_REV.
By contrast, variables named Date and Rev seemingly do exist - as you state, they are used in the default format definition for the Build.BuildNumber / $Env:BUILD_BUILDNUMBER build variable, $(Date:yyyyMMdd)$(Rev:.r) - but are seemingly of a different kind not exposed as env. vars. (unlike Build.BuildNumber / $Env:BUILD_BUILDNUMBER itself, which is exposed).
(I don't know where these variables are defined or how they are classified, and where this is documented - do tell us if you know.)
A quick workaround would be to split the value of $Env:BUILD_BUILDNUMBER into its constituent parts:
# Split the build number into date and revision, by "."
$date, $rev = $Env:BUILD_BUILDNUMBER -split '\.'
"BUILD_DATE: $date"
"BUILD_REV: $rev"

How can I access pre-defined Release Management variables in a Powershell script?

According to the documentation, there are a bunch of predefined variables available for the tasks which run in an environment for Release Management. How do I access these variables from within a Powershell script?
For example: the System.TeamProject variable is defined, and should return the current TFS TeamProject. However, when I write:
Write-Host "environment var: $env:System.TeamProjectId"
The output in the log file is:
2016-06-07T09:26:49.5537161Z environment var: release.TeamProject
However, in the Initialize log file, the following is displayed:
4 2016-06-07T09:26:40.4121001Z Environment variables available are below. Note that these environment variables can be referred to in the task (in the ReleaseDefinition) by replacing "_" with "." e.g. AGENT_NAME environment variable can be referenced using Agent.Name in the ReleaseDefinition:
...
34 2016-06-07T09:26:40.4277002Z [SYSTEM_COLLECTIONID] --> [2043d9ba-7ec9-43f0-8e6c-96a8b28f55d8]
35 2016-06-07T09:26:40.4277002Z [SYSTEM_TEAMPROJECTID] --> [9718773d-2aee-4625-91c6-80de16301479]
36 2016-06-07T09:26:40.4277002Z [SYSTEM_TEAMPROJECT] --> [MyProject]
37 2016-06-07T09:26:40.4277002Z [SYSTEM_CULTURE] --> [en-US]
So this means the variable is there. I tried $(System.TeamProject) as suggested somewhere else, but that fails with The term ... is not recognized-error.
Also, the variables which I have configured myself in the Release Definition, e.g. priority, I am able to access with $env:priority.
As a workaround I can create my own parameters in the script, and pass them in the Arguments field in the task definition, but this kind of defeats the purpose.
Use curly braces because the variable name contains .. Example:
PS C:\> ${Env:System.TeamProject} = "Var contents"
PS C:\> ${Env:System.TeamProject}
Var contents
PS C:\> Write-Host "Prefix - $Env:System.TeamProject"
Prefix - .TeamProject
PS C:\> Write-Host "Prefix - ${Env:System.TeamProject}"
Prefix - Var contents

PowerShell Syntax Error

I am working on a powershell script that will create TFS build definitions. I have used below example as my starting point.
http://geekswithblogs.net/jakob/archive/2010/04/26/creating-a-build-definition-using-the-tfs-2010-api.aspx
I have the script done in powershell and it creates me a build definition file in TFS. One thing I am stuck in is creating Process information such as "Item to build" and "Projects to build". The C# code for this is given below
//Set process parameters
varprocess = WorkflowHelpers.DeserializeProcessParameters(buildDefinition.ProcessParameters);
//Set BuildSettings properties
BuildSettings settings = newBuildSettings();
settings.ProjectsToBuild = newStringList("$/pathToProject/project.sln");
settings.PlatformConfigurations = newPlatformConfigurationList();
settings.PlatformConfigurations.Add(newPlatformConfiguration("Any CPU", "Debug"));
process.Add("BuildSettings", settings);
buildDefinition.ProcessParameters = WorkflowHelpers.SerializeProcessParameters(process);
Below is the powershell code I have written to achive above.
Write-Host"Set process parameters "$now
$process=[Microsoft.TeamFoundation.Build.Workflow.WorkflowHelpers]::DeserializeProcessParameters($def.ProcessParameters)
Write-Host"Set build settings properties "$now
$settings=new-object-`enter code here`TypeNameMicrosoft.TeamFoundation.Build.Workflow.Activities.BuildSettings
$sList=New-Object-TypeNameMicrosoft.TeamFoundation.Build.Workflow.Activities.StringList
$sList="$/pathToProject/project.sln"
$settings.ProjectsToBuild =$sList
$process.Add("BuildSettings", $sList)
But the above segment of code does not create me the Build settings in my build definition file. Myquestion is am I doing this the correct way in powershell? I feel I am not writing the powershell code incorrectly as I am newbie to powershell. Any guidance and
help would be appreciated
Calling a constructor with parameters should be done like this in PowerShell:
$ns = 'Microsoft.TeamFoundation.Build.Workflow.Activities'
$settings.ProjectsToBuild = new-object "$ns.StringList" '$/pathToProject/project.sln'
Also note the use of single quotes around the TF server path. $ is s special character in PowerShell - tells it what follows is either a variable name or sub-expression even in a string. Unless that string is single quoted. In which case, PowerShell doesn't interpret any special characters within the string.

TFSBuild to include an array in parameters to powershell

I have a TFS 2010 build which calls a powershell script for deployment. I've defined several arguments for the build script and these have worked great. They are used by the build and also included in the arguments that are passed into Powershell via the Arguments property of the InvokeProcess control.
I now have a requirement for the powershell script to deploy to a variable number of servers, so I'd like to pass the server ID's in on the argument list from TFS.
In the build definition, I have declared a new argument called TargetServers of type string[]. I have populated this from the Build Process Parameters dialog prior to executing a build.
I have set the FileName property of the InvokeProcess control to "Powershell", and the Arguments property as follows:
String.Format(" ""& '{0}' '{1}' '{2}' '{3}' '{4}' '{5}' '{6}' '{7}' '{8}' '{9}' "" ", DeploymentScriptFileName, IO.Path.GetDirectoryName(DeploymentScriptFileName), "ExecuteBizTalkAppMSI.ps1", MSIFileName, BTDFFilename, TargetServerPath, TargetServers, ServerDeploymentFolder, InstallFolder, HostInstanceFilter, ApplicationName)
My problem is that the TargetServers argument being passed to Powershell is simply System.String[].
From the build log I can see the following output of the Invoke Process control:
Powershell "& 'C:\Builds\3\x.Int.MIS.Deployment\CopyDeployScriptThenExecute.ps1'
'C:\Builds\3\\x.Int.MIS.Deployment' 'ExecuteBizTalkAppMSI.ps1'
'x.Int.MIS-3.0.0.msi' 'x.Int.MIS.Deployment.btdfproj'
'\\d-vasbiz01\BizTalkDeployment' 'System.String[]' 'c:\BizTalkDeployment'
'c:\Program Files (x86)\x.Int.MIS for BizTalk 2010\3.0' 'BTSSvc*MIS*' "
Can anyone please advise how to pass the array?
As strings delimited by commas:
PS> function foo([string[]]$x){$x}
PS> foo a,2,3
a
2
3
If you want, you can put quotes around each individual item but you don't need to unless they contain spaces or other characters reserved for the syntax.