Skip to content

Repository files navigation

Reusable GHA workflows

🚩🚩🚩 This repo is intended for internal use only. Sweeping changes will be made without notice. 🚩🚩🚩

A reusable workflow is a workflow that is defined in a single location but can be executed from another location as if it was locally defined. Link: https://docs.github.com/en/actions/learn-github-actions/reusing-workflows

Usage:

This workflow below should be copied into your repo at .github/workflows/R-CMD-check.yaml

# Workflow derived from https://github.com/rstudio/shiny-workflows
#
# NOTE: This Shiny team GHA workflow is overkill for most R packages.
# For most R packages it is better to use https://github.com/r-lib/actions
on:
  push:
    branches: [main, rc-**]
  pull_request:
  workflow_dispatch:

name: Package checks

jobs:
  website:
    uses: rstudio/shiny-workflows/.github/workflows/website.yaml@v1
  routine:
    uses: rstudio/shiny-workflows/.github/workflows/routine.yaml@v1
    with:
      format-r-code: true
  R-CMD-check:
    uses: rstudio/shiny-workflows/.github/workflows/R-CMD-check.yaml@v1

This file is also available as examples/pkg-r.yaml, so it can be installed directly:

usethis::use_github_action(
  url = file.path(
    "https://raw.githubusercontent.com/rstudio/shiny-workflows",
    "main/examples/pkg-r.yaml"
  )
)

To run any of the three workflows on its own triggers, adopt the matching file from examples/ instead and drop that job from Package checks.

Workflows

There are three main reusable workflows to be used by packages in the shiny-verse

  • website.yaml
    • This is a wrapper for building a {pkgdown} website and deploying it to the gh-pages branch of the repo.
    • Packages included in the DESCRIPTION field Config/Needs/website will also be installed
    • The site is deployed on push, workflow_dispatch, and repository_dispatch events. On other events (such as pull_request), the site is only built and verified.
    • To run the site as its own workflow, so that it can also be rebuilt on demand without running the rest of Package checks, copy examples/website.yaml into your repo and drop the website job from Package checks. See the examples README.
    • Parameters:
  • routine.yaml
    • Performs many common tasks for packages in the shiny-verse and commits them back to the repo
      • Check for url redirects in rc-v** branches
      • Formats R code with air
      • usethis::use_tidy_description()
      • devtools::document()
      • devtools::build_readme() (if README.Rmd exists)
      • Losslessly optimizes tracked PNG files with oxipng
      • Checks code coverage with covr if codecov.yml exists
      • Checks for broken lints if .lintr exists
      • Calls npm build / yarn build and commits any changes in inst, srcts, and srcjs.
      • Updates the bundled JavaScript dependency list in LICENSE.note and comments on the PR when it changes, if license-note: true. See the license-note README.
      • Calls npm test / yarn test
      • Checks for outdated staticimports
    • Packages included in the DESCRIPTION field Config/Needs/routine will also be installed
    • To run the tasks as their own workflow, so that they can be re-run on demand without the rest of Package checks, copy examples/routine.yaml into your repo and drop the routine job from Package checks. See the examples README.
    • Parameters:
      • extra-packages, cache-version, pandoc-version: Same as in website.yaml
      • node-version: Version of node.js to install. Defaults to "current".
      • staticimports: If true, checks for outdated staticimports. Defaults to true.
      • format-r-code: If true, will format R code with air. Defaults to false.
      • format-description: If true, will run usethis::use_tidy_description() to format the DESCRIPTION file. Defaults to true.
      • build-readme: If true, will build README.md from README.Rmd. Defaults to true.
      • check-js: If true, will check for a package.json file and run npm install / yarn install and npm build / yarn build if it exists. Defaults to true.
      • js-working-directory: Folder that contains the package.json file. Defaults to the working directory input.
      • optimize-pngs: Newline-separated git pathspecs of tracked PNG files to losslessly optimize with oxipng. Defaults to man/figures/*.png and vignettes/*.png. Note that * matches / in a pathspec, so nested folders are included. Files under a _snaps/ folder are never optimized, as testthat::compare_file_binary() compares snapshots byte for byte and optimizing one would keep it from matching a freshly generated screenshot. Set to false (or an empty string) to disable. See the optimize-pngs action for details.
      • license-note: If true, updates the bundled JavaScript dependency list in LICENSE.note. Defaults to false — set it to true and add the generated-block markers to LICENSE.note to opt in. See the license-note README.
      • working-directory: The working directory where all checks are executed. Defaults to "." (repository root).
  • R-CMD-check.yaml
    • Performs R CMD check . on your package
    • To run the check matrix as its own workflow, so that it can be re-run on demand without the rest of Package checks, copy examples/R-CMD-check.yaml into your repo and drop the R-CMD-check job from Package checks. See the examples README.
    • Parameters:
      • extra-packages, cache-version, pandoc-version: Same as in website.yaml
      • extra-check-args, extra-check-build-args: Arguments passed in addition to the default check args/build-args of https://github.com/r-lib/actions/blob/v2/check-r-package/
      • error-on: Condition that makes R CMD check fail, forwarded to rcmdcheck's error_on. Must be a quoted R string, e.g. '"note"'. Defaults to '"warning"'. Note that '"note"' can be flaky in CI even for a locally clean package, due to environment NOTEs such as checking CRAN incoming feasibility and checking for future file timestamps.
      • macOS: macOS runtime to use. Set to false to disable testing on macOS. Defaults to "macOS-latest".
      • windows: windows runtime to use. Set to false to disable testing on Windows. Defaults to "windows-latest".
      • ubuntu: ubuntu runtime to use. To use more than one ubuntu value, send in a value separated by a space. For example, to test on ubuntu 22.04 and 24.04, use "ubuntu-22.04 ubuntu-24.04". The first ubuntu value will be tested using the "devel" R version. Set to false to disable testing on Ubuntu. Defaults to "ubuntu-24.04".
      • minimum-r-version: If provided, only R versions >= to minimum-r-version will be created in the matrix. Great for dependencies that will not install on earlier R versions.
      • force-windows-src: If true, forces the check to assume the package has compiled code even if it doesn't. Defaults to false.
      • upload-snapshots: If true, uploads testthat snapshots as artifacts. Defaults to true.
      • upload-check-results: If true, uploads check results on failure. Defaults to false.
      • working-directory: The working directory where all checks are executed. Defaults to "." (repository root).
      • check-timeout-minutes: Timeout in minutes for the check step. Defaults to 30.
      • check-depends-only: If true, adds an extra job that checks the package with only dependencies installed (sets _R_CHECK_DEPENDS_ONLY_=true). Defaults to true.

Customization

There are a set of known files that can be run. The file just needs to exist to be run. No extra configuration necessary.

The files must exist in the .github/shiny-workflows/ folder. Such as .github/shiny-workflows/package-install.R.

Files:

  • package-install.R / package-install.sh
    • This step is run in all workflows after R is installed, but before the local package dependencies are installed.
    • This script could be useful for installing custom dependencies
  • website.R / website.sh
    • Run in website.yaml before the site is built
    • This script could be useful for copying assets to a directory
  • routine.R / routine.sh
    • Run in routine.yaml. Runs before the local commits are pushed back to GitHub
    • This script could be useful for running some logic on a single OS and push the results back to GitHub
    • This script could be useful for running a test that needs to be performed once and not on every job of R-CMD-check.yaml

These scripts should be done for their side effects, such as copying files or installing dependencies.

For example, a common use case for using a shell script over an R script would be to install custom system dependencies. Since installation is usually OperatingSystem specific, you'll likely want to make use of System environment variables, such as $RUNNER_OS. Link: https://docs.github.com/en/actions/learn-github-actions/environment-variables

Example usage of package-install.sh:

if [ "$RUNNER_OS" == "macOS" ]; then
  brew install harfbuzz fribidi
fi

pkgdown setup

Typically when using pkgdown in a package, you run the command below to initalize all necessary configs.

# Init pkgdown webs
usethis::use_pkgdown_github_pages()

However, we will need to remove the GHA workflow file created, as we will use the website.yaml reusable shiny-workflow.

# Remove pkgdown workflow file; (Using reusable shiny-workflow)
unlink(".github/workflows/pkgdown.yaml")

Where to find help

If your build fails and you are unsure of why, please visit https://github.com/r-lib/actions#where-to-find-help for more debugging tips. If you feel it is an error done by shiny-workflows, please submit an issue: https://github.com/rstudio/shiny-workflows/issues/new

Additional resources

Common questions

  1. Why are my builds failing on macOS?
    macOS packages are installed as binaries from Posit Public Package Manager, so system dependencies are rarely needed; setup-macOS-dependencies only installs XQuartz, and only for Cairo. If a package must be built from source, or its binary is linked against a library the runner image lacks, install it from your package-install.sh local script. Please also make an issue so that other repos may utilize this knowledge: https://github.com/rstudio/shiny-workflows/issues/new
  2. What if my website is custom?
    It is ok to comment the website job in your workflow file. When the time comes that you can use the standardised {pkgdown} workflow, feel free to uncomment the website job.

shiny-workflow development

Adopting a feature

Reasons to consider a feature:

  • If more than two repos needs custom work, it should be considered.
  • If all other repos could benefit from an installation step, even if they are currently not utilized. (Ex: phantomJS, tinytex)

Reasons to NOT consider a feature:

  • Trying to appease a single repo. General response: The repo can run more compute cycles / jobs to meet their needs
  • The feature imposes behavior that no other repos are performing or willing to adopt. Ex: Automatically setting the package version in package.json

Updates to workflows or actions

If updates are made to the workflows, the v1 tag must be (forcefully) moved forward to the latest commit on main within rstudio/shiny-workflows. Until the tag moves, consumers on @v1 do not see merged changes.

Moving the tag ships every unreleased commit on main to every consumer repo at once, so it is a deploy rather than a git chore. The procedure — pre-flight checks, the commit list to review, the force-push, and how to roll back — lives in .claude/skills/update-v1-tag/SKILL.md. Follow it there rather than running the commands from memory; if you are working with Claude Code, ask it to update the v1 tag and it will use that skill.

License CC0 licensed

All examples in this repository are published with the CC0 license.

About

GitHub Actions workflows for Shiny and related packages

Resources

Stars

22 stars

Watchers

7 watching

Forks

Releases

Packages

Used by

Contributors

Languages