When building, deploying, or testing an renv-using project with continuous integration (CI) systems (e.g. GitHub Actions, GitLab CI, and others) you need some way to tell the CI system to use renv to restore the same packages that you’re using locally.
The general idea is:
Call renv::snapshot() on your local machine to
generate renv.lock.
Call renv::restore() on your CI service to restore
the project library from renv.lock.
Cache the project library and global renv cache on the CI service.
Note that this workflow is not generally a good fit for CRAN
packages, because CRAN itself runs R CMD check using the
latest version of all dependencies.
Here, we describe two common approaches for integrating renv with a GitHub Actions workflow:
r-lib/setup-renv action.The r-lib organization offers some actions for R users, and among
them a setup-renv
action is provided for projects using renv. To use this action, you can
add the following steps to your workflow:
steps:
- uses: actions/checkout@v5
- uses: r-lib/actions/setup-r@v2
- uses: r-lib/actions/setup-renv@v2Using these steps will automatically perform the following actions:
install.packages("renv"),with: profile: key, that renv profile
will be activated,renv::restore().After this, any steps using R will use the active renv project by default.
When using renv in your own custom GitHub action workflow, there are two main requirements:
renv::restore() to restore packages using this
cache to speed up installationAs an example, these steps might look like:
env:
RENV_PATHS_ROOT: ~/.cache/R/renv
steps:
- name: Cache packages
uses: actions/cache@v4
with:
path: ${{ env.RENV_PATHS_ROOT }}
key: ${{ runner.os }}-renv-${{ hashFiles('**/renv.lock') }}
restore-keys: |
${{ runner.os }}-renv-
- name: Restore packages
shell: Rscript {0}
run: |
if (!requireNamespace("renv", quietly = TRUE)) install.packages("renv")
renv::restore()See also the example on GitHub actions.
In some CI workflows, you may want to generate or update a lockfile without installing packages – for example, to validate that dependencies can be resolved, or to produce a lockfile artifact in a lightweight container that doesn’t have compilation tools.
renv::plan() resolves the packages required by a project
and writes a lockfile, without installing anything:
# resolve all project dependencies and write renv.lock
renv::plan()
# or, resolve a specific set of packages
renv::plan(c("dplyr", "ggplot2"))Because renv::plan() works from repository metadata
rather than installed packages, it can run in environments where package
installation would be impractical.
In multi-stage CI pipelines, it can be useful to download packages in
one step and install them in a later step. renv::retrieve()
downloads the packages required by a project (or a lockfile) without
installing them:
# download all packages required by the lockfile
renv::retrieve()
# download specific packages
renv::retrieve(c("dplyr", "ggplot2"))Downloaded packages are stored in renv’s local cache, so a subsequent
renv::restore() can install from the cache without
re-downloading.
The following template can be used as a base when using renv with GitLab CI: