Engineering at MindLink

Publishing to GitHub Pages from TFS

April 13, 2018

Recently we decided it was time to publish our own blog to showcase some of what our talented engineers do and find interesting. To do this with the existing tools and as cheaply and quickly as possible we needed to link Team Foundation Server (TFS) to GitHub Pages.

TL;DR

To deploy from TFS to GitHub pages:

  1. Install the gh-pages npm module
  2. Define an npm script to run gh-pages e.g. “deploy”: “gh-pages -d public”
  3. Use TFS secure variables to inject a GitHub personal token into gh-pages call
  4. Combined this means defining a build step of the form

    • npm run deploy — -r https://$(GH_TOKEN)@github.com/user/repository.git
    • The (that’s a double -) tells npm that it should forward what follows as additional script arguments
    • The -r is the gh-pages argument for defining an alternative repository
    • The $(GH_TOKEN) will be replaced by TFS with the value of the variable called GH_TOKEN

Onward to a continuously deployed blog

Here at MindLink we use Microsoft Team Foundation Server to host our source in a git repository, manage the build and release process and track our iterations. It’s all nice and integrated!

We wanted to keep ownership of the blogging platform as seems to be the trend, as opposed to using a service like medium. The main reason for this is that by having control we also gain the ability to change where we publish and how we publish in future.

GitHub pages struck us as the perfect platform for a low cost (free) way to publish a blog and is widely used for such a purpose. It also has a simple way to publish a site - simply push a static site to a specific repository (or gh-pages branch in a project repository). You can read more about GitHub pages here.

What we wanted was a simple way to write a blog post and automatically publish it using the tools our engineers use every day.

This will give it a low barrier to entry and encourage all the development team to contribute!

As TFS was our existing git repository host and build system it made sense to leverage that for the blog source and release mechanism. Getting TFS to publish a built static site to GitHub is not so straight forward.

With a static site generator (gatsby in this case) it’s easy to take a source tree and build a static site. That’s step 1.

To take that static site and publish it to GitHub when you’re not already in a GitHub repository is less straight-forward, but still perfectly doable!

  1. Use the gh-pages npm module to publish
  2. Use an npm script to define the standard gh-pages script
  3. Get TFS build to run the npm script and inject the GitHub credentials and target repository
  4. Setup the build triggers to either run on every commit, schedule it or do something else

I’d probably also suggest splitting the build and release phases if you’re worried about publishing potentially broken sites. Since TFS has a fairly powerful build and release mechanism you can get a process that works for you!

The details

I’m going to assume the following:

  1. You already have a script to build the static site (maybe an npm script or gulp or grunt process)
  2. The static site is built to /public in the root directory

Setup gh-pages npm script

The first step is to install the node modules we will need (I’m using yarn here but it will work just as well with npm install): yarn add gh-pages.

With that installed we’ll now specify an npm script to publish the built static site (you could just as easily do this with a task runner like gulp or grunt instead, the trick is in injecting the GitHub key):

{
    ...,
    "scripts": {
        ...,
        "deploy": "gh-pages -d public"
    }
}

This tells gh-pages to run using only the “public” folder. With only this configuration it will add a branch called gh-pages to the current repository.

Get TFS Build to run the script

For the second step we need to tell TFS build to run this script and target a GitHub repository instead!

Get yourself a personal access token from GitHub by going to github token settings for your account and creating a new access token. Make sure you give it permission to read and write to public repositories. Copy that token and don’t lose it!

Now go to your TFS build configuration and select the variables tab. Add the token as a secure variable with any name you like - here we use GH_TOKEN.

TFS Variables

Next add a new build step to run our deploy script as below:

TFS Build Step

Type: npm
Run: custom
Arguments: deploy — -b master -r https://$(GH_TOKEN)@github.com/MindLink/MindLink.github.io.git

That’s it! TFS build will run the npm script “deploy” and pass additional arguments:

  • -b master => publish to the master branch of the repository
  • -r https://$(GH_TOKEN)@<repository> => publish to a repository using the personal token (which allows you to publish without a user/pass)

Now whenever you trigger the build it will publish a new version of your static site to GitHub Pages.

Wrap up

This is the exactly how we have started doing it. Right now our team has total freedom to push updates to the blog with continuous deployment, in future that may change to a more managed release process, but our aim is to get our content out with as few steps as possible!

If you’re interested the full process for somebody to post an article to our blog is:

  1. Checkout the blog source
  2. Add an author yaml entry if they’ve not already got one
  3. Add a new post folder with a unique name
  4. Add a markdown article with front matter (author, title, date and tags)
  5. Run it locally first if you like
  6. Commit and push

We could distil this further, but we shall see how we get on! A couple of ideas are:

  • don’t require a separate folder, so you just create the markdown article and push
  • Support drafts so you can push without publishing, but still view in develop

Luke Terry

Written by Luke Terry.

Senior Engineer at MindLink. Enjoys technology, playing games and making things work, blogs at www.indescrible.co.uk.