Is it possible to get a release pipeline creation date on Azure Devops/TFS? - azure-devops

I was wondering if it is possible to find the exact creation date as a predefined variable for a Release in Azure Devops. In release pipelines it can be seen as an actual column labeled "Created" (along with "Releases" and "Stages" to the left and right of "Created" respectively) - so I know that the data is stored somewhere.
The only variable I have been able to find is Release.Deployment.StartTime - which is the time the release deployment begins, which can be hours or even days after Release Creation, so not quite what I want.
Is there a way to do this? I attached a screenshot to show what I am trying to get.

What about $(SYSTEM_PIPELINESTARTTIME) ?
I like this task which dumps all the variables for you. I have it at the start of all my dev pipelines: https://marketplace.visualstudio.com/items?itemName=dutchworkz.DisplayAllVariables
You can also do it with powershell if you don't have access to install extensions:
Get-ChildItem Env: | Format-Table -Wrap -AutoSize
If none of the variable work you can also publish your own variable with a Powershell task. It will be about 5-10 seconds later than the real stage execution time:
$DateTime = (Get-Date).ToString("yyyyMMdd_HHmm")
Write-Host "##vso[task.setvariable variable=DateTime;]$DateTime"

You always can run a rest api call to see release details. Here is the example of a stage step with powershell:
$user = ""
$token = "$(System.AccessToken)"
$teamProject = "$(System.TeamProject)"
$releaseId = "$(Release.ReleaseId)"
$orgUrl = "$(System.CollectionUri)"
$orgUrlrel = $orgUrl -replace "dev", "vsrm.dev"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$uriGetRelease = "$orgUrlrel/$teamProject/_apis/release/releases/$releaseId"+"?api-version=5.1"
$resultStatus = Invoke-RestMethod -Uri $uriGetRelease -Method Get -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
Write-Host "Created date:" $resultStatus.createdOn
Additionally, you have to enable access to the token:

Related

Setting Git Tag from Azure Devops Build Pipeline on Complete

I'm trying to set a tag with the current version number determined by GitVersion on the GIT commit at the end of a successful build. Feels like I can't be the first one to be doing this, but I'm struggling to find something that works.
Azure Devops Pipeline has a feature in Get Sources to "Tag sources" On Success. I've set this and set to a variable that is set by one of the Agent Tasks I have (GitVersion)
I can see in the debug logs that this variable is getting set by the GitVersion component that I've added to the pipeline.
2019-12-06T20:54:20.2390794Z ##[debug]Processed: ##vso[task.setvariable variable=GitVersion.MajorMinorPatch;]2.98.0
However if I leave it just as this, I get a tag created as "v$(GitVersion.MajorMinorPatch)" which means that at the time that the tag is being created that that variable no longer exists.
The Tag Format help tooltip says
"Tag format could be a combination of user-defined or pre-defined variables that have a scope of "All". For example: '$(Build.DefinitionName)$(Build.DefinitionVersion)$(Build.BuildId)$(Build.BuildNumber)$(My.Variable)'"
So I guess the problem is that this variable created during the pipeline does not have a scope of All.
I then tried adding a pipeline variable to the pipeline of "GitVersion.MajorMinorPatch" with the hope that this was at the right scope and hoping that when the "task.setvariable" command is run, that this will set the variable value of this higher scoped variable.
However in this case I just got a tag "v" created.
So I am a bit stuck. Somehow I need to be able to dynamically create or set a variable at scope ALL with the value I want to tag here.
I'd be really grateful for any ideas on this.
If you are doing a yaml pipeline, you can add the following steps
- checkout: self
persistCredentials: true
## Rest of pipeline ##
- script: |
git tag $(GitVersion.NugetVersionV2)
git push origin $(GitVersion.NugetVersionV2)
workingDirectory: $(Build.SourcesDirectory)
The persistCredentials allows the token to be automatically passed to other git commands. Note the assignment of workingDirectory, otherwise I had an error that the location was not a git repository.
For an annotated tag rather than lightweight tag, the syntax would look like this...
- script: |
git tag -a <tagname> -m <message>
git push origin <tagname>
To get a user/date against it you need to set the user name/email as well e.g.
- script: |
git config --global user.name "BuildService"
git config --global user.email "autobuild#fabrikam.com"
git tag -a <tagname> -m <message>
git push origin <tagname>
For this to work, the Project Collection Build Server account (not the Project Build Service Accounts group) needs to be allocated the Contribute permission for the Repositories
Expanding on the excellent answer from Paul Hatcher, I'd like to add that for me the account was called Project Collection Build Service in Azure DevOps Server 2019. This also seems to be in line with the current Microsoft documentation.
Sorry for the answer, my reputation does not yet suffice to comment.
I can see in the debug logs that this variable is getting set by the
GitVersion component that I've added to the pipeline.
The variable GitVersion.MajorMinorPatch you saw from the log is a step-level variable, which means its life cycle is only start from the current GitVersion task.
As the definition you are referring, it scope must to all. This means is must be a global variable. For example, the predefined variables that the system default have, and the customized variables which specified in the Variables tab.
Based on the GitVersion task compile and work logic, in fact, the GitVersion.MajorMinorPatch value is generated and stored as current build's build number:
So, the most convenient method for you to tag the GitVersion.MajorMinorPatch value to repos is using $(Build.BuildNumber):
v$(Build.BuildNumber)
And this is my result:
Update:
To add the GitVersion.MajorMinorPatch which generated by the GitVersion task into Variables, please apply below scripts into PowerShell task:
$connectionToken="{PAT Token}"
$urlget = "https://dev.azure.com/{org}/{project}/_apis/build/definitions/$(System.DefinitionId)?api-version=5.1"
$base64AuthInfo = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$getdef = Invoke-RestMethod -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method GET -ContentType application/json -Uri $urlget
Write-Host Pipeline = $($getdef | ConvertTo-Json -Depth 100)
$bvalue=#"
{
"value": "$(GitVersion.MajorMinorPatch)"
}
"#
$getdef.variables | add-member -Name "GitVersion.MajorMinorPatch" -value (Convertfrom-Json $bvalue) -MemberType NoteProperty -Force -PassThru
$getdef = $getdef | ConvertTo-Json -Depth 100
$getdef | clip
$urlput = "https://dev.azure.com/{org}/{project}/_apis/build/definitions/$(System.DefinitionId)?api-version=5.1"
$putdef = Invoke-RestMethod -Uri $urlput -Method PUT -Body $getdef -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
As I mentioned previously, I still don't think it is available to specify $(GitVersion.MajorMinorPatch) in Tag format.
Still strongly suggest you by calling $(Build.BuildNumber) to tag the $(GitVersion.MajorMinorPatch) value
- pwsh: |
# Construct PAT authentication header
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "user",$env:SYSTEM_ACCESSTOKEN)))
$headers = #{Authorization=("Basic {0}" -f $base64AuthInfo)}
$url="$(System.CollectionUri)/$(System.TeamProject)/_apis/git/repositories/$(Build.Repository.ID)/annotatedtags?api-version=5.0-preview.1"
$body = #{name = "$(GitVersion.MajorMinorPatch)"
message = "automatically added"
taggedObject = #{
objectId = "$(Build.SourceVersion)"
}
} | ConvertTo-Json
Invoke-RestMethod -Uri $url -Headers $headers -Method Post -ContentType "application/json" -Body ($body)
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: 'Add tag'

Store result of Azure CLI task into release variable

I have a release pipeline with multiple jobs.
On the first agent job there is an Azure CLI task that retrieves the keys of a storage account on azure.
The command it executes is :
az storage account keys list --account-name "$(diagnosticsStorageAccountName)" --resource-group "$(resourceGroup)"
What I want to do is store the result of this command and utilize it in a task that is running under a deployment group job.
I've already looked into these resource :
Set Output Variable in Azure CLI task on VSTS
How to modify Azure DevOps release definition variable from a release task?
I've tried the first one but I didn't get it working.
I didn't bothered with the second because it seems way to hacky.
Is there any way do achieve this that isn't hacky ?
The output values didn't get stored properly.
The output of az storage account keys list --account-name "$(diagnosticsStorageAccountName)" --resource-group "$(resourceGroup)"is spread over multiple lines when you use the following syntax:
echo "##vso[task.setvariable variable=testvar;]%myvar%"
So one of the problems was that only the first line of the JSON array was being stored into the variable.
I solved this problem in the following way:
keys=`az storage account keys list --account-name "$(diagnosticsStorageAccountName)" --resource-group "$(resourceGroup)"`
taskvariable="##vso[task.setvariable variable=_[tempVariable];]"
echo $taskvariable$keys
According to documentation echo "##vso[task.setvariable variable=testvar output=true;]%myvar% should make the variable available for the whole release. Unfortunately I had no luck with this.
I overcame this using a Powershell task under the same Agent Job (Ubuntu 16.0) :
$url = "$($env:SYSTEM_TEAMFOUNDATIONSERVERURI)$env:SYSTEM_TEAMPROJECTID/_apis/Release/definitions/$($env:RELEASE_DEFINITIONID)?api-version=5.1"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $(System.AccessToken)"
}
#Parsing JSON string from previous task
$keys = $(#"
$(_tempVariable)
"# | ConvertFrom-Json)
# Assignment of variable value
$pipeline.variables.[variableName].value = $keys[0].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 $(System.AccessToken)"}
write-host "=========================================================="
Write-host "The value of Variable '[variableName]' is updated to" $updatedef.variables.[variableName].value
write-host "=========================================================="
Please note that in order to get this working there are a couple of things you need to do.
First you need to allow access to the OAuth token on the Agent Job.
On top of that you need to give the "Project Collection Build Service".
Click on security on the release and click on the "Project Collection Build Service" user.
Change the values for the "Edit release" and "Manage release" to allow and save the changes.

AzureDevOps Build/Release Pipeline - get git commit message (Build title)?

I have a webhook task that runs after a deploy on my release pipeline, currently it just pushes a message to say a new version has been deployed, but I'd like to include the git commit message in this as well to show exactly what has been deployed. I'm not quite sure how to retrieve this, but I'm hoping it's possible as the build is initially triggered from a git push and moreover the Build title is named with this message as per this screenshot:
This is somewhat tricky since the Release Pipeline typically does not
have Git access like the Build Pipeline does. To add to this, it is not
possible to share variables across pipelines, which would have been an
easy solution.
This is how I've done it:
First, Add a Bash script task to your Build Pipeline that exports your
last commit message to a file:
CHANGES=`git log -1 --pretty=%B`
mkdir -p $(Build.artifactStagingDirectory)/exported
echo "$CHANGES" > $(Build.artifactStagingDirectory)/exported/CHANGES
Make sure this folder is published as an artifact in your build using
the Publish build artifacts task:
Path to publish: $(Build.ArtifactStagingDirectory)/exported
Artifact name: exported
Second, add a Bash script task to your Release Pipeline that picks up
these changes from the file and stores them in a variable:
CHANGES=$(cat $(System.DefaultWorkingDirectory)/Development/exported/CHANGES)
echo "##vso[task.setvariable variable=commitComment]$CHANGES"
The last Git change is now available for use in your Build Pipeline as the variable $commitComment.
Note: your exact paths above may vary.
Ok, I've worked out a way, not sure if it's the best way so let me know if it can be done differently...
I've used a Powershell Task in the Release pipeline which queries the Azure REST API and calls into Git, as follows:
$webClient = New-Object Net.WebClient
$token = "Bearer $env:SYSTEM_ACCESSTOKEN"
$headers = #{ Authorization = $token }
$baseUrl = "https://dev.azure.com/<your company>/<your project>/_apis/git/repositories/<your repo Id>/commits"
$request = "$baseUrl/$env:RELEASE_ARTIFACTS_<your repo name>_SOURCEVERSION"
Write-Host "Request: $request"
$response = Invoke-WebRequest -Uri $request -Headers $headers
$json = ($response | ConvertFrom-Json)
$comment = $json.comment
Write-Host "Response: $comment"
Write-Host "##vso[task.setvariable variable=commitComment;]$comment"
To find out the values for the parameters I've tokenised above, follow this guide:
https://learn.microsoft.com/en-us/azure/devops/pipelines/release/variables?view=azure-devops&tabs=powershell#view-the-current-values-of-all-variables
This writes to a custom pipeline variable I've created called "commitComment", which I then use in a marketplace task I found to generate a discord webhook request.
Alternatively, you could just call that directly from Powershell.
Hope this helps anyone wanting to do the same..
Updated version: The json response contains not only the last commit, but a collection of the last 100 commits. You would need to access the first commit in the collection (ordered by date DESC). Also, all <your_custom_values> can be retrieved dynamically, to improve reusability:
$webClient = New-Object Net.WebClient
$token = "Bearer $env:SYSTEM_ACCESSTOKEN"
$headers = #{ Authorization = $token }
$devOpsUrl = "$(System.TeamFoundationCollectionUri)"
$projectName = "$(System.TeamProject)"
$repoId = "$(Build.Repository.Id)"
$repoName = "$(Build.Repository.Name)"
$baseUrl = "$devOpsUrl$projectName/_apis/git/repositories/$repoId/commits"
$request = "$baseUrl/$env:RELEASE_ARTIFACTS_$repoName_SOURCEVERSION"
Write-Host "Request: $request"
$response = Invoke-WebRequest -Uri $request -Headers $headers
$json = ($response | ConvertFrom-Json)
$lastCommit = $json.value[0]
Write-Host "Last Commit: $lastCommit"
$comment = $lastCommit.comment
Write-Host "Comment: $comment"
Write-Host "##vso[task.setvariable variable=CommitMessage;]$comment"

Equivalent for TeamCity's system.build.start.date in Azure Pipelines

Is there an equivalent for the TeamCity variable system.build.start.date in Azure Pipelines? I couldn't find it in the predefined variables (https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=vsts)
It doesn't appear like there is. It is available on the Get Builds API though. You could add a custom PowerShell task as the first step and use it to set a variable for future tasks to reference within the same Agent phase.
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes((":{0}" -f $env:SYSTEM_ACCESSTOKEN)))
$uri = "https://dev.azure.com/{oraganization}/{project}/_apis/build/builds/$($env:BUILD_BUILDID)?api-version=5.0"
$buildStartTime = Invoke-RestMethod -Uri $uri -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} |
Select-Object -ExpandProperty startTime
Write-Host "##vso[task.setvariable variable=BuildStartTime;]$buildStartTime"

How to modify Azure DevOps release definition variable from a release task?

What is the easiest way to get key rotation to work for azure storage accounts from a AzureDevOps relase task? The current plan is to re-generate the old key after release to invalidate it, and have a fresh key that can be used on next deployment. But to get that to work it seems like I at least need to store the name of the key to use in a release variable.
I had a look at he logging tasks (https://github.com/Microsoft/azure-pipelines-tasks/blob/master/docs/authoring/commands.md), but that only changes the value in the current release and does not modify the release definition.
You can use the REST API (Definitions - Update) to update the value of the release definition variable from a release task.
Go to the Agent Phase and select Allow Scripts to Access OAuth Token. See Use the OAuth token to access the REST API
Grant Project Collection Build Service (xxx) account the edit
release pipeline permission. (Select the release pipeline --> ... --> Security --> Edit release definition set to Allow)
Add a PowerShell task in your release pipeline
Run inline script: (Update the value of variable v1030 in below sample)
$url = "$($env:SYSTEM_TEAMFOUNDATIONSERVERURI)$env:SYSTEM_TEAMPROJECTID/_apis/Release/definitions/$($env:RELEASE_DEFINITIONID)?api-version=5.0-preview.3"
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 v1030 to its new value 1035
$pipeline.variables.v1030.value = "1035"
####****************** 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 'v1030' is updated to" $updatedef.variables.v1030.value
write-host "=========================================================="
Here is a much cleaner and better solution that also allows for multiple builds being triggered simultaneously.
https://tsuyoshiushio.medium.com/how-to-pass-variables-with-pipeline-trigger-in-azure-pipeline-5771c5f18f91
Essentially your triggering build produces artifacts that your triggered build reads and turns into variables.
Still not at all great, but better than nothing and better than REST calls setting static global variable groups.
The other answer above talks about how to update Release pipelines.
If you would like to update a Build Pipeline's variables, here is how you do that:
Edit build pipeline
Go to the Agent Phase and select Allow Scripts to Access OAuth Token. See Use the OAuth token to access the REST API
Go to Manage Security -> Users -> Select Project Collection Build Service (YOUR TEAM NAME HERE)
Change "Edit Build Definitions" to Allow
Now add a powershell stage - 2.x - inline script called Update variables.
Script inline contents:
$api_version='5.0-preview.6'
$url = "$($env:SYSTEM_TEAMFOUNDATIONSERVERURI)$env:SYSTEM_TEAMPROJECTID/_apis/build/definitions/$(System.DefinitionId)?api-version=${api_version}"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
# Update variables as desired here:
$pipeline.variables.mavenBuildVersionPatch.value = "2401"
####****************** 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 Variable mavenBuildVersionPatch is updated to" $updatedef.variables.mavenBuildVersionPatch.value
write-host "=========================================================="
Take note of the API version in this script is 5.0-preview.6.
If your version of Azure Devops is newer, you may need to update this in the future.
Save build pipeline.
Now when you run job, after the job completes this powershell stage, this variable will be set.
Important: If you want to update a variable then make the updated variable for other pipeline stages, then you do it with a powershell stage with the following inline script:
$mavenBuildVersionPatch = [int]"$(mavenBuildVersionPatch)"
$mavenBuildVersionPatch = $mavenBuildVersionPatch + 1
Write-Host "##vso[task.setvariable variable=mavenBuildVersionPatch;]$mavenBuildVersionPatch"
This example would take our existing patch number and increment it by 1.
This does not save the variable at the end of the job, you still need to do that with another powershell script if desired.