I'm using the "Post to Slack" task as one of my build steps in TFS 2018 and I'm wondering how to access variables relating to that commit. I would like to include them as part of the Message field (something like "Commit: $(CommitMessage) link to changeset $(ChangesetLink)" but those variables don't exist). Here is where I need to reference the variables in TFS:
This document: link describes how to access build variables but it doesn't mention anything relating to the commit. I would like to access the commit message, associated commit changesets and the link to the changeset(s) associated with the commit. Does anyone know how to do this or know where I can find documentation for it? Thank you
Cruiser is right, no such Predefined variables in TFS, you can retrieve the needed information by REST API, then set corresponding variables using the Logging Commands.
Create a PowerShell script to set the avariables (Reference below
sample, you can also Use the OAuth token to access the REST API), then commit and push the script into TFS.
Add a PowerShell task before the "Post to Slack" task in your
definition to run the PS script
Use the variables $(commitID), $(CommitMessage) and
$(commitUrl) in "Post to Slack" task
Note: For Git it's commit, For TFVC it's changeset
You can use below script to set the variables:
Param(
[string]$collectionurl = "http://server:8080/tfs/DefaultCollection",
[string]$repoid = "389e8215-1fb2-4fdc-bd04-ebc8a8a4410e",
[string]$user = "username",
[string]$token = "password"
)
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$searchCriteria = "$" + "top=1"
$baseUrl = "$collectionurl/_apis/git/repositories/$repoid/commits?$searchCriteria"
$response = (Invoke-RestMethod -Uri $baseUrl -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
#Retrieve values
$commitID = $response.value.commitID
$CommitMessage = $response.value.comment
$commitUrl = $response.value.remoteUrl
#Set variables
Write-Host "##vso[task.setvariable variable=commitID]$commitID"
Write-Host "##vso[task.setvariable variable=CommitMessage]$CommitMessage"
Write-Host "##vso[task.setvariable variable=commitUrl]$commitUrl"
UPDATE:
You can use this REST API to get the repository ID:
GET http://server:8080/tfs/DefaultCollection/{ProjectName}/_apis/git/repositories
Related
I'm trying to use TFS Release management on TFS 2017/2018 on prem.
I have releases created every time artifact is created. I also have several environments to deploy releases to. QA-1 environment is updated every time we have new artifact (can be several times a day). QA-2 environment should be updated once a day.
How can I get list of releases available for deployment to QA-2 environment?
If I had Release-20 already deployed overnight. During the day we created Release-21, 22, 23 (all deployed to QA-1). Is there a way to tell that 21, 22, 23 are available for QA-2 environment using API?
I tried this but it shows what was already deployed:
https://<server>/<project>/_apis/release/deployments?definitionId=12&definitionEnvironmentId=28
It does not show those that are not deployed yet (those that I'm looking for).
Thanks.
Unless there is better way that I can't see at the moment, this may work.
Get latest deployed release to the environment.
https://<server>/<collection>/<project>/_apis/release/deployments?definitionId=<def_ID>&definitionEnvironmentId=<env_ID>&$top=1&api-version=4.1-preview.2
Get when this release was created from JSON. Add one second to the to be used in next command:
https://<server>/<collection>/<project>/_apis/release/releases?definitionId=<def_ID>&minCreatedTime=<datetime>&api-version=4.1-preview.2
Now we can iterate through releases in this JSON result.
Here is the powershell script to get the concept:
param(
[String]$TFSurl = "", # URL to access TFS server
[String]$TFScollection = "", # Collection name in TFS
[String]$TFSproject = "", # Name of the project in TFS
[String]$APIversion = "4.1-preview.2", # Version of API to be used
[String]$definitionId = "", # Release definition ID
[String]$definitionEnvironmentId = "", # Environment ID inside the release definition
$debugTrace = "SilentlyContinue" # SilentlyContinue, Continue
)
$dtformat = 'yyyy-MM-ddTHH:mm:ss.FFFFFK' # DateTime format used by TFS API and returned in Json.
# Get last release that was deployed to the environment to get date and time when it was created
$uri = "$TFSurl/$TFScollection/$TFSproject/_apis/release/deployments?definitionId=$definitionId&definitionEnvironmentId=$definitionEnvironmentId&`$top=1&api-version=$APIversion"
Write-Host "Calling REST: $uri"
$result = Invoke-RestMethod -Method 'Get' -ContentType 'application/json' -uri $uri -UseDefaultCredentials
Write-Host "Release Definition: " $result.value.releaseDefinition.name
Write-Host "Environment name: " $result.value.releaseEnvironment.name
Write-Host "Last release deployed: " $result.value.release.name
Write-Host "Release create date: " $result.value.completedOn
# add 1 second to create date to make sure we don't get the same realease again
$dateTimeNew=[datetime]::ParseExact($result.value.completedOn,$dtformat,$Null).AddSeconds(1).ToString($dtformat)
Write-Host "Release time +1 second:" $dateTimeNew
# Get list of releases avaialble since specified date and time
$uri = "$TFSurl/$TFScollection/$TFSproject/_apis/release/releases?definitionId=$definitionId&minCreatedTime=$dateTimeNew&queryOrder=ascending&api-version=$APIversion"
Write-Host "Calling REST: $uri"
$result = Invoke-RestMethod -Method 'Get' -ContentType 'application/json' -uri $uri -UseDefaultCredentials
foreach ($V in $result.value) {
Write-Host "Release: $($V.releaseDefinition.name) (id=$($V.releaseDefinition.id)) $($V.name) (id=$($V.id))"
}
I've defined a variable in my TFS/AzureDevops Build definition (say it's time)
and assign the value using PowerShell task within my build definition.
Like,
Type: Inline Script.
Inline script:
$date=$(Get-Date -Format g);
Write-Host "##vso[task.setvariable variable=time]$date"
You can refer to this similar example
Now I want to get this value in my release definition pipeline. I configured this build definition as continuous deployment to my release definition.
My Question is
How can I get the value of time in my release definition using some other variable? Is this possible?
The is no official way to pass variables from Build to Release. The only way to accomplish this is to store the values in a file (json, xml, yaml, what have you) and attach that as a Build Artifact. That way you can read the file in the release and set the variable again.
Martin Hinshelwood seems to have gotten frustrated enough by this problem and turned that functionality into an extension for Azure DevOps Pipelines.
Tasks included
Variable Save Task - During your build you can save the variables to a json file stored with your other build assets
Variable Load Task - During your Release you can load the saved variables and gain access to them.
What about using a variable within a variable group?
I managed to set the value of a variable in a variable group to a variable coming from a build pipeline, and then to read that variable in a release pipeline.
For that, it is necessary:
To have previously created the variable group, and the variable (its name identified by $(variableName). Let's assume its value would be stored in $(variableValue)).
To find the variable group ID (stored in $(variableGroupId)), which can be done by navigating on Azure DevOps to that variable group. The group ID will then be in the URL.
A Personal Access Token (PAT) with Read & Write access to group variables (called $(personalAccessToken) )
CI pipeline
- powershell: |
az pipelines variable-group variable update --group-id $(variableGroupId) --name $(variableName) --value $(variableValue)
displayName: 'Store the variable in a group variable'
env:
AZURE_DEVOPS_EXT_PAT: $(personalAccessToken)
Then all that's necessary, is to link the variable group to the release pipeline, and the variable will be seeded to that pipeline.
I found another solution that works even without text files just by using the Azure REST API to get the build parameters.
In my release pipeline I execute this Powershell tasks first to extract any build pipeline parameters:
function Get-ObjectMember {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True, ValueFromPipeline=$True)]
[PSCustomObject]$obj
)
$obj | Get-Member -MemberType NoteProperty | ForEach-Object {
$key = $_.Name
[PSCustomObject]#{Key = $key; Value = $obj."$key"}
}
}
$url = "https://dev.azure.com/$(account)/$(project)/_apis/build/builds/$(Build.BuildId)?api-version=6.0"
$build = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
$params = $build.templateParameters
if ($params) {
$params | Get-ObjectMember | foreach {
Write-Host $_.Key : $_.Value
echo "##vso[task.setvariable variable=$($_.Key);]$($_.Value)"
}
}
My build pipeline contained the parameter: RELEASE_VERSION and after I executed the above code, I can use $(RELEASE_VERSION) in my other release tasks.
There are 100s of builds left in our build definition indefinitely, regardless of the retention settings: i want to delete builds with scripts, i am trying run from remote PC. our tfs server is 2015.2.
tfsbuild destroy /collection:http://tfsserver:8080/tfs/ProjectCollection /dateRange:01/01/2017~31/12/2017 /buildDefinition:teamProject\Builddefintion
output shows: No builds found for build specification. even though there are many builds meets the criteria. any help is appreciated. Thanks!
Tfsbuild delete/destroy only availabe for Xaml builds. And need to delete first then destroy.
For vNext builds, you can try to delete them with the REST API (Delete a build):
DELETE http://server:8080/tfs/DefaultCollection/ProjectName/_apis/build/builds/{build Id}?api-version=2.0
You can use below PowerShell script to delete all the builds which compeleted in the year 2017 for the specific build definiiton:
Param(
[string]$collectionurl = "http://server:8080/tfs/Collection",
[string]$projectName = "ProjectName",
[string]$builddefinitionID = "56",
[string]$keepForever = "true",
[string]$user = "username",
[string]$token = "password"
)
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
#Get builds list which completed in the year 2017
$buildsUrl = "$($collectionurl)/$projectName/_apis/build/builds?definitions=$builddefinitionID&statusFilter=completed&api-version=2.0"
$builds = (Invoke-RestMethod -Uri $buildsUrl -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}).value | where({$_.finishTime -like '*2017*'})
#Delete the builds
foreach ($build in $builds.id)
{
$deleteurl = "$($collectionurl)/$projectName/_apis/build/builds/$build"+"?api-version=2.0"
$result = (Invoke-RestMethod -Uri $deleteurl -Method Delete -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)})
Write-Host "Builds deleted with the ID" : $build
}
Given a Jenkins build job with different promotion jobs (i.e., that promote builds to different environments), how can one trigger a specific promotion job for a specific build using the Jenkins API?
Combined answers from different sources to come up with this:
$Username = "Username"
$APItoken = '12345'
$Credential = "$($Username):$($APItoken)"
$EncodedCredential = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($Credential))
$BasicAuthValue = "Basic $EncodedCredential"
$Headers = #{
Authorization = $BasicAuthValue
}
Write-Output "Promoting build $LatestBuildNumber to Environment..."
Invoke-WebRequest -URI "http://jenkins.prd.company.com/job/jobname/buildnumber/promotion/forcePromotion?name=PromoteToEnvironment" -Headers $Headers
I know this is an old thread, but just to help the community.
Shell Solution using CURL:
user_name="jenkins_user"
user_token="token"
promotion_name="Test_Promote"
jenkins_url="http://build-server.com"
JOB_NAME="job_name"
JOB_NO="job-no"
url="--silent -u $user_name:$user_token $jenkins_url/job/$JOB_NAME/$JOB_NO/promotion/forcePromotion?name=$promotion_name"
curl $url
How to generate jenkins user token: https://jenkins.io/blog/2018/07/02/new-api-token-system/
I'm looking for a way to set the retain indefinitely field of a build when it completes.
Maybe using a PowerShell script as a build step?
For the benefit of searchers using vNext builds, you can use a Powershell script to do this.
You will need to 'Allow scripts to access OAuth token' in the buid options.
$buildId = $env:BUILD_BUILDID # the currently running build
"Build ID: $buildId"
$keepforever = #{
keepforever='true'
}
$jsonKeepForever = $keepforever | ConvertTo-Json -Depth 100
$uriForBuildUpdate = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$($env:SYSTEM_TEAMPROJECTID)/_apis/build/builds/" + $buildID + "?api-version=2.0"
$result = Invoke-RestMethod -Uri $uriForBuildUpdate -Method Patch -Body $jsonKeepForever -ContentType "application/json" -Headers #{ Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN" }
Write-Verbose "Result: $result" -Verbose
"********************************"
"Build set to retain indefinitely"
"********************************"
Check out the "Build Updating Tasks" extension. It contains a Build Retention task. It does exactly what you need. You do need to be on Update 3 of TFS if I'm not mistaking.