I am running an azure pipeline to deploy applications to the cloud.
Before deploying I want to check if the current version deployed on the cloud is not same as the version the user wants to deploy.
I was looking into getting release name of the build which was deployed before.
I am using Azure devops git as my repository.
Is there any way I can get the desired information using the Azure Devops Rest API?
Thanks in advance.
I was looking into getting release name of the build which was deployed before. I am using Azure devops git as my repository.
We could use the REST API Releases - List with argument $top to get the latest release pipeline:
GET https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/releases?definitionId={definitionId}&`$top={$top}&api-version=6.0
We could get the latest release pipeline Id:
$connectionToken="Your PAT Here"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$ReleasePipelineUrl = "https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/releases?definitionId={definitionId}&`$top={$top}&api-version=6.0"
Write-Host "URL: $ReleasePipelineUrl"
$ReleasePipelineInfo = (Invoke-RestMethod -Uri $ReleasePipelineUrl -Method Get -UseDefaultCredential -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
$LatestReleaseId = $ReleasePipelineInfo.value.id | ConvertTo-Json -Depth 100
Write-Host "LatestReleaseId = $LatestReleaseId"
After getting the LatestReleaseId, we could use the REST API Releases - Get Release:
GET https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/releases/{releaseId}?api-version=6.0
to get the detailed info, like artifact name about the latest pipeline:
$connectionToken="Your PAT Here"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$ReleaseArtifactUrl = "https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/releases/$($LatestReleaseId)?api-version=5.1"
Write-Host "URL: $ReleaseArtifactUrl"
$ReleaseArtifactInfo = (Invoke-RestMethod -Uri $ReleaseArtifactUrl -Method Get -UseDefaultCredential -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
$ReleaseArtifactName = $ReleaseArtifactInfo.artifacts.definitionReference.version.name | ConvertTo-Json -Depth 100
Write-Host "ReleaseArtifactName = $ReleaseArtifactName"
Now, we get the release name of the build which was deployed latest time.
To resolve your question, we could add a powershell task in your build pipeline to invoke above REST API to check the Release name.
And add another task to compare whether the release name is the same as the artifact name generated by this build, we could use REST API to get it Artifacts - Get Artifact. If they are different, call the REST API to trigger the release pipeline. If they are the same, do nothing.
Therefore, we can judge whether there is an update by the name or version of each artifact generated, but it seems difficult to do it if we want to directly compare the version of the app. Unless we throw out this information about the app when building our pipeline, and then use the REST API to get it, for example, store it in a file. In any case, these methods require a bit of familiarity with the REST API and hope to help you.
Related
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 an ADO release pipeline, which has multiple releases.
I want to share information between releases. Basically the new release needs to know the details about the last release. Is there a way to do that?
I was thinking of using artifacts to share this information, but looks like "Publish Pipeline Artifacts" is not supported for the release pipeline : https://github.com/Microsoft/azure-pipelines-tasks/issues/8812
What is a good way to achieve this capability?
To let the new release know the details about the last release. You can add a powershell task in your release pipeline to call azure devops rest api.
You can use below restful api get the the release information.
GET https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/releases/{releaseId}?api-version=5.1
Below is an example in powershell script.
$lastRelease =$(Release.ReleaseId) -1
$url = "https://vsrm.dev.azure.com/{org}/{proj}/_apis/release/releases/$($lastRelease)?api-version=5.1"
$result = Invoke-RestMethod -Uri $url -Headers #{authorization = "Bearer $(System.AccessToken)"} -Method get
echo $result
Note:
To run above script in your release pipeline powershell task, You need to go to Agent Job and make sure allow scripts access to the OAthen token is checked
I am trying to invoke rest api from within Azure DevOps build agent. For that I need bearertoken which I can get in my local machine with:
$accessToken = ((Get-AzContext).TokenCache.ReadItems() | Where { $_.TenantId -eq (Get-AzContext).Tenant } | Sort-Object -Property ExpiresOn -Descending)[0].AccessToken
However, on the build agent this never returns any tokens. Is there some other way I should try to get that token?
Have you enabled the 'Allow scripts to access the OAuth token' setting in the Agents settings?
This would be for builds and releases using the visual designer.
For YAML builds see the predefined variable documentation. There are notes about using the "System.AccessToken" variable in a script. Essentially, you must explicitly map System.AccessToken into the pipeline using a variable. You can do this at the step or task level:
steps:
- bash: echo This is a script that could use $SYSTEM_ACCESSTOKEN
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
- powershell: Write-Host "This is a script that could use $env:SYSTEM_ACCESSTOKEN"
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
Thanks for the suggestions and ideas. Answer was too simple to figure it out. I ripped most of the oneliner and now it works by only using:
$accessToken = ((Get-AzContext).TokenCache.ReadItems()
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.