Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save a warmed R package cache for faster installs in failing Actions #695

Merged
merged 16 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion setup-r-dependencies/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This action install dependencies for the current R environment based on the DESC
Inputs available

- `cache` - default `true`. Whether packages should be cached across runs or
gaborcsardi marked this conversation as resolved.
Show resolved Hide resolved
not.
not. If `"always"` is provided, the package cache will be saved even if the Action fails.
- `cache-version` - default `1`. If you need to invalidate the existing
cache pass any other number and a new cache will be used. Ignored if
`cache: false`. Note that you can also [delete caches
Expand Down Expand Up @@ -47,6 +47,7 @@ Inputs available
you need quoting. Defaults to `FALSE`.
- `working-directory` - default `'.'`. If the DESCRIPTION file is not in the
root directory of your repository.
- `prune` - default `true`. Used when `cache="always"`. Whether to prune the R packages not found within the lock file used during installation.
gaborcsardi marked this conversation as resolved.
Show resolved Hide resolved

Basic:
```yaml
Expand Down
54 changes: 48 additions & 6 deletions setup-r-dependencies/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: 'Action to setup installation tools and install R dependencies'
author: 'Jim Hester'
inputs:
cache:
description: 'A boolean value indicating whether packages should be cached from one to the other'
description: 'Whether packages should be cached across runs or not. If `"always"` is provided, the package cache will be saved even if the Action fails.'
required: true
default: true
cache-version:
Expand All @@ -29,6 +29,9 @@ inputs:
upgrade:
description: 'Whether to install the latest available versions of the dependencies. Must be an R expression. See the README for details if you need quoting.'
default: 'FALSE'
prune:
description: 'Whether to prune the R packages not found within the lock file used during installation.'
default: true
install-pandoc:
description: 'Whether to install pandoc. By default it is installed if it is not on the PATH and the local package suggests or depends on the rmarkdown package.'
pandoc-version:
Expand Down Expand Up @@ -116,24 +119,63 @@ runs:
shell: Rscript {0}
working-directory: ${{ inputs.working-directory }}

- name: Restore R package cache
if: inputs.cache == 'true'
- name: R package cache
if: inputs.cache != 'false'
uses: actions/cache@v4
with:
path: |
${{ env.R_LIBS_USER }}/*
!${{ env.R_LIBS_USER }}/pak
key: ${{ format('{0}-{1}-{2}-{3}', steps.install.outputs.os-version, steps.install.outputs.r-version, inputs.cache-version, hashFiles(format('{0}/.github/pkg.lock', inputs.working-directory ))) }}
restore-keys: ${{ steps.install.outputs.os-version }}-${{ steps.install.outputs.r-version }}-${{inputs.cache-version }}-
restore-keys: ${{ format('{0}-{1}-{2}-', steps.install.outputs.os-version, steps.install.outputs.r-version, inputs.cache-version) }}
# Used to save package installation on troublesome Actions
save-always: ${{ inputs.cache == 'always' }}
gaborcsardi marked this conversation as resolved.
Show resolved Hide resolved

- name: Install dependencies
id: install-pkgs
run: |
# Install/Update packages
cat("::group::Install/update packages\n")
Sys.setenv("PKGCACHE_HTTP_VERSION" = "2")
library(pak, lib.loc = Sys.getenv("R_LIB_FOR_PAK"))
pak::lockfile_install(".github/pkg.lock")
## Clean up lock file
pkgs <- pak::lockfile_install(".github/pkg.lock")
# Store the installed packages
packages <- paste0(pkgs$package, collapse = "|")
cat("packages=", packages, "\n", file = Sys.getenv("GITHUB_OUTPUT"), sep = "", append = TRUE)
cat("::endgroup::\n")
shell: Rscript {0}
working-directory: ${{ inputs.working-directory }}

- name: Prune unused R packages
if: inputs.cache == 'always' && inputs.prune == 'true'
gaborcsardi marked this conversation as resolved.
Show resolved Hide resolved
run: |
# Prune packages
cat("::group::Prune unnecessary packages\n")
installed_df <- as.data.frame(installed.packages(), stringsAsFactors = FALSE)
installed_packages <- installed_df$Package
core_pkgs <- c(
"translations", # Core package on windows
installed_packages[!is.na(installed_df$Priority)]
)
pak_pkgs <- c(
"pak", # Never remove pak
strsplit("${{ steps.install-pkgs.outputs.packages }}", "|", fixed = TRUE)[[1]]
)
to_remove_pkgs <- setdiff(installed_packages, c(core_pkgs, pak_pkgs))
if (length(to_remove_pkgs) > 0) {
cat("Removing unnecessary packages: ", paste0(to_remove_pkgs, collapse = ", "), "\n")
remove.packages(to_remove_pkgs)
} else {
cat("No unnecessary packages to remove\n")
}
cat("::endgroup::\n")
shell: Rscript {0}
working-directory: ${{ inputs.working-directory }}

- name: Clean up lock file
run: |
# Clean up lock file
cat("::group::Clean up lock file\n")
unlink(".github/pkg.lock")
cat("::endgroup::\n")
shell: Rscript {0}
Expand Down
Loading