Introduction
Today in this article, we are going to see how to take your open source project and let Travis test, build and deploy your project, all for free.
Create a Travis account
Go to https://travis-ci.org/ and click “Sign up”, log in using your Github account.
Attach your repository in Travis
- Go to the repository page: https://travis-ci.org/account/repositories.
- Click on “Sync account” to make sure all your repository are present.
- In the “Filter repository” search box, start typing the name of your repo.
- When you find it, toggle to checkbox to enable Travis for this project
Configure the settings of your repository in Travis
- After enabling your repo, click on “Settings”
- For my repo, here are my settings:
- Build pushed branches : ON
- Build pushed pull requests: ON
- Limit concurrent jobs: OFF
- Auto cancel branch builds: ON
- Auto cancel pull request builds: ON
- Cron Jobs:
- branch master
- Runs monthly
- Do not run if there has been a build in the last 24h
You can look at my project at https://travis-ci.org/leobenkel/safety_plugin.
Configure the .travis.yml file
The yml config file is extremely confusing. I will try to do my best explaining it simply.
Key concepts (Stages and Jobs)
Stages
A Stage in Travis is a collection of Jobs.
Each stage run sequentially and will only run if all previous Stage have succeeded.
You define them in the stages key in the yml file.
For instance:
stages:
- name: clean
- name: test
- name: release
if: ((branch = master AND type = push) OR (tag IS present)) AND NOT fork
In this example of stages declaration, we have 3 stages: clean, test, release. Note here that the release stage have condition, it will only execute if the condition is True.
Jobs
A Job in Travis is part of a Stage and they will run in parallel.
You declare them inside jobs > include in the config file.
For instance:
jobs:
include:
- stage: cleanStage
name: cleanJob
script: make clean
In this example, we have declared on Job inside the Stage named cleanStage , the job is named cleanJob and the code executed will be make clean.
To declare several Job inside one Stage, you have to do something like:
jobs:
include:
- stage: test
name: compile
script: sbt compile
-
name: scalafmt
script: ./bin/scalafmt --test
-
name: unit-test
script: make unit_test
In this example, there are 3 Jobs inside the Stage named test. The three jobs are named compile, scalafmt, unit-test. Those 3 Jobs will run in parallel.
What does it look like in the Travis UI?
The screenshot have been taken from this Travis build: https://travis-ci.org/leobenkel/safety_plugin/builds/544870243.
You can see 3 Stages: Clean, Test, Release. Each of those stage will run one after another.
Inside the Test stage, each Jobs will run together in parallel.
If any of the Jobs fail, the owning Stage will be marked as fail. If any of the previous Stage have failed, all next Stages will not run.
Have several step inside a Job
To have sequential steps inside a job, you have to do:
jobs:
include:
- stage: StageName
name: JobName
script:
- step 1
- step 2
Summary – all together
Here is an example, all together:
stages:
- name: clean
- name: test
- name: release
if: ((branch = master AND type = push) OR (tag IS present)) AND NOT fork
jobs:
include:
- stage: clean
name: clean
script: make deep_clean
- stage: test
name: compile
script: sbt compile
-
name: scalafmt
script: ./bin/scalafmt --test
-
name: mutators-test
script: make mutator_test
if: branch = master AND type = push AND NOT fork
-
name: plugin-test
script: make test_plugin
-
name: unit-test
script:
- make test_coverage test_coverage_report
- sbt coveralls
- stage: release
name: release
script: sbt ci-release
In this example, taken from this repo: Safety_Plugin
- There are three stages, named:
clean,test,release:- Clean contains 1 job:
make deep_clean
- Test contains 4 jobs, including one with a condition
- Release contains 1 job:
sbt ci-release
- Clean contains 1 job:
I hope this help you understand the Travis config file. Let me know in the comment below if you have any questions !
Install the Travis badge in your README.md file
To add the badge in your README file, edit the file and add this line of code:
[](https://travis-ci.org//[GITHUB_USER]/[GITHUB_PROJECT_NAME])
Replace[BRANCH_NAME] by the name of the branch you want to monitor, usually master , [GITHUB_USER] by your user group name and [GITHUB_PROJECT_NAME] by the name of your project. It correspond to the github URL in this way:
https://github.com/[GITHUB_USER]/[GITHUB_PROJECT_NAME]
For my project, it looks something like:
And this badge will update when you push new code to the monitored branch. It can be marked as failing if the build have failed for the monitored branch. The caching is marked for 7 days so you might have to wipe you local cache out if you want to see the most recent update for your project.
Build Optimization
Caching
You can add those lines below to cache the dependencies and speed up the build process.
# https://github.com/olafurpg/sbt-ci-release/blob/master/.travis.yml
cache:
directories:
- $HOME/.sbt/1.0/dependency
- $HOME/.sbt/boot/scala*
- $HOME/.sbt/launchers
- $HOME/.ivy2/cache
- $HOME/.coursier
before_cache:
- du -h -d 1 $HOME/.ivy2/cache
- du -h -d 2 $HOME/.sbt/
- find $HOME/.sbt -name "*.lock" -type f -delete
- find $HOME/.ivy2/cache -name "ivydata-*.properties" -type f -delete
- rm -rf $HOME/.ivy2/local
Parallel test
I put all my test Job inside one Stage so they can run in parallel:
jobs:
include:
- ...other Stages...
- stage: test
name: compile
script: sbt compile
-
name: scalafmt
script: ./bin/scalafmt --test
-
name: plugin-test
script: make test_plugin
-
name: unit-test
script:
- make test_coverage test_coverage_report
- sbt coveralls
Add a clean up stage
I added a first clean up stage, that allow the virtual machine to fetch the dependency during this Stage and keep it for the next Stages.
jobs:
include:
- stage: clean
name: clean
script: sbt clean
Conclusion
That’s it for today ! Let me know if you have any questions about how to set up your Travis pipeline in the comment below or if you have things to add to this article.
