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 (Thank you!)

  Gift a cup of coffee

Note that, as an Amazon Associate, I earn from qualifying purchases on amazon.ca.

  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

Last updated: 2022-08-06

  Author: Takuya Kitazawa

Takuya Kitazawa is a freelance software developer, minimalistic traveler, ultralight hiker & runner, and craft beer enthusiast. While my area of specialty is in data & AI ethics and machine learning productization, I have worked full-stack throughout the career e.g., as a frontend/backend engineer, OSS developer, technical evangelist, solution architect, data scientist, and product manager. You can find what I am doing lately at my "now" page, and your inquiry is always welcome at [email protected], including comments on my blog posts.

  Schedule a call with me

  Disclaimer

  • Opinions are my own and do not represent the views of organizations I am/was belonging to.
  • I am doing my best to ensure the accuracy and fair use of the information. However, there might be some errors or biased subjective statements because the main purpose of this blog is to jot down my personal thoughts as soon as possible before conducting an extensive investigation. Visitors understand the limitations and rely on any information at their own risk.
  • That said, if there is any issue with the content, please contact me so I can take the necessary action.