In this part of the workshop, we will implement a few GitHub Actions Continuous Integration workflows for our R package we made in the previous session 📦!

We will be using template workflows developed by the amazing team of contributors that run the r-lib/actions repo. Massive shout out to these folks for making our lives easier! 👏👏👏

Helpful resources 🧑‍🏫

To get a general sense of what GitHub Actions Workflows are for R users, I recommend:

If you want to know all the nitty-gritty details and eventually write your own custom GHA workflows, I recommend 🔍:

Let’s get started! 🚀

If you haven’t already, lets load {devtools}! We might need a few other packages below, but we will load/install these as we go!

#install.packages("devtools")

library(devtools) #Will load usesthis and roxgen2 as well

Git set go!!! 🏁

Before we jump in, we have to make sure:

  1. [git] the version control software is installed
  2. your GitHub Personal Access Token (PAT) are set up correctly! Your PAT is our key to GitHub’s API 🔑

Want to learn more about PAT? Highly recommend this section of the Happy Git and GitHub for the useR!

First, we can check if we have git and PAT installed/set up correctly. You may have done so in previous projects! Your past self has your back! 🙏

git_sitrep() # git situation report

If git and PAT has already been set up, we would see this under the bold heading GitHub:

If you don’t see this ⚠️ Follow the next steps to git sorted 😉

Install git 👾

git installation is via the shell terminal and is OS dependent, so take a look at this chapter of Happy git with R to get started!

💻 For a macOS user: git is usually installed along with ‘Command Line Developer Tools’ via Xcode when you first open RStudio

Create a PAT token! 🎟

I recommend having a good read of ?usethis::gh_token_help() and follow the instructions there

If you want more details, try the tl;dr section of the Happy Git and GitHub for the useR book and the subsequent chapters, these will get you on your feet in no time!

?usethis::gh_token_help()

This function will open up a browser for you to select the scopes you want to your PAT to do. The recommended scopes are already pre-selected for ya!

usethis::create_github_token() 

If usethis::create_github_token() fails, try this link to create a PAT manually on the GitHub Website

Saving PAT on your system 💾

Once you a PAT has been created for you, copy and save this in your password manager! For security reasons, you won’t get to see the PAT again if you close the browser! Now we will register your PAT using:

#install.packages("gitcreds")
gitcreds::gitcreds_set()

Once this is complete, just for peace of mind… check your git settings are OK!

git_sitrep() # git situation report

Our first GitHub Action! 💥

{usethis} will be your portal to the most commonly use R GHA templates! You can access any of the templates from the r-lib/actions repository.

Remember devtools::check() from our previous sessions? Well, for our first workflow, we are going to set up a GHA to run R-CMD-CHECK on our R package in one operating system (by default its Ubuntu), on the latest version of R.

Go ahead and run:

use_github_action_check_release()

Notice, how this function does a few things on your behalf:

  1. First it creates a hidden directory: .github/
  2. Adds .github/ directory to you .gitignore
  3. Creates a directory: .github/workflow
  4. Downloads version 2 of the R CMD CHECK template from r-lib/actions/examples/check-release.yaml
  5. The function also prompts us to add the badge to README.Rmd! Who doesn’t like badges!? Remember to knit to regenerate the README.md!

Lets take a look at the R-CMD-check.yml:

  • Explain the structure
  • Explain where each steps come from
  • Where does the v2 come from?

Now commit these changes and push and see the magic work! 🧙‍♀️

Different OS and R versions 📚

What if we want to make sure your package can pass R-CMD-CHECK on Windows, macOS and Linux? Farewell virtual machines! You can do this all in one GHA workflow, although it will take longer compared to a single OS workflow! ⏰

Go ahead and run:

use_github_action_check_standard()

Note that this will overwrite the pre-existing R-CMD-check.yaml. Allow this to happen, these workflow files can be regenerated by calling the respective use_github_action_XX function ♻️

Lets then take a look at the .yml: 👀

  • Syntax of matrix

You can check out all the OS options here that are currently available on GHA servers

Other versions of R and dependencies

  • 'release' is the current release e.g. 4.2.1
  • 'oldrel-1' is the release prior to current e.g 4.2.0

You can request other R versions but change 'release' to your desired version number like this:

jobs:
 R-CMD-check:
    runs-on: ${{ matrix.config.os }}

    name: ${{ matrix.config.os }} (${{ matrix.config.r }})

    strategy:
      fail-fast: false
      matrix:
        config:
          - {os: macOS-latest,   r: '3.6'}

You can use RStudio Package Manager to load specific versions of dependencies that were around at an earlier version of R. I have never done this before, but this example looks promising! I would be happy to investigate this with you 💪

Which workflows for you? 🤔

There are many GHA workflows you can apply to a standard R package. Here is a handy list of example templates from the r-lib/actions repository.

I tend to only use:

  • R-CMD-CHECK (use_github_action_check_standard())
  • test-coverage
  • pkgdown (Covered in next session)

The choice is up to you and the needs of your package. For example, lint one looks promising if there are multiple contributors to the package and everyone’s coding style is slightly different!

💡 TIP: If you are using RStudio IDE, you can use start writing use_github_action_ in your R console to see what type of GHA templates are already built in {usethis}

Covering your bases 🪤 with codecov

Let’s set up test-coverage together. This workflow uses codecov.io to compute how well spread your unit tests are across your package functions. Generally speaking, a high code coverage indicates your package is robust to bugs, a value of ~70-80% is thought to be a good threshold!

We compute code coverage through the R package {covr}, you may need to install this one!

#install.packages("covr")

library(covr) 

First we need to link our R package with codecov using:

use_coverage(type ="codecov")

This function will:

  • Add {covr} the R package to our DESCRIPTION file
  • Add a codecov.yml file to your R package
  • Add this file to your .Rbuildignore
  • Adds a codecov badge to your README.Rmd which may need further configuration! (More of this below)

Now let’s add the test-coverage GHA workflow to our package! This will add the .yml to our .github/workflows directory.

usethis::use_github_action("test-coverage")

Commit these recent changes and push to trigger codecov and your new workflow! 🚀

Configuring your codecov badge 🛡

Navigate to your README.Rmd and knit to see if your badge set up has worked! Note that by default codecov will point to your master branch of your package repo. Don’t worry if it is showing ‘unknown’ as it did for me. It just means there is a few extra steps to properly set this up! 😁

  1. Click on your badge this will take you to our codecov dashboard where you can see your code coverage
  2. Navigate to Settings tab
  3. Click on Badges & Graphs
  4. Copy the contents below Markdown and paste this in README.Rmd, replacing the previous one

Re-knit and see if it works?! 🤞

Notice how the URL path to this badge includes a token=XXX. For some reason, including this in the badge worked for me, despite documentation saying that public repos don’t need this step 🤷‍♀️. I’ve lodged an issue here, if you are interested!

I tested this section on another mac M1 machine that has never used git/GitHub/codecov before. Once I granted third-party authorisation and clicked through a checklist on codecov, the default badge from usethis::use_github_action("test-coverage") worked 🤷‍♀️🤷‍♀️

I also tested this section on Windows machine that has never used codecov before. Things were a little tricky here. The badge was still not loading even after granting third-party authorisation and clicked through a checklist on codecov. In the end, I had to add the codecov token from Settings and paste it in the codecov.yml file.