A first look at GitHub Action - converting my Azure DevOps tasks to GitHub Actions

Introduction

GitHub Actions open up an interesting new way to provide CI/CD automation for your GitHub projects, other than the historic options of Jenkins, Bamboo, Team City, Azure DevOps Pipelines etc. No longer do you have to leave the realm of GitHub to create a powerful CI/CD process or provision a separate system.

For people familiar with Azure DevOps YAML based Pipelines you will notice some common concepts in GitHub Actions. However, GitHub Action’s YAML syntax is different and Actions are not Tasks.You can’t just re-use your old Azure DevOps tasks.

So my mind quickly went to the question ‘how much work is involved to allow me to re-use my Azure DevOps Pipeline Tasks?’. I know I probably won’t be moving them to Docker, but surely I can reuse my Node based ones somehow?

The Migration Process

The first thing to consider is ‘are they of any use?’.

Any task that used the Azure DevOps API was going to need loads of work, if even relevant on GitHub. But, my Versioning tasks seemed good candidates. They still needed some edits, such as the logic to extract a version number from a the build number needed to be removed. This is because GitHub Actions have no concept of build numbers (it is recommended that versioning is done using SemVer and branching).

Given all this I picked one for migration, my JSONVersioner

The first step was to create a new empty GitHub repo for my new Action. I did this using the JavaScript template and followed the Getting Started instructions. This allowed me to make sure I had a working starting point.

I then copied in my JSON file versioner task into the repo bit by bit

  • Renamed my entry ApplyVersionToJSONFile.ts file to main.ts to keep inline with the template standard

  • Copied over the AppyVersionToJSONFuncitons.js

  • I removed any Azure DevOps specific code that was not needed.

  • In both files swapped the references to "vsts-task-lib/task" to "@actions/core" and update the related function calls to use

  • core.getInput()

  • core.debug()

  • core.warning()

  • core.SetFailed()

  • Altered my handling of input variables defaults to use the GitHub Actions as opposed to Azure DevOps Pipeline variables (to find the current working folder)

  • Migrated the manifest from the task.json to the action.yaml

  • Updated the readme.md with suitable usage details.

And that was basically it, the Action just worked, I could call my Action from a test workflow in another GitHub repo

However, I did decided to do a bit more work

  • I moved my Mocha/Chai based tests over to use Jest, again to keep inline with the template example. This was actually the main area of effort for me. Jest runs it’s tests async, and this caused me problem with my temporary file handling that had to be reworked. I also took the chance to improve the tests handing of the JSON comparison, making it more resilient for cross platform testing.
  • I also added TSLint to the npm build process, something I do for all my TypeScript based projects to keep up code quality

Summary

So the basic act of migration from Azure DevOps Pipeline Extension to GitHub Actions is not that hard if you take it step by step.

The difficultly will be with what your tasks do, are they even relevant to GitHub Actions? And are any APIs you need available?

So migration of Azure DevOps Extension Tasks to GitHub Actions is not an impossible task, have a look at my source at JSONFileVersioner or in the actual task in the GitHub Marketplace with the usage

 1jobs:
 2
 3   build:
 4
 5     runs-on: ubuntu-latest
 6
 7     strategy:
 8
 9        matrix:
10
11           node-version: \[12.x\]
12
13  steps:
14
15     - uses: actions/checkout@v1
16
17    - **uses: rfennell/JSONFileVersioner@v1**
18
19 **with:**
20
21 **Path: ''**
22
23 **Field: 'version'**
24
25 **FilenamePattern: '.json'**
26
27 **Recursion: 'true'**
28
29    - name: Use Node.js ${{ matrix.node-version }}   
30
31      uses: actions/setup-node@v1
32
33      with:
34
35         node-version: ${{ matrix.node-version }}
36
37    - name: npm install, build, and test
38
39      run: |
40
41        npm install
42
43        npm run build --if-present
44
45        npm test
46
47  env:
48
49     CI: true
50
51  
52
53  

There is a nice series of posts on Actions from Microsoft’s Abel Wang - Github Actions 2.0 Is Here!!!