Travis Continuous deployment for your open source library

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

  1. Go to the repository page: https://travis-ci.org/account/repositories.
  2. Click on “Sync account” to make sure all your repository are present.
  3. In the “Filter repository” search box, start typing the name of your repo.
  4. When you find it, toggle to checkbox to enable Travis for this project

Configure the settings of your repository in Travis

  1. After enabling your repo, click on “Settings”
  2. 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?

Travis UI of Stages and Jobs
Stages and Jobs in 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

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:

[![Build Status](https://travis-ci.org/[GITHUB_USER]/[GITHUB_PROJECT_NAME].svg?branch=[BRANCH_NAME])](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:

Badge for the project “safety_plugin”

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.

Leave a Reply

%d bloggers like this: