Trigger Release Pipeline only for Scheduled builds

Currently I am working on some build and release pipelines to deploy some websites automatically. I have some CI builds running, and some scheduled buils that are deployed automatically. This works fine, but there is some waste in the process.

My CI build is the same as my scheduled build, with 1 major difference. I do not want to start a deployment pipeline for my CI builds, but I do want that for manual and scheduled builds. But how can I distinguish between the 2 builds triggers? I can only configure Continuous Deployment on a Build Definition and not on a trigger.

pic1

But there is a solution! Use the tags on a build definition to steer the Continuous Deployment.

Modifying the Build

The build definition can be configured to be a scheduled build, or a CI build, or, of course, a manual build. On the MSDN (docs) page of predefined build variables, the variable $(Build.Reason) is mentioned. But unfortunately, this does not work :-(. Luckily for us, we have the REST API that we can use to reach our goal.

First, I use the REST API, to get the build details, the response JSON contains a field “reason”. The reason is “manual”, “scheduled” or some other value.

Then, I set the Build Tag to this specific value. You can write an output variable and use this in a subsequent task (for example the Add Build Tag Task, found here) or just write the Tag directly in the powershell script using the REST API to write a Tag.

pic2

I described both options in earlier posts.

Modify the Release

When you updated the build to set the Tag, you can then create or update the Release trigger, to only listen to builds with a certain tag

pic_tag

The Script

For people who are interested, I created a Powershell script that you can use within your build pipeline and that sets that Tag of the build to the trigger.

param
(
[string] $BuildID=""
)
#global variables
$baseurl = $env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI
$baseurl += $env:SYSTEM_TEAMPROJECT + "/_apis"
Write-Debug "baseurl=$baseurl"
Write-Debug "basermurl=$basermurl"
<#
.Synopsis
Creates either a Basic Authentication token or a Bearer token depending on where the method is called from VSTS.
When you send a Personal Access Token that you generate in VSTS it uses this one. Within the VSTS pipeline it uses env:System_AccessToken
#>
function New-VSTSAuthenticationToken
{
[CmdletBinding()]
[OutputType([object])]
$accesstoken = "";
if([string]::IsNullOrEmpty($env:System_AccessToken))
{
if([string]::IsNullOrEmpty($env:PersonalAccessToken))
{
throw "No token provided. Use either env:PersonalAccessToken for Localruns or use in VSTS Build/Release (System_AccessToken)"
}
Write-Debug $($env:PersonalAccessToken)
$userpass = ":$($env:PersonalAccessToken)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($userpass))
$accesstoken = "Basic $encodedCreds"
}
else
{
$accesstoken = "Bearer $env:System_AccessToken"
}
return $accesstoken;
}
<#
.Synopsis
Sets a Build Tag on a specific BuildID. Semicolon separates multiple Build Tags (e.g. Test;TEST2;Ready)
#>
function Set-BuildTag
{
[CmdletBinding()]
[OutputType([object])]
param
(
[string] $BuildID="",
[string] $BuildTags=""
)
$buildTagsArray = $BuildTags.Split(";");
$token = New-VSTSAuthenticationToken
Write-Host "BaseURL: [$baseurl]"
Write-Host "tagURL: [$tagURL]"
Write-Host "token: [$token]"
if ($buildTagsArray.Count -gt 0)
{
foreach($tag in $buildTagsArray)
{
$tagURL = "$baseurl/build/builds/$BuildID/tags/$tag`?api-version=2.0"
$response = Invoke-RestMethod Uri $tagURL Headers @{Authorization = $token} Method Put
Write-Host $response
}
}
}
<#
.Synopsis
Sets a Build Tag on a specific BuildID. Semicolon separates multiple Build Tags (e.g. Test;TEST2;Ready)
#>
function Get-BuildTrigger
{
[CmdletBinding()]
[OutputType([object])]
param
(
[string] $BuildID=""
)
$token = New-VSTSAuthenticationToken
$buildUrl = "$baseurl/build/builds/$($BuildID)?api-version=2.0"
$response = Invoke-RestMethod Uri $buildUrl Headers @{Authorization = $token} Method Get
return $response.reason
}
function Set-BuildTagToTrigger
{
param
(
[string] $BuildID=""
)
$reason = Get-BuildTrigger BuildID $BuildID
Set-BuildTag BuildID $BuildID BuildTags $reason
}
Set-BuildTagToTrigger BuildID $BuildID

Add this script to your pipeline and call it using the $(Build.BuildId) parameter and you’re all set !

pic4

Trackbacks/Pingbacks

  1. Only trigger a release when the build changed | The Road to ALM - May 1, 2017

    […] Then, in the Release Pipeline that deploys this build, I set up the trigger Tag, so that it only releases builds with the right trigger. I’ve described that in my previous blog post  […]

  2. Only trigger a release when the build changed — Xebia Blog - May 1, 2017

    […] Then, in the Release Pipeline that deploys this build, I set up the trigger Tag, so that it only releases builds with the right trigger. I’ve described that in my previous blog post  […]

%d bloggers like this: