I have a release pipeline in Azure DevOps with one stage. The stage contains a task "Kubectl" to login to an AKS cluster. It expects a service connection as a parameter. My problem is that I get the service connection from the previous task which reads the value from "App Configuration". The value I get from App Configuration is set as an environment variable that I then pass on this way echo "##vso[task.setvariable variable=SC]$AKS_SERVICECONNECTION". So the variable is SC, and I set the service connection in "Kubectl"-login with $(SC). $AKS_SERVICECONNECTION has the correct value, I printed it out to check.
This doesn't work. The value is not set even though the environment variable SC has now the correct value. So, I tested it with the namespace parameter, and that works, just not with service connection. My question and assumption is that a service connection has to be set at execution-time, and can not be set in a previous task that a following task will use?
It seems that the service connection for Kubectl task is retrieved at compile time before the task being executed.
I created a testing variable on the release pipeline Variables section, and i changed the testing variable value in a script task using echo "##vso[task.setvariable... I saw in the task log that the original value for the testing variable was always picked.
See this similar issue here.
However, you can use the rest api as workaround. See below steps:
1, Add a second stage in your release pipeline. Select the trigger as Manual Only. Move the Kubectl task and related tasks in the second stage(ie. Kubetcl stage in below screenshot)
2, Define a variable ServiceCon in the Variables section. Select the variable Scope to the Second stage(ie.Kubetcl). Check Settable at release time
3, Add a script task to call update release environment rest api in the first stage (ie. SetServiceCon stage). See below inline powershell script: The variable SC is assigned the service connection name in the previous task.
$url = "https://vsrm.dev.azure.com/Org/Project/_apis/Release/releases/$(Release.ReleaseId)/environments/$($(Release.EnvironmentId)+1)?api-version=6.1-preview.7"
#override the variable ServiceCon by referencing to variable $(SC) from your previous task
$body = #{
status= "inProgress";
variables= #{ ServiceCon= #{value= $(SC)}}
}
Invoke-RestMethod -Uri $url -Headers #{Authorization = "Bearer $(System.AccessToken)"} -Method patch -Body (ConvertTo-Json $body) -ContentType "application/json"
Above script will trigger the second stage (ie. kubetcl stage) with the updated service connection name
4, In order the token $(System.AccessToken) can be accessed in above step, you need to go to the edit page of first stage and check the option Allow scripts to access the OAuth token See below screenshot.
5, You also need to allow the Manage deployments and edit release stage permission for the build service account. See below screenshot.
In your release pipeline edit page. Click the 3 dots on the top right corner. And select Security.
Allow the Manage deployments and edit release stage permission for the (ProjectName)build service (OrgName) account.
After complete above steps, and when your release pieline is triggerred, the first stage will be executed first and the script task will call the update release environment rest api. Then the second stage will be triggered with the updated service connection name
Related
I've created a task group which deploys an Azure Function App which normally in a normal release pipeline (not a task group), it gives you the option of naming this variable on the panel which opens on the right hand side:
output variable
But when an azure function app task is contained within a task group, it gives you no option to create an output variable.
I was wondering if theres a way I can capture that output variable so I can later use it as a variable in a later task within the same task group?
You will find your variable but under slightly different name.
Assuming you have one FunctionApp in yout ask group you will get it via this variable
AZUREFUNCTIONAPP_APPSERVICEAPPLICATIONURL
To be sure please display all env variables. For Ubuntu you can add bash script with this command
env | sort
For more information please check this GitHub issue.
In our organization we have each repo set up with a complete pipeline (build in yaml and release using the ui which we have to do to use deployment groups). We have to keep the repos separate via pipelines as we often do a release just for that service, sometimes however we are releasing several services at once (this is known way in advance of the release).
Currently we just have the list of release pipelines to run and we run each one manually.
I was wondering if there was a way to setup something so that multiple release pipelines can be run off one click after the initial setup?
Below are the steps id ideally like to take:
Determine which pipelines need to be released (this usually happens before the sprint in a planning meeting)
Create "something" (another release pipeline that is only used for this release, another azure option I'm unaware of) that basically brings all the release pipelines that need to be included in one place.
Trigger all the release pipelines so they run (as if I ran each one manually)
You may use Trigger Azure DevOps Pipeline and then create another pipeline:
You can create a variable for each release to indicate which version of artifact you want to deploy.
In that way all what you need is to edit variables before running this release once you define it.
As another workaround, you could add a PowerShell task to create multiple releases for different release definition by REST API.
POST https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/releases?api-version=5.0
Sample powershell script to create releases as below:
#Define the variable and enter the release definition id that you want to trigger. For example, I want to manually trigger release pipelines 1 and 2 at once.
$ReleaseDefinitionID = 1,2
ForEach ($ID in $ReleaseDefinitionID)
{
Write-host "ID is" $ID
$token = "pat"
$url = "https://vsrm.dev.azure.com/{organization}/{project}/_apis/Release/releases?api-version=5.0"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$JSON = #"
{
"definitionId": $ID
}
"#
$response = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Post -ContentType application/json -body $JSON
}
I started out with a release pipeline setup in azure DevOps to deploy a windows service to a deployment group which had only a single VM with an agent set up. I have a variable set in the pipeline for the deployment folder.
I'm now trying to expand this to deploy to 2 servers. I've added the second server into the deployment group and the registration has worked. On this server, the deployment needs to go to a different drive.
There doesn't seem to be a way to specify a different value for the variable by an agent.
I've tried googling and trawling around in the ui and so far I've found nothing. I'm wondering if variables are even the right thing?
Im going to answer my own question as the solution is actually a combination of the answers kindly provided by #Martin A #Tomasz Kaniewski and #Vito Liu-MSFT with a fair amount trial and error. I hope this will help others.
Environment Variables are the key to identifying the deployment folder so I set up a system environment variable called AutomationDeploymentRoot on each of my VM's
You must restart the Azure Pipelines Agent windows service on each VM before changes to environment variables are picked up!!
I found that the support for environment variables to be quite inconsistent between the different tasks - they seem to work well in script tasks but not so well in others such as CopyFiles.
The most reliable approach was to copy the environment variable into a pipeline variable (deployment.root) which I set up on the variable tab like so
And then set the variable from script as suggested by Thomasz and Vito
steps:
- script: |
#echo ##vso[task.setvariable variable=deployment.root]%AutomationDeploymentRoot%
displayName: 'Set Deployment Folder'
when this runs the c:\temp\deploy is replaced by the correct folder for the target machine and everything goes green!
You can set a variable from the script: https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=classic%2Cpowershell#set-variables-in-scripts
Write a script that will be able to determine on which machine it is running and assign a proper value to a variable.
Agree with Tomasz.
We can set the variable via the power script Write-Host "##vso[task.setvariable variable={variable name}]{variable value}", then we can call the variable in the another task.
Please refer this answer for more details
In addition, we can update the release pipeline variable via this API Update a release definition.
a. Open the release pipeline and add a new variable test and grant test Build Service (xxx) account the Edit release pipeline permission. (open the release pipeline--> ... --> Security --> Edit release pipeline set to Allow).
b. Open pipeline, enable the feature Allow scripts to access the OAuth token (Click Agent Job Name=>Additional options) add task powershell and enter the script below to update the release variable test value.
$url = "https://vsrm.dev.azure.com/{org name}/{project name}/_apis/release/definitions/{release definition ID}?api-version=6.0-preview.4"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
# Update an existing variable named test to its new value
$pipeline.variables.test.value= {new variable value}
####****************** update the modified object **************************
$json = #($pipeline) | ConvertTo-Json -Depth 99
$updatedef = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
write-host "=========================================================="
Write-host "The value of Varialbe 'test' is updated to" $updatedef.variables.test.value
write-host "=========================================================="
I have multiple artifacts and i would detect if one of these artifacts is triggered after build and deploy it to its respective agent
or(succeeded(), eq(variables['Build.SourceBranch'], '$_Multi-Country/SSIS_FileDrop/Dev/DEV'))
Since you can have multiple artifacts sources tied to one release definition, there's no such pre-defined variable exists could achieve the artifacts name.
Though artifacts source is not unique for release pipeline, but the build id which relevant with the artifacts is unique in release, and it can be got with one pre-defined variable Build.Buildid.
So, here agree with #MarTin's comment, you could use this api to achieve the artifacts name firstly.
Below is the powershell script sample:
$url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/build/builds/$env:BUILD_BUILDID/artifacts?api-version=4.1"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
} -Method Get
Write-Host "artifactName:" ($artifactName = $Pipeline.value.name)
Write-Host "##vso[task.setvariable variable=artifactName]$artifactName"
In this script, use environments SYSTEM_TEAMFOUNDATIONCOLLECTIONURI and SYSTEM_TEAMPROJECTID to get the current org name and project name. Also, the latest version that supports this api is 4.1.
You can add this powershell task in the first step of the agent job. Then, you will be able to use the variable artifactName in the condition expression to validate whether the trigger artifact name is the specific one.
I am trying to automate resource group creation with team services release.
I added azure resource group project to the solution and defined administratorLoginPassword variable as a secure string in json definition:
Also I defined administratorLoginPassword variable at the environment level in release definition as the following:
But when I run release it fails with the following reason:
Cannot process command because of one or more missing mandatory
parameters: administratorLoginPassword.
You need to pass that variable explicitly to the template script specifying its value in the Override Template Parameters text box, as follow:
-administratorLoginPassword (ConvertTo-SecureString -String '$(administratorLoginPassword)' -AsPlainText -Force)
Anyway I would suggest to create a proper azuredeploy.parameters.json file where you store all the actual values for all the required template parameters, and pass this file to Template Parameters input of the Azure Resource Group Deployment task. This file could be manipulated during build/release by replacing the content with the values you need, avoiding entirely to play with special parameters of the build task.
The variables created in the Build/Release Definition are disregarded by the Azure Res. Group Deployment task unless you pass it over explicitly as shown above.