Hello!

I’m currently working on a project where we are using git as our source control, and so we have created branch policies on master that specify a specific VSTS build must be green before a pull request can be accepted. This is great, because what I like to do with any pull request is pull the branch and run the build, deploy and test scripts to make sure that at the very least, all this passes. So by adding the builds as a branch policy at least gives a thumbs up, at least in the sense that the code compiles.

However this is really only one of three stages that we have, the other two being deploy and test. And whilst some tests do run as part of the build, we have Pester tests that test that the ARM Templates have deployed objects to the Resource Group (1). So I’d really like to be able to add a release as a branch policy. Sadly this is not yet do-able. So to this end I have 3 choices -

  1. Forget about it, and hope that the build is good enough. This is perhaps not an unreasonable approach to take, however my concern here is that to thoroughly check the pr a dev is going to have to do this, so it makes total sesne to automate this so we know it is done at least once.
  2. Someway or another run the release scripts within the build. Depending on your release pipeline this can be relatively trivial to very hard.
  3. Kick off a release within a build and monitor status of release within that build. This is two separate steps, and also because the way that build artifacts are published after a build has completed, we will need to set up a new build and add that as a branch policy, whilst having access to the latest artifacts.

This third step will be tricky to implement because we’re going to need to make use of the VSTS API. But to make life easier I’ve written a PowerShell module that can be used both locally and in VSTS build steps. It’s called rib 0.0.0.30, which is short for “Release In Build”

For the first step you need to create a step in the build that will kick off the trigger build -

[cmdletbinding()]
param (
	[parameter(Mandatory = $true)] $vstsAccountName,
	[parameter(Mandatory = $true)] $vstsProjectName,
	[parameter(Mandatory = $true)] $vstsBuildToTrigger
	
)

try {
	Find-Module -Name "rib"
	Install-PackageProvider -Name NuGet -Force -Scope CurrentUser
    Install-Module rib -Force -Scope CurrentUser
}
catch {
	Write-Host "No rib, Installing from PSGallery."
    Install-PackageProvider -Name NuGet -Force -Scope CurrentUser
    Install-Module rib -Force -Scope CurrentUser
}
finally {
	Write-Host "Importing rib."
	Import-Module rib -Force
}

$build = Get-VstsBuild -vstsAccount $vstsAccountName -projectName $vstsProjectName -buildName $vstsBuildToTrigger
$buildid = $build.definition.id
$buildOutput = Invoke-VstsBuild -vstsAccount $vstsAccountName -projectName $vstsProjectName -buildId $buildId
Write-Output $buildOutput | ConvertTo-Json

After that it is a case of creating one step in the build that will be triggered - this will kick off a release and monitor the status of the release. It’s still early days so the build step does not do any real reporting of the release, just whether it passes or fails.

[cmdletbinding()]
param (
	[parameter(Mandatory = $true)] $vstsAccountName,
	[parameter(Mandatory = $true)] $vstsProjectName,
	[parameter(Mandatory = $true)] $vstsReleaseToTrigger
	
)
try {
	Find-Module -Name "rib"
	Install-PackageProvider -Name NuGet -Force -Scope CurrentUser
    Install-Module rib -Force -Scope CurrentUser
}
catch {
	Write-Host "No rib, Installing from PSGallery."
    Install-PackageProvider -Name NuGet -Force -Scope CurrentUser
    Install-Module rib -Force -Scope CurrentUser
}
finally {
	Write-Host "Importing rib."
	Import-Module rib -Force
}

$release = Get-VstsReleaseByName -vstsAccount $vstsAccountName -projectName $vstsProjectName -releaseName $vstsReleaseToTrigger
$releaseDefinitionId = $release.releaseDefinition.id
$selfRef = $release._links.self.href
$thisRelease = Get-VstsRelease -vstsAccount $accountName -projectName $proj -releaseSelfUri $selfRef
$buildArtifactAlias = $thisRelease.artifacts.alias
Invoke-VstsReleaseInBuild -vstsAccount $vstsAccountName -projectName $vstsProjectName -releaseDefinitionId $releaseDefinitionId -buildArtifactAlias $buildArtifactAlias

There is a limitation with the Module in that when you create a release you need to specify the artifacts, and currently the json that is published to create the release is hardcoded to only accept one release artifact (see Get-VstsRelease is used to return the release, and then we pass the alias to Invoke-VstsReleaseInBuild). Some way or another this could be improved to return all alias’, but for my purposes right now this will do (it is in development anyway!)

One thing I need to crack on with is some more documentation. I’ll also concede it may be a little odd to create a build jsut to act as a wrapper - why not just add your release steps to the end of a build for example? But I’m not a fan of this as it’s not testing the release process, it merely mimmicks it. It also means that the build has to be maintained when releases are changed, something that may be forgotten. On a personal level, one thing from this project is that it has been useful to find out that you can use the oauth token when executing a PowerShell script so that it can access the VSTS REST API within the build/release process itself.

(1) For example - we have Firewall rules to allow connections via ranges of IPs. After a deployment has run, we run the Azure PowerShell Function Get-AzureRmSqlServerFirewallRule and check that the start and end ranges are as we expect them. This means that if someone accidentally changes these, or are dropped then the tests will pick them up. This is infinitely more useful than finding out when no one can connect!