Travis(Surge, Github) => Auto Deploy Every PR, Branch and Tag
The entire setup is free if your project is open source.
You can visit the following URLs to check different automatically deployed versions of the project:
Latest Version: https://latest-onfido-sdk-ui-onfido.surge.sh
Latest Master: https://master-branch-onfido-sdk-ui-onfido.surge.sh
Pull request thread: https://95-pr-onfido-sdk-ui-onfido.surge.sh
Pull request deployed: https://github.com/onfido/onfido-sdk-ui/pull/95
The drive to have such an exhaustive deployment of different versions of the project was to allow for better manual testing and to provide easy progress updates to our wider team.
The automatic deployment of each Git/Github data structure has its own purpose, they will be discussed below.
Automatically deploying every branch allows one to keep track of the bleeding edge of development. By deploying each branch one can see the status of development of a particular feature.
Tags, by convention, are meant to indicate different releases of a project. By deploying each tag one can look back in time and see how the project has changed with each release. By deploying the latest tag to always the same URL, one can also keep track of the status of the latest release.
Pull requests have the purpose to review changes before they are merged. But since Github only shows you code (and images), non software developers cannot really review much. Also, to fully review the result of the code changes, as a developer, one would have to run the code locally, which few developers do.
Therefore, if the changes of the pull request were to be deployed, anyone could easily test them. This is particularly important for non technical roles, such as designers or project managers. With this solution they could also review codebase changes and approve them before they are merged.
What is Travis?
Travis is a continuous integration service used to automatically build software projects hosted in Github. It supports multiple platforms and languages. It also supports scripting which allows one to run tests and, more importantly for this article, to deploy a project using cloud services such as surge.sh.
What is surge.sh?
It’s a simplified way to deploy static websites with a command line tool.
With surge you can define for free a subdomain to deploy your static website. The following command would deploy everything in its contained folder to the specified domain:
You do have to take care not to clash with existing subdomains, since there is no enforced namespacing. Therefore anyone can potentially deploy to a domain which has not yet been taken. If you do not want to specify a domain, surge will chose one for you randomly.
So what is
Travis(Surge, Github) => Automatic Deployment?
The idea talked about in this article can be implemented by using Travis as the backbone, which listens to every Github project update and then triggers a build process and feeds the results of that to surge.sh for deployment.
The technical solution had to consider multiple aspects, namely how to namespace the deploy URLs and how to pipe the results of the build to surge.sh.
Details of this technical implementation will be described below.
The hooks to Github and Git project updates are provided for free by Travis, no real configuration is necessary. Every time there is a new status update a build is triggered for that particular status change.
Types of Project Update
As mentioned, every project update will have its own build run. The following are the different types of a project updates and what triggers a build run for each:
- Branch: Every time a new branch is created or the commit its HEAD points to changes;
- Pull Request: Every time a pull request is created or if it’s associated branches change in any way;
- Tag: Every time a new tag is created or its commit changes;
Each build run can have it own distinct set of actions, before, after and during the build step.
To truly customize the build runs to our intents, we determine, after the build step is complete, which type of project update triggered the build. When that is known, we decide how to deploy the output of the build step to surge.
Note: Travis actually has out-of-the-box support for surge: docs.travis-ci.com/user/deployment/surge/. However, we do not use this functionality due to a configuration limitation that does not allow us to use dynamically generated URLs as the target deploy domain name.
The deploy URL structure
When deploying we enforce a URL structure according to the type of project update (and other details) to create unique and meaningful domain names.
By knowing the structure, one can even guess what the URL is going to be if he knows the details about the project update.
Project name spacing
In order to reduce the chance of colliding with other projects deployed to surge, we namespace all the deployed urls with the following suffix:
- Format: (…)
- Example: https://latest-onfido-sdk-ui-onfido.surge.sh
Project update prefix: Pull Request
Each pull request has its own URL. To allow for this a prefix that precedes the general namespace is added, which includes the pull request number, making the url unique.
The generated url will also be posted in the Pull Request thread as a bot comment, this way participants of the thread can just click to see the deployed result. Eg. https://github.com/onfido/onfido-sdk-ui/pull/95
Project update prefix: Branch
The format of the branch prefix is quite simple, it uses its name and a
branch keyword for proper namespacing.
Project update prefix: Tags
Tags actually have two potential deploy urls. In this scheme tags are treated as product releases. Therefore the tag with the highest version number will be considered the latest, and will have its own dedicated url, as well as its specific version url.
Specific Version TAG:
Note, if the tag version
0.11.0 was the latest release, the two provided examples would point to the same code. That is until a new version would come in.
The configuration file that calls the deploy script after the build step is complete.
The deploy script (written in Travis compatible bash).