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()
Related
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.
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 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 have a simple Build setup in Team Services. The build simply downloads source code from a Team Services hosted Git repo and then executes a Powershell script.
The Powershell Script receives 4 parameters;
-SiteName "$(AppServiceName)" -AzureRMTenantID "$(AzureRMTenantID)" -AzureRMUN "$(AzureRMUN)" -AzureRMPW "$(AzureRMPW)"
AppServiceName is entered manually when the build is queued.
The 3 AzureRM* parameters should be coming from a Variable Group which I have linked to the Build Definition;
The Variable Group AzureDevOps is configured to Link the Secrets from Azure Key Vault as variables;
Based on everything I have been able to find regarding this pattern, it seems like it should just work.
As an interim sanity check, I am printing the variables out in my powershell script just so I can confirm they are being passed correctly.
Thus far, I have not been able to get the values of any of the AzureRM* variables to print correctly which leads me to believe they are NOT being passed as expected.
Generating script.
Formatted command: . 'd:\a\1\s\AppServices\Create Canned App Service Application.ps1' -SiteName "Testers" -AzureRMTenantID "" -AzureRMUN "" -AzureRMPW ""
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -File "d:\a\_temp\23b9a27a-4b6d-4232-8e24-150173e08915.ps1"
Working Set of Variables:
SiteName: Testers
ResourceGroup: Applications
ASE Name: appservices-ase
Location: East US
Additional Variables:
AzureRMTenantID:
I am not expecting the variables to be printed in the log command here;
Formatted command: . 'd:\a\1\s\AppServices\Create Canned App Service Application.ps1' -SiteName "Testers" -AzureRMTenantID "" -AzureRMUN "" -AzureRMPW ""
but I would expect them to be printed within my script where I am explicitly writing them out;
Write-Host "Working Set of Variables:`nSiteName: "$SiteName"`r`nResourceGroup: "$RG"`r`nASE Name: "$ASEName"`r`nLocation: "$Location
Write-Host "Additional Variables:`nAzureRMTenantID: "$AzureRMTenantID"`r`n"$AzureRMUN"`r`n"$AzureRMPW
If I run the PS script locally, the values do print as expected;
PS C:\ashley\scm\AzureAutomation\AppServices> & '.\Create Canned App Service Application.ps1' -SiteName "tester" -AzureRMTenantID 12345 -AzureRMUN user -AzureRMPW 1234
Working Set of Variables:
SiteName: tester
ResourceGroup: Applications
ASE Name: appservices-ase
Location: East US
Additional Variables:
AzureRMTenantID: 12345
user
1234
Does anyone know how to make this work? I am wondering if the problem has to do with the KeyVault permissions since the request is coming from the "Hosted 2017" Agent Queue built into Team Services.
First, you can’t print out the secret variables’ value, you can send the data to a service (e.g. Web API) to get the actual data during the build/release.
Secondly, the Key Vault secrets variables are used for release, it will add Azure Key Vault task during the release. Link secrets from an Azure Key vault as variables
You will get the empty value if you are using in build. You can add Key Vault Task to the build definition, then you can use the related variables in the following tasks. (Do not need to link to that variable group in build definition)
The Key Vault support currently works only with Release Definitions. You can create a Release Definition and link your Git Repo as an artifact and can achieve the same.
I receive this error while linking Azure Keyvault VG to BD.