Transiton from Travis CI to GitHub Actions
Overview
The recent introduction of GitHub Actions makes a lot of our Travis CI build configurations redundant.
In particular, the examples actions include:
R-CMD-check
usingrcmdcheck::rcmdcheck()
to check the package.test-coverage
usingcovr::codecov()
to publish the unit test coverage of the package to https://codecov.io/.pkgdown
usingpkgdown::deploy_to_branch()
to push thepkgdown
website to thegh-pages
branch of the repository.
However, Bioconductor packages need a bit of extra tweaking to run those workflows, as we will see below.
In addition, it is useful to combine those individual example actions into a single workflow, as some of those actions only make sense to run when other have successfully completed.
Use case
Let’s pick up one of my Bioconductor-to-be packages that needs updating, namely https://github.com/kevinrue/deeperTools.
Issue
Recent updates of the GitHub and Travis integration have caused the latest Travis run to fail deploying the pkgdown
website to the gh-pages
branch of the repository.
── Deploying to GitHub Pages ───────────────────────────────────────────────────
Running git remote -v
origin https://github.com/kevinrue/deeperTools.git (fetch)
origin https://github.com/kevinrue/deeperTools.git (push)
Running git push --force origin 'HEAD:gh-pages'
remote: Invalid username or password.
fatal: Authentication failed for 'https://github.com/kevinrue/deeperTools.git/'
Error: System command 'git' failed, exit status: 128, stdout & stderr were printed
Stack trace:
1. pkgdown::deploy_site_github()
2. pkgdown:::deploy_to_branch(pkg, commit_message = commit_message, ...
3. pkgdown:::github_push(dest_dir, commit_message, remote, branch)
4. pkgdown:::with_dir(dir, { ...
5. base:::force(code)
6. pkgdown:::git("push", "--force", remote, paste0("HEAD:", branch))
7. processx::run("git", c(...), echo_cmd = echo_cmd, echo = echo, ...
8. throw(new_process_error(res, call = sys.call(), echo = echo, ...
x System command 'git' failed, exit status: 128, stdout & stderr were printed
── Removing worktree ───────────────────────────────────────────────────────────
Running git worktree remove /tmp/Rtmpzu14jy/file3f67f42389b
Execution halted
Script failed with status 1
failed to deploy
As Hadley Wickham wrote, it is now recommended to move away from Travis CI and use GitHub Action instead.
We now recommend using the github actions workflow instead; which avoids all this configuration pain.
Initialise the GitHub action
Having open the RStudio project located at the root of my repository, I use the usethis
package to fetch and set up the R-CMD-check
example workflow.
usethis::use_github_action_check_full()
Edit the R-CMD-check
GitHub action as necessary
I proceed to edit some steps of the workflow for my package. Some of those edits are necessary, others are for my own convenience. The following command opens the file in the RStudio editor.
file.edit("github/workflows/R-CMD-check.yaml")
First, I remove the restriction on branches
for the push
event.
This will trigger the action on every push to any branch.
on:
push:
pull_request:
branches:
- master
Then, I keep only the latest ubuntu
version, mainly to reduce the number of configurations run as separate jobs.
strategy:
fail-fast: false
matrix:
config:
- {os: windows-latest, r: '3.6'}
- {os: macOS-latest, r: '3.6'}
- {os: macOS-latest, r: 'devel'}
- {os: ubuntu-16.04, r: '3.6', rspm: "https://demo.rstudiopm.com/all/__linux__/xenial/latest"}
When working with a Bioconductor package, BiocManager
should be installed during the Query dependencies
step.
This allows BiocManager::repositories()
to be called to add Bioconductor package repositories to be added to the global session options.
In turn, this allows remotes::dev_package_deps()
to query all repositories when identifying dependencies, as it uses the default argument value repos = getOption("repos")
.
- name: Query dependencies
run: |
install.packages(c('remotes', 'BiocManager'))
options(repos = c(getOption("repos"), BiocManager::repositories()))
saveRDS(remotes::dev_package_deps(dependencies = TRUE), "depends.Rds", version = 2)
shell: Rscript {0}
Again, when working with a Bioconductor package, we add Bioconductor package repositories to the global session options during the Install dependencies
step.
Similarly, the remotes::install_deps(dependencies = TRUE)
uses the default argument value repos = getOption("repos")
.
In this step, you may also add any dependency that is not explicitly declared in the DESCRIPTION
file of your package, or installed as an indirect dependency, as well as any esoteric development version of your dependencies.
- name: Install dependencies
run: |
options(repos = c(getOption("repos"), BiocManager::repositories()))
remotes::install_deps(dependencies = TRUE)
remotes::install_cran("rcmdcheck")
shell: Rscript {0}
You may wish to set error_on = "error"
during R CMD check
.
Otherwise, deprecation warnings would cause the step (and as a consequence the entire workflow) to fail.
- name: Check
run: rcmdcheck::rcmdcheck(args = "--no-manual", error_on = "error", check_dir = "check")
shell: Rscript {0}
Remove redundant actions from the Travis CI build
The Test coverage
step of the R-CMD-check
GitHub action deploys the website.
Remove the following sections from the Travis build configuration.
after_success:
- Rscript -e 'library(covr); codecov()'
The Deploy
step of the R-CMD-check
GitHub action deploys the website.
Remove the following sections from the Travis build configuration.
before_cache: Rscript -e 'remotes::install_cran("pkgdown")'
deploy:
provider: script
script: Rscript -e 'pkgdown::deploy_site_github()'
skip_cleanup: true
Credits
Thanks to Charlotte Soneson for discussion and advice!