Home  >   Blog  >   Programming   >   Moving Julia Project from Travis CI to GitHub Actions #JuliaLang

2021-03-06

Moving Julia Project from Travis CI to GitHub Actions #JuliaLang


Thanks to a pull-request "Install TagBot as a GitHub Action", which was created by a bot, I realized now is the time to move one of my Julia projects, Recommendation.jl, from Travis CI to GitHub Actions.

Since I haven't had enough time to work on the project for a year, migration was not straightforward as I expected. Hence, this post summarizes what I've undergone to get there. As always, I referred to some of the most actively/recently maintained official Julia packages (e.g., Statistics.jl, Tokenize.jl) to see what is the most 'modern' way to organize a Julia project.

Original .travis.yml

I've written the following Travis CI configuration more than a year ago:

language: julia 

os: 
  - linux 
  - osx 

julia:  
  - 0.7 
  - 1.0 
  - nightly 

matrix: 
  allow_failures: 
  - julia: nightly  

notifications:  
  email: false  

after_success:  
  - julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Coveralls.submit(process_folder())' 

jobs: 
  include:  
    - stage: "Documentation"  
      julia: 1.0  
      os: linux 
      script: 
        - julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd()));  
                                               Pkg.build("Recommendation"); 
                                               Pkg.instantiate()' 
        - julia --project=docs/ docs/make.jl  
      after_success: skip

The workflow breaks down into three pieces:

  1. Unit testing over multiple Julia versions
  2. Profiling test coverage
  3. Building and publishing a documentation page to GitHub Pages

Running a Workflow over multiple Julia versions

First and foremost, what I like about GitHub Actions is the easiness of using a build matrix.

For every pull-requests onto the master branch, as well as push event to the master with an arbitrary tag, the following workflow executes 3x3=9 jobs for 3 Julia versions and 3 operating systems:

name: CI
on:
  pull_request:
    branches:
      - master
  push:
    branches:
      - master
    tags: '*'
jobs:
  test:
    name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        version:
          - '1.0'
          - '1' # automatically expands to the latest stable 1.x release of Julia
          - 'nightly'
        os:
          - ubuntu-latest
          - macOS-latest
          - windows-latest
        arch:
          - x64
    steps:
      # (actual tasks are defined here)

Having a comprehensive build matrix is particularly important for Julia because Julia is one of the rare programming languages that aggressively introduce backward-incompatible changes as the version number grows.

Notice that I dropped Julia 0.7 from the matrix when I switched out the Travis config with GitHub Workflow; considering the stable version is 1.5.3 as of Nov 2020, it's reasonable not to support Julia < 1.0 anymore.

Testing and reporting coverage

Next, we could leverage julia-actions/julia-runtest and julia-actions/julia-processcoverage as follows:

jobs:
  test:
    # (define a build matrix - see above)
    steps:
      - uses: actions/[email protected]
      - uses: julia-actions/[email protected]
        with:
          version: ${{ matrix.version }}
          arch: ${{ matrix.arch }}
      - uses: actions/[email protected]
        env:
          cache-name: cache-artifacts
        with:
          path: ~/.julia/artifacts
          key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
          restore-keys: |
            ${{ runner.os }}-test-${{ env.cache-name }}-
            ${{ runner.os }}-test-
            ${{ runner.os }}-
      - uses: julia-actions/[email protected]
      - uses: julia-actions/[email protected]
      - uses: julia-actions/[email protected]
      - uses: codecov/[email protected]
        with:
          file: lcov.info

As long as your repository is registered to Codecov.io, test coverage is automatically reported in a pull-request. See this comment as an example.

Documenting and hosting on GitHub Pages

Finally, we can define a dedicated job for building and publishing a documentation page using Documenter.jl.

Luckily, there is an official step-by-step guide: Hosting Documentation, and the definition of the job looks like:

jobs:
  docs:
    name: Documentation
    runs-on: ubuntu-latest
    steps:
      - uses: actions/[email protected]
      - uses: julia-actions/[email protected]
        with:
          version: '1'
      - run: |
          julia --project=docs -e '
            using Pkg
            Pkg.develop(PackageSpec(path=pwd()))
            Pkg.instantiate()'
      - run: julia --project=docs docs/make.jl
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}
          DOCUMENTER_DEBUG: true

secrets.GITHUB_TOKEN is automatically set by GitHub Workflow.

Meanwhile, secrets.DOCUMENTER_KEY can be generated as explained in Authentication: SSH Deploy Keys and be configured as a custom GitHub repository secret at: https://github.com/{user}/{repository}/settings/secrets/.

It is important to note that we should accordingly update TagBot Workflow:

  - uses: JuliaRegistries/[email protected]
    with:
      token: ${{ secrets.GITHUB_TOKEN }}
+     ssh: ${{ secrets.DOCUMENTER_KEY }}

Moreover, in case you're using an old version of Documenter.jl like me, you probably need to update the version in docs/Project.toml first of all because GitHub Actions are supported since Documenter.jl 0.24:

  Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"

  [compat]
- Documenter = "~0.20"
+ Documenter = "0.24"

That's all, and here is a complete set of GitHub Actions Workflows for my Julia project.

  Share


  Support

  Buy me a coffee

  See also

2019-07-26
Lightning Talk about Recommender Systems in Julia at #JuliaCon 2019
2019-03-31
Publishing My Master's Thesis with Documenter.jl
2017-06-26
Deploying Static Site to GitHub Pages via Travis CI

  More

  Author: Takuya Kitazawa

Takuya Kitazawa is a software engineer based in Vancouver. I have worked as a full-stack software engineer, OSS developer, data scientist, machine learning engineer, and product manager for 6+ years.

  Set up a 1:1 call with me

Opinions are my own and do not represent the views of organizations I am/was belonging to.

  Popular articles

2020-02-07
Why a Data Science Engineer Becomes a Product Manager
2018-10-26
Apache Hivemall at #ODSCEurope, #RecSys2018, and #MbedConnect
2017-02-25
Parallel Programming vs. Concurrent Programming