How this skill is triggered — by the user, by Claude, or both
Slash command
/r-package-development:github-actionsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
---
This skill covers setting up comprehensive GitHub Actions workflows for R package development, including cross-platform testing, continuous integration, automated documentation deployment, and test coverage reporting.
Every R package should have these three workflows:
Create .github/workflows/R-CMD-check.yaml:
# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
name: R-CMD-check
permissions: read-all
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: 'release'}
- {os: windows-latest, r: 'release'}
- {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'}
- {os: ubuntu-latest, r: 'release'}
- {os: ubuntu-latest, r: 'oldrel-1'}
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
R_KEEP_PKG_SOURCE: yes
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Pandoc
uses: r-lib/actions/setup-pandoc@v2
- name: Setup R
uses: r-lib/actions/setup-r@v2
with:
r-version: ${{ matrix.config.r }}
http-user-agent: ${{ matrix.config.http-user-agent }}
use-public-rspm: true
- name: Install system dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update -y
sudo apt-get install -y libcurl4-openssl-dev
- name: Install dependencies
uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages: any::rcmdcheck
needs: check
- name: Check package
uses: r-lib/actions/check-r-package@v2
with:
upload-snapshots: true
build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")'
For simpler packages, you can use fewer test configurations:
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
name: R-CMD-check
permissions: read-all
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: 'release'}
- {os: windows-latest, r: 'release'}
- {os: ubuntu-latest, r: 'release'}
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
R_KEEP_PKG_SOURCE: yes
steps:
- uses: actions/checkout@v4
- uses: r-lib/actions/setup-pandoc@v2
- uses: r-lib/actions/setup-r@v2
with:
r-version: ${{ matrix.config.r }}
use-public-rspm: true
- uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages: any::rcmdcheck
needs: check
- uses: r-lib/actions/check-r-package@v2
For packages with system dependencies (e.g., gdal, jags, gsl):
- name: Install system dependencies on macOS
if: runner.os == 'macOS'
run: |
brew install gdal proj geos
- name: Install system dependencies on Linux
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y \
libgdal-dev \
libproj-dev \
libgeos-dev \
libudunits2-dev
- name: Install system dependencies on Windows
if: runner.os == 'Windows'
run: |
# Usually handled by rtools or binary packages
- uses: r-lib/actions/check-r-package@v2
with:
upload-snapshots: true
build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")'
error-on: '"error"' # Can be "warning", "note", or "error"
build_args options:
--no-manual: Skip PDF manual creation (faster, requires less LaTeX)--compact-vignettes=gs+qpdf: Compress vignettes with Ghostscript and qpdf--no-build-vignettes: Skip vignette building entirely--resave-data: Optimize data file compressionCreate .github/workflows/pkgdown.yaml:
# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
release:
types: [published]
workflow_dispatch:
name: pkgdown
# Limit concurrency: cancel in-progress runs when new ones are triggered
concurrency:
group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }}
permissions:
contents: write
jobs:
pkgdown:
runs-on: ubuntu-latest
# Only restrict concurrency for non-PR jobs
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Pandoc
uses: r-lib/actions/setup-pandoc@v2
- name: Setup R
uses: r-lib/actions/setup-r@v2
with:
use-public-rspm: true
- name: Install dependencies
uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages: any::pkgdown, local::.
needs: website
- name: Build site
run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE)
shell: Rscript {0}
- name: Deploy to GitHub Pages
if: github.event_name != 'pull_request'
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: docs
branch: gh-pages
clean: true
single-commit: false
- name: Build and deploy
if: github.event_name != 'pull_request'
run: |
git config --local user.name "$GITHUB_ACTOR"
git config --local user.email "[email protected]"
Rscript -e 'pkgdown::deploy_to_branch(new_process = FALSE)'
- name: Build site for preview
if: github.event_name == 'pull_request'
run: |
pkgdown::build_site(preview = FALSE, install = FALSE)
shell: Rscript {0}
- name: Upload preview
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v3
with:
name: pkgdown-preview
path: docs/
Create .github/workflows/test-coverage.yaml:
# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
name: test-coverage
permissions: read-all
jobs:
test-coverage:
runs-on: ubuntu-latest
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup R
uses: r-lib/actions/setup-r@v2
with:
use-public-rspm: true
- name: Install dependencies
uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages: any::covr, any::xml2
needs: coverage
- name: Test coverage
run: |
cov <- covr::package_coverage(
quiet = FALSE,
clean = FALSE,
install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package")
)
covr::to_cobertura(cov)
shell: Rscript {0}
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: true
files: ./cobertura.xml
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
- name: Show testthat output
if: always()
run: |
## --------------------------------------------------------------------
find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true
shell: bash
CODECOV_TOKEN to GitHub secrets (Settings > Secrets and variables > Actions)[](https://codecov.io/gh/username/packagename)
- name: Upload coverage to Coveralls
uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: ./coverage.lcov
Respond to comments like /document or /style:
Create .github/workflows/pr-commands.yaml:
on:
issue_comment:
types: [created]
name: Commands
jobs:
document:
if: startsWith(github.event.comment.body, '/document')
runs-on: ubuntu-latest
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
- uses: r-lib/actions/pr-fetch@v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- uses: r-lib/actions/setup-r@v2
- uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages: any::roxygen2
- name: Document
run: roxygen2::roxygenise()
shell: Rscript {0}
- name: Commit
run: |
git config --local user.name "$GITHUB_ACTOR"
git config --local user.email "[email protected]"
git add man/\* NAMESPACE
git commit -m 'Document' || echo "No changes to commit"
- uses: r-lib/actions/pr-push@v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
style:
if: startsWith(github.event.comment.body, '/style')
runs-on: ubuntu-latest
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
- uses: r-lib/actions/pr-fetch@v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- uses: r-lib/actions/setup-r@v2
- name: Install styler
run: install.packages("styler")
shell: Rscript {0}
- name: Style
run: styler::style_pkg()
shell: Rscript {0}
- name: Commit
run: |
git config --local user.name "$GITHUB_ACTOR"
git config --local user.email "[email protected]"
git add \*.R
git commit -m 'Style' || echo "No changes to commit"
- uses: r-lib/actions/pr-push@v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
Create .github/workflows/lint.yaml:
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
name: lint
permissions: read-all
jobs:
lint:
runs-on: ubuntu-latest
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
- uses: r-lib/actions/setup-r@v2
with:
use-public-rspm: true
- uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages: any::lintr, local::.
needs: lint
- name: Lint
run: lintr::lint_package()
shell: Rscript {0}
env:
LINTR_ERROR_ON_LINT: true
# Add R-CMD-check workflow
usethis::use_github_action("check-standard")
# Add pkgdown workflow
usethis::use_github_action("pkgdown")
# Add test-coverage workflow
usethis::use_github_action("test-coverage")
# Add lint workflow
usethis::use_github_action("lint")
# List available workflows
usethis::use_github_actions()
# Browse workflow files
usethis::use_github_action()
Place workflows in .github/workflows/ directory:
.github/
workflows/
R-CMD-check.yaml
pkgdown.yaml
test-coverage.yaml
lint.yaml
Problem: Workflow can't push to gh-pages or create releases
Solution: Add permissions block:
permissions:
contents: write # For pushing to gh-pages
# Or for fine-grained control:
# contents: read
# pages: write
# id-token: write
Problem: Rate limited or can't access private repos
Solution: Set environment variable:
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
For private dependencies, create a Personal Access Token:
repo scopeGH_PATGITHUB_PAT: ${{ secrets.GH_PAT }}Problem: vignettes fail on Ubuntu devel
Solution: Skip vignettes on devel:
- uses: r-lib/actions/check-r-package@v2
with:
build_args: 'c("--no-manual", if (Sys.getenv("R_VERSION") != "devel") "--compact-vignettes=gs+qpdf")'
Or add system dependencies:
- name: Install system dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y \
texlive-latex-base \
texlive-fonts-recommended \
texlive-fonts-extra \
texlive-latex-extra
Problem: macOS builds fail with missing system libraries
Solution: Use Homebrew:
- name: Install system dependencies
if: runner.os == 'macOS'
run: |
brew install pkg-config
brew install openssl
brew install libgit2
Problem: Multiple pushes create conflicting deployments
Solution: Use concurrency groups:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
For pkgdown specifically:
concurrency:
group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }}
Problem: Old package versions used despite new releases
Solution: Dependencies are cached by setup-r-dependencies. To force refresh:
- uses: r-lib/actions/setup-r-dependencies@v2
with:
cache-version: 2 # Increment this to bust cache
Problem: PDF manual fails on Windows
Solution: Skip manual on Windows:
- uses: r-lib/actions/check-r-package@v2
with:
build_args: 'c(if (.Platform$OS.type != "windows") "--no-manual", "--compact-vignettes=gs+qpdf")'
Or install TinyTeX:
- name: Install TinyTeX
if: runner.os == 'Windows'
run: |
install.packages("tinytex")
tinytex::install_tinytex()
shell: Rscript {0}
Problem: Snapshot tests fail but snapshots aren't committed
Solution: Use upload-snapshots: true:
- uses: r-lib/actions/check-r-package@v2
with:
upload-snapshots: true
Then download artifacts and commit manually, or use pr-commands workflow.
Problem: Push to main but workflow doesn't run
Solution: Check:
main vs master).github/workflows/.yaml or .yml extensionProblem: README badge doesn't show status
Solution: Ensure badge URL matches workflow name:
<!-- Workflow name: R-CMD-check -->
[](https://github.com/username/repo/actions/workflows/R-CMD-check.yaml)
Get badge from GitHub: Repository > Actions > Select workflow > ... > Create status badge
[](https://github.com/username/packagename/actions/workflows/R-CMD-check.yaml)
[](https://codecov.io/gh/username/packagename)
[](https://lifecycle.r-lib.org/articles/stages.html#experimental)
[](https://CRAN.R-project.org/package=packagename)
strategy:
fail-fast: false # Don't cancel all if one fails
matrix:
config:
- {os: macos-latest, r: 'release'}
- {os: windows-latest, r: 'release'}
- {os: ubuntu-latest, r: 'devel'}
- {os: ubuntu-latest, r: 'release'}
- {os: ubuntu-latest, r: 'oldrel-1'}
exclude: # Skip specific combinations
- os: windows-latest
r: 'devel'
- name: Install LaTeX
if: runner.os == 'Linux' && matrix.config.r == 'release'
run: sudo apt-get install texlive
- name: Build PDF manual
if: matrix.config.r != 'devel'
run: R CMD Rd2pdf .
env:
# Global (all jobs)
GLOBAL_VAR: value
jobs:
check:
env:
# Job-level
JOB_VAR: value
steps:
- name: Step with env
env:
# Step-level
STEP_VAR: value
run: echo $STEP_VAR
Run checks daily to catch upstream breakage:
on:
schedule:
- cron: '0 8 * * *' # 8 AM UTC daily
workflow_dispatch: # Allow manual trigger
This comprehensive setup ensures robust CI/CD for your R package.
npx claudepluginhub choxos/rpkgagent --plugin r-package-developmentConfigures GitHub Actions CI/CD for R packages: multi-platform R CMD check, test coverage, and pkgdown site deployment using r-lib/actions.
Creates, audits, and optimizes GitHub Actions workflows for CI/CD, matrix builds, reusable workflows, composite actions, caching, and security hardening like pinning and permissions.
Checks and configures GitHub Actions CI/CD workflows for container builds, tests, and releases. Updates action versions, adds caching, multi-platform builds, and audits missing workflows.