Publishing to gh-pages from Travis CI

I figured out how to 'publish to gh-pages' (i.e. building and publishing a website into GitHub pages) using Travis CI. Instead of messing with the serious repository, I made a simple repository which builds and publishes its web page daily, using Travis CI's cron feature. You can clone/fork it and read the instructions on the README or you can read on here for why I did it this way.

Many projects use Travis CI to run tests automatically, but with the experimental additional feature of a cron you could use the service for many more things. Such, as for example, automatically build and publish to a site that uses GitHub pages.

Unfortunately it isn't immediately obvious how to do this. It took me a bit of research and 'scratching my head' to understand what's going on and why the common solution isn't the best if you're working on a repository with other people.

It helps to ask ourselves: how do the two systems talk to each other normally?

If Travis CI is enabled on a repository, there will be an entry for it in the "Integrations and services" section of the repository settings in GitHub. Whenever an action such as pushing a commit happens in the repository, Travis CI is notified. And will, maybe, create a build from there, grabbing the code for that commit.

So the communication goes GitHub -> Travis, and generally Travis has a 'read' view of GitHub, so it cannot push data back, which is what you need to publish websites in GitHub, as it implies pushing a new commit to the gh-pages branch (which you might also need to create).

The common advice is to generate a GitHub personal access token with write repository access, and adding it to Travis, so it can use it on the builds. Therefore, Travis can push back to GitHub and the problem is solved, right?

But these tokens are meant to be secret, as they enable anyone with access to them to get your GitHub privileges in all the repositories you have access to. Which is why a) you don't check them into the source code, and b) you enable the option in Travis to hide them from the build, so no one can read the token in the build log. So in theory this token is all safe inside Travis CI... or is it?

What if someone else is working with you in the same project and modifies the Travis CI build script to email them your token? Or maybe they somehow print it in the log and someone else sees it and impersonates you? Your fellow developers don't need to be malicious per se: never underestimate the possibility of accidents! In any case, I don't know about you, but this got me a bit nervous.

GitHub tokens stored in an environment that can execute arbitrary code when working with more people are perhaps not a good idea then. They are not finely grained enough. What can we do if we still want to push data?

Good news: there are SSH deploy keys. They work very similarly to GitHub's SSH keys per user, but they will be valid for only that repository... which means that people that get access to the token do not get immediate access to all of your other repositories. And they are indeed finely grained, compared to the personal access token.

I learnt all of this from this fantastic gist by Domenic Denicola (and many commenters). I didn't want to copy and paste and edit his script though, I wanted a better way that didn't involve me going back to the gist each time I wanted to set up a project like this. Luckily someone had had the same idea and had written the gh-pages-travis npm module.

With that and my newly acquired understanding of what was going on, I managed to set up my automatically published to gh-pages repository, imaginatively named publish-and-cron.

If you want to do the same thing, you could use this as a skeleton repo. Instead of just generating an index.html in output, you could generate your entire static blog there, or any other thing that you want to publish from source code. There is still a bit of set up involved, as creating the keys and all that is not automated, but the basic pieces are in place. Instructions for creating the keys and the rest are all in the README, I'm not going to replicate them here O:-)

We're using this for the new Firefox Developer Tools technical docs, which are written in Markdown and rendered with GitBook. So we render the book and then publish it once a day, automatically. And the onus is not on 'the webmaster' to publish updates--it is automatically done. Here's the repository that renders the docs; the website is on the gh-pages branch.

Now we just need to write the docs 😏