How to use Travis CI to automatically deploy a HarpJS application to GitHub Pages

How to use Travis CI to automatically deploy a HarpJS application to GitHub Pages
Photo by Possessed Photography / Unsplash

If you're a HarpJS fan like me and you want to easily deploy HarpJS applications to GitHub Pages, stay with me and by the end of this article you will know exactly how to automatically deploy your applications to GitHub Pages and host them for free on GitHub's CDN.

  • HarpJS is free static web server with built-in preprocessing.
  • GitHub Pages is an amazing GitHub service to host your project sites for free.
  • Travis CI is a free (for public repositories) hosted continuous integration service integrated with GitHub.
This article assumes that you already have a HarpJS application running. If you're not familiar with HarpJS and you want to learn more about it, feel free to check out http://harpjs.com.

The manual way

The default "Deploy to GitHub" procedure is a bit cumbersome if you need to update and re-deploy your project regularly.

There are quite a bit of manual steps involved and switching to your gh-pages branch to recompile a static version of your project can be painful if you have staged and unstaged changes in your repository.

An alternative is to create a _harp directory in your gh-pages branch and develop directly in the gh-pages branch, but that makes it hard to commit changes that you don't want to deploy yet.

The goal

Ideally you should be able to:

  • work in any non gh-pages branch (such as master or development branch)
  • deploy to GitHub Pages using a script from your local machine
  • deploy to GitHub Pages automatically when you update a file on GitHub.com without having to pull in the changes locally and re-deploy

So let's make it happen!

Step 1: create a GitHub token

Because you will interact with GitHub from within a script, you need a way to tell GitHub on who's behalf the script is acting.

For that, you will need a personal access token.

To generate a new personal access token in GitHub, go to Personal settings / Applications and click on Generate new token in the Personal access tokens section of the page:

Give it an appropriate decscription such as "Deployment token for repository X" so you can later identify the token again in case you no longer need it and want to remove it.

Finally copy the generated token that GitHub presents on your screen. It is important to copy it right now because it is only shown once and you'll have to regenerate a new one if you forget it.

Great, so now you have a GitHub token to identify yourself.

It's time to set up Travis.

Step 2: enable your repository in Travis CI

Go to https://travis-ci.org and sign in with your GitHub account.

Open the repositories tab on your accounts pages and toggle the switch next to your repository to enable Travis support for that repository.

If your repository is not in the list, click the Sync now button to let Travis fetch all latest data from GitHub.

Enabling a repository tells GitHub to notify Travis when new code has been committed. Travis then looks for a .travis.yml file in the repository to check for further instructions.

So let's configure Travis in your repository.

Step 3: add a .travis.yml file to your repository

To tell Travis what you want it to do when it receives a notification from GitHub, you need to create a .travis.yml file in your repository.

Travis supports an amazing set of options.

Depending on your actual project, you may or may not need certain commands, but here is a .travis.yml from one of my repositories.

language: node_js
node_js: ['0.10']
before_script:
  - npm install -g bower
  - npm install -g harp
  - bower install
  - npm install
  - chmod +x ./scripts/deploy.sh
script: gulp process-all
after_success: ./scripts/deploy.sh
env:
  global:
    - secure: ...

Let's break down what's happening here

First we tell Travis to instantiate a node.js environment running node v0.10.

The before_script key contains all the commands you want Travis to perform before the script commands are called. If one of these before_script commands fails, the build stops immediately and the script commands are never executed.

When all before_script commands have been completed successfully, we want Travis to run gulp process-all. The main difference with before_script is that if a command from the script commands fails, the build process does not exit immediately.

Depending on the outcome of script, Travis calls the commands defined in after_success or after_failure.

In our case, if the build succeeds, we tell Travis to run the deploy script by running ./scripts/deploy.sh.

This script then takes care of compiling a static version of the project and deploying it to GitHub in the gh-pages branch.

Environment variables

Travis offers a really convenient feature where it lets you define environment variables to customize the build process.

What's more is that it even lets you encrypt these variables so you can add sensitive information to your .travis.yml file without having to worry about others seeing the file.

To add encryped environment variables to your .travis.yml file, you can:

$ gem install travis
$ cd your_project
$ travis encrypt GITHUB_TOKEN=secret-token-from-step-1 --add

This will add a line to your travis.yml file that looks like this:

secure: <encryped string>

When Travis runs your scripts, it will decrypt the encrypted value and make it available as a regular environment variable so you can conveniently access the original GITHUB_TOKEN again.

How cool is that!

Now let's create the actual deployment script.

Step 4: add deployment script

In step 2 we configured Travis to run ./scripts/deploy.sh when the build succeeds, so we need to add a new file deploy.sh to our repository in a directory called scripts:

you can choose any location or file name you like as long as it references the one specified in step 2
#!/bin/bash
echo "Starting deployment"
echo "Target: gh-pages branch"

TEMP_DIRECTORY="/tmp/__temp_static_content"
CURRENT_COMMIT=`git rev-parse HEAD`
ORIGIN_URL=`git config --get remote.origin.url`
ORIGIN_URL_WITH_CREDENTIALS=${ORIGIN_URL/\/\/github.com/\/\/$GITHUB_TOKEN@github.com}

echo "Compiling new static content"
mkdir $TEMP_DIRECTORY || exit 1
harp compile . $TEMP_DIRECTORY || exit 1
cp .gitignore $TEMP_DIRECTORY || exit 1

echo "Checking out gh-pages branch"
git checkout -B gh-pages || exit 1

echo "Removing old static content"
git rm -rf . || exit 1

echo "Copying newly generated static content"
cp -r $TEMP_DIRECTORY/* . || exit 1
cp $TEMP_DIRECTORY/.gitignore . || exit 1

echo "Pushing new content to $ORIGIN_URL"
git config user.name "Travis-CI" || exit 1
git config user.email "travis@jvandemo.com" || exit 1

git add -A . || exit 1
git commit --allow-empty -m "Regenerated static content for $CURRENT_COMMIT" || exit 1
git push --force --quiet "$ORIGIN_URL_WITH_CREDENTIALS" gh-pages > /dev/null 2>&1

echo "Cleaning up temp files"
rm -Rf $TEMP_DIRECTORY

echo "Deployed successfully."
exit 0

View the code on GitHub.

Let's break down the script together

First we extract some git information that we will need later on to push back our changes to GitHub.

Then we use harp compile to compile a static version of our application to a temporary directory. We also copy .gitignore so we can restore it later on.

Next we check out the gh-pages branch, remove all existing content and restore the generated content from the temporary directory.

Finally we commit the changes, push everything to the gh-pages branch on GitHub and clean up temporary files.

Step 5: initiate a build

Now it's time to try everything out.

To trigger a Travis build, we need to update our code in master and push the changes the GitHub.

You can use your own workflow but for the sake of clarity, we just use the master branch in this example.

You should see a new build appear in Travis. Notice the yellow build at the top of the list:

You can click on the build to see the build details:

And follow the output live as it progresses:

If everything went well, your build is marked as passed.

Your application is now available at http://username.github.io/repository-name/.

Check out this live demo hosted on GitHub Pages of the application used as example in this article. I can edit any file in the https://github.com/jvandemo/deploy-harp-to-gh-pages-using-travis repository directly on github.com and Travis will automatically re-deploy the application.

The cool thing is that if anything would have failed, the deployment would not have been executed, ensuring that your live web application is only updated when all commands ran successfully.

Conclusion

Travis is an incredibly powerful tool and can save you tons of time and money.

If you invest some time in reading the Travis documentation you will surely come up with more customized ways to automate many facets of your project, from unit testing to deployment.

For example you could tweak the .travis.yml file to:

  • only re-deploy when a certain message appears in a commit
  • only re-deploy when a commit is pushed to a certain branch
  • only re-deploy when unit tests have passed
  • etc

In this article we focused on deploying a HarpJS application to GitHub Pages, but the possibilities are truly endless. Even if you don't use HarpJS or GitHub Pages, you can equally benefit from using Travis CI.

Give it a try. I'm sure you'll love it!

Have a great one!

All code and a working demo are available on https://github.com/jvandemo/deploy-harp-to-gh-pages-using-travis.