VSTS Build Task: GitHub Tag

So you are utilizing Visual Studio Team Services as your build server for direct integration into GitHub, perhaps entirely or perhaps just for your public repo’s in GitHub (while your private repo’s are in VSTS). In either case, in a standard continuous delivery fashion your going to want to publish a tag to your GitHub repo whenever you have a successful packaging of your software.

Lucky for us, the GitHub API makes this a pretty trivial web request, so all we need to do is wire it up inside a custom VSTS Build Task. If our not sure of the basics of custom build tasks, check out “Building Custom VSTS Tasks“.

Getting Started

We are going to simply create a standard GitHub reference for our tag (lightweight), utilizing this API here:

https://developer.github.com/v3/git/refs/#create-a-reference

If you just want the task code, find it and others here:

https://github.com/travisgosselin/vsts-tasks 

And then you’ll have a task that looks like this at the end:

Capture

Tag: This will the actual name of the reference you want to create. We will default it to the existing build number, assuming that build number is our continuous delivery number we want to tag $(Build.BuildNumber). But you could manually enter a tag or some other dynamic combination here.

Repository Name: The name of the repository that the tag will be added too (you’ll specify account below under “owner”).

Commit: This is the commit hash that the reference should be applied too. Of course you’ll likely want that applied to the latest commit in which this build definition is consuming, in which case stick with the default build variable: $(Build.SourceVersion)

Owner: This is the repository owner. It can also be an organization (since that is the owner in some cases). For example, my own repo, my account (username) is “travisgosselin” from http://github.com/travisgosselin

OAuth Token: You must supply credentials which have access to add tag references to this repository. Utilizing an account with the necessary permissions, create a personal access token and added it in here. If your  not sure how to create a Personal Access Token then check out this article. Also remember if you don’t want to leave your access token out in the open for others on your account to steal, you can add this token under the “Variables” section of the build utilizing the encryption option and then specify the variable here instead.

 Task JSON Definition

Below is the JSON task definition as an example. You may want to add your own custom defaults for owner or token if you plan to utilize it personally. I have a copy of this task utilized in my organization that defaults all of the “Advanced” settings so you can drop the task in without any modifications (other than repo) and your good to go.

  1. {
  2.         "id": "fa562823-36f1-412d-9393-8d953f9cb289",
  3.         "name": "GitTag",
  4.         "friendlyName": "GitHub Tag",
  5.         "description": "Add a tag to GitHub on a supplied repository using the GitHub API.",
  6.         "category": "Build",
  7.         "visibility": [ "Build" ],
  8.         "author": "Travis Gosselin",
  9.         "version": { "Major": 1, "Minor": 0, "Patch": 0 },
  10.     "groups": [
  11.         {
  12.             "name": "advanced",
  13.             "displayName": "Advanced",
  14.             "isExpanded": true
  15.         }
  16.     ],
  17.         "inputs": [
  18.                 {
  19.                         "name": "Tag",
  20.                         "type": "string",
  21.                         "label": "Tag",
  22.                         "defaultValue": "$(Build.BuildNumber)",
  23.                         "required": true,
  24.                         "helpMarkDown": "Tag to add to the related repository and branch. Defaults to $(Build.BuildNumber)."
  25.                 },
  26.                 {
  27.                         "name": "Repo",
  28.                         "type": "string",
  29.                         "label": "Repository Name",
  30.                         "defaultValue": "",
  31.                         "required": true,
  32.                         "helpMarkDown": "The name of the repository to add thte tag to."
  33.                 },
  34.                 {
  35.                         "name": "Commit",
  36.                         "type": "string",
  37.                         "label": "Commit",
  38.                         "defaultValue": "$(Build.SourceVersion)",
  39.                         "required": true,
  40.                         "helpMarkDown": "The SHA commit id to which the tag should be applied. By default is $(Build.SourceVersion), which is the building commit id.",
  41.             "groupName": "advanced"
  42.                 },
  43.                 {
  44.                         "name": "Owner",
  45.                         "type": "string",
  46.                         "label": "Owner",
  47.                         "defaultValue": "",
  48.                         "required": false,
  49.                         "helpMarkDown": "The owner of the repository to form the URL.",
  50.             "groupName": "advanced"
  51.                 },
  52.                 {
  53.                         "name": "AuthToken",
  54.                         "type": "string",
  55.                         "label": "OAuth Token",
  56.                         "defaultValue": "",
  57.                         "required": false,
  58.                         "helpMarkDown": "The OAuth token for a user with write permission to this repository to create the tag.",
  59.             "groupName": "advanced"
  60.                 }
  61.         ],
  62.     "instanceNameFormat": "Git Tag $(Tag) on Repo $(Repo)",
  63.         "execution": {
  64.                 "PowerShell": {
  65.                         "target": "$(currentDirectory)\\tag.ps1",
  66.                         "argumentFormat": "",
  67.                         "workingDirectory": "$currentDirectory"
  68.                 }
  69.         }
  70. }

 

PowerShell Script

The script to generate the GitHub Tag is relatively simple, take a peak:

  1. #Variables
  2. param ([string]$Tag, [string]$Repo, [string]$Commit, [string]$Owner, [string]$AuthToken)
  3.  
  4. Write-Host "Adding GIT tag $Tag for repo $Repo under owner $Owner"
  5.  
  6. $resource = "https://api.github.com/repos/$Owner/$Repo/git/refs"
  7. Write-Host "Posting to URL: $resource"
  8.  
  9. $body = @{
  10.     ‘ref’ = "refs/tags/$Tag";
  11.     ‘sha’ = "$Commit"}
  12.  
  13. $jsonBody = (ConvertTo-Json $body)
  14. Write-Host "Posting with Body: $jsonBody"
  15.  
  16. $result = Invoke-RestMethod -Method Post -Uri $resource -Body (ConvertTo-Json $body) -Header @{"Authorization" = "token $AuthToken"}
  17.  
  18. Write-Host $result

Any improvements on error handling and scripting is much appreciated!

Also, I’m always on the lookout for some other repo’s of VSTS Build Tasks that might add some great utility. Please leave em’ in the comments if you know of any!