Skip to content

Instantly share code, notes, and snippets.

@jimhester
Created March 1, 2021 21:28
Show Gist options
  • Save jimhester/3452d4bd9f7ecaf46cfcd47e872e3e8e to your computer and use it in GitHub Desktop.
Save jimhester/3452d4bd9f7ecaf46cfcd47e872e3e8e to your computer and use it in GitHub Desktop.
Highly annotated R GitHub Actions workflow
# We want to run this on all pushes on the 'main' branch, whether it is called main or master.
on:
push:
branches:
- main
- master
# We also want to run it on pull requests targetting the 'main' branch
pull_request:
branches:
- main
- master
# This is the overall workflow name, which shows up in the log
name: R-CMD-check
jobs:
# This can be called anything, but I think it is generally better practice to keep it the same as the overall workflow name
R-CMD-check:
# This specifies the operating system that the job will run on, here we look this up based on the matrix config below
runs-on: ${{ matrix.config.os }}
# We name the individual job with the operating system and the version of R we are running against
name: ${{ matrix.config.os }} (${{ matrix.config.r }})
strategy:
# fail-fast: true is the default, but this means the whole workflow fails as soon as one job fails, which is often not what we want.
fail-fast: false
# Here we specify the build matrix, all the possibilities we want to consider
matrix:
# This name could be anything, config is just generic
config:
# We test macOS only on the release version, as it always has binaries there
- {os: macOS-latest, r: 'release'}
# We test windows only on release and 3.6, because 3.6 uses the 'old' RTools toolchain and R versions 4.0+ use the new one
- {os: windows-latest, r: 'release'}
- {os: windows-latest, r: '3.6'}
# We test R devel on linux using RStudio Package Manager. We need to set the user agent to R 4.0 so that RStudio Package Manager will serve the 4.0 binaries for R devel (currently 4.1).
# This will work as long as R-devel does not break API compatibility with the release version of R.
- {os: ubuntu-18.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/bionic/latest", http-user-agent: "R/4.0.0 (ubuntu-18.04) R (4.0.0 x86_64-pc-linux-gnu x86_64 linux-gnu) on GitHub Actions" }
# We set rspm here so we can have package binaries for all the linux builds. No there is not a way to inherit matrix values to avoid the repetition.
- {os: ubuntu-18.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/bionic/latest"}
- {os: ubuntu-18.04, r: 'oldrel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/bionic/latest"}
- {os: ubuntu-18.04, r: '3.5', rspm: "https://packagemanager.rstudio.com/cran/__linux__/bionic/latest"}
- {os: ubuntu-18.04, r: '3.4', rspm: "https://packagemanager.rstudio.com/cran/__linux__/bionic/latest"}
- {os: ubuntu-18.04, r: '3.3', rspm: "https://packagemanager.rstudio.com/cran/__linux__/bionic/latest"}
env:
# pak queries the RSPM environment when it retrieves the system requirements below
RSPM: ${{ matrix.config.rspm }}
# We set the GITHUB_PAT (which pak uses) to be the automatically available GITHUB_TOKEN, this increases the API limits when querying the GitHub API
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
steps:
# The checkout action checks out a repository. v2 is the latest tag
- uses: actions/checkout@v2
# This action installs and sets up R
- uses: r-lib/actions/setup-r@v1
# We need to set the id for this step because we use an output for it in the cache step below
id: install-r
with:
# We pass the r-version and user agents we want to install and setup here, based on the matrix above
r-version: ${{ matrix.config.r }}
# The user agent is set by putting an option in `~/.Rprofile` in the setup code
http-user-agent: ${{ matrix.config.http-user-agent }}
# We install pandoc with this step
- uses: r-lib/actions/setup-pandoc@v1
- name: Install pak and query dependencies
run: |
# We install the dev version of pak with this step. It contains all of its dependencies automatically
install.packages("pak", repos = "https://r-lib.github.io/p/pak/dev/")
# We need to query the package dependency versions and save them to a file, which we put in the `.github` folder, so it is automatically excluded from the built R package.
# We can then use this file as a key when caching, so if the dependencies have not changed we can just reuse the previously installed packages.
saveRDS(pak::pkg_deps("local::.", dependencies = TRUE), ".github/r-depends.rds")
shell: Rscript {0}
- name: Cache R packages
uses: actions/cache@v2
with:
# Where the files we are caching live, e.g. the R library
path: ${{ env.R_LIBS_USER }}
# The key is the OS we are running on, the actually installed R version (rather than 'release', which could change when new R versions are released),
# -1-, which is just a version we can bump if we need to invalidate the cache, and our dependency versions we stored in the previous step.
# hashFiles() computes a hash based on the contents of the file, in this case the serialized R dependency information
key: ${{ matrix.config.os }}-${{ steps.install-r.outputs.installed-r-version }}-1-${{ hashFiles('.github/r-depends.rds') }}
# The restore key specifies where you want to load the cache from if a cache is _not_ found, in this case we load the most recent cache that matches all of the key parts _except_ the last part.
restore-keys: ${{ matrix.config.os }}-${{ steps.install-r.outputs.installed-r-version }}-1-
- name: Install system dependencies
# Install system dependencies, we only do this automatically on linux, Windows and macOS usually don't need to explicitly install system dependencies.
if: runner.os == 'Linux'
run: |
# local_system_requirements() queries RSPM for the commands needed to install the system requirements for the package and its dependenices and execute = TRUE runs them automatically.
pak::local_system_requirements(execute = TRUE)
# We also need to install the system requirements for the rcmdcheck package
pak::pkg_system_requirements("rcmdcheck", execute = TRUE)
shell: Rscript {0}
- name: Install dependencies
run: |
# Actually install the package dependencies, upgrading them if there are older versions in the cache.
# If you have _newer_ versions of packages in the cache they won't be downgraded, so you would have to bump the cache version in this case.
pak::local_install_dev_deps(upgrade = TRUE)
# install the rcmdcheck package, this won't do anything if the package is already in the cache.
pak::pkg_install("rcmdcheck")
shell: Rscript {0}
- name: Session info
run: |
# We use a little bit larger width for this, as the default of 80 makes the output wrap badly
options(width = 100)
# Get all the packages we installed in the last step
pkgs <- installed.packages()[, "Package"]
# Print their versions
sessioninfo::session_info(pkgs, include_base = TRUE)
shell: Rscript {0}
- name: Check
env:
_R_CHECK_CRAN_INCOMING_: false
run: |
# We explicitly turn on colors for this, as the auto-detection doesn't detect the actions log as color enabled.
options(crayon.enabled = TRUE)
# We don't build a manual (as that requires the full LaTeX stack, and use --as-cran to turn on CRAN's normal checks)
# We want to throw a full R error (and fail the GitHub Actions build) if there is a warning or an error from R CMD check
# And we want to output the checks into the 'check' directory
rcmdcheck::rcmdcheck(args = c("--no-manual", "--as-cran"), error_on = "warning", check_dir = "check")
shell: Rscript {0}
- name: Show testthat output
# Originally this was only in if: failure(), but we changed it to always output, this line could potentially be removed.
if: always()
# Find any testthat.Rout or testthat.Rout.fail files and output them
# Sometimes this is useful to see to make sure the tests you think are running have actually run.
run: find check -name 'testthat.Rout*' -exec cat '{}' \; || true
shell: bash
# If there are any failures, upload the results in the 'check' directory as an artifact so they can be inspected.
- name: Upload check results
if: failure()
uses: actions/upload-artifact@main
with:
name: ${{ matrix.config.os }}-r${{ matrix.config.r }}-results
path: check
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment