Skip to content

Commit 0da1e78

Browse files
committed
ask users to install suggested packages
1 parent 6c454ba commit 0da1e78

2 files changed

Lines changed: 80 additions & 27 deletions

File tree

.github/workflows/pkgcheck.yaml

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,22 @@ jobs:
2222
R_KEEP_PKG_SOURCE: yes
2323
xc_api_key: ${{ secrets.XENO_CANTO_API_KEY }}
2424
steps:
25-
- uses: actions/checkout@v4
26-
27-
# pkgcheck-action runs as a Docker container action, whose $HOME
28-
# (typically /github/home) does not necessarily match the runner
29-
# host's $HOME -- so a `git config --global --add safe.directory`
30-
# step here is not guaranteed to be visible inside that container.
31-
# Worse, libgit2 (which the R packages pkgcheck relies on for git
32-
# operations use under the hood) does NOT support the
33-
# GIT_CONFIG_COUNT/GIT_CONFIG_KEY_n/GIT_CONFIG_VALUE_n environment
34-
# variable mechanism at all -- that is a git-CLI-only feature
35-
# (added in git 2.31); libgit2 only reads actual config files.
25+
# pkgcheck-action is a composite action that runs its own internal
26+
# actions/checkout@v4 step, sharing this job's normal runner $HOME
27+
# (it is NOT a Docker container action, so no container/$HOME
28+
# mismatch is involved here). actions/checkout@v4's own
29+
# safe.directory handling is scoped only to itself (it temporarily
30+
# overrides $HOME while making that config change), so it does not
31+
# persist for later steps -- specifically the R-level git operations
32+
# pkgcheck performs afterwards via git2r/gert (which wrap libgit2),
33+
# which then hit the "dubious ownership" check (CVE-2022-24765)
34+
# under the job's real, persistent $HOME.
3635
#
37-
# The container-agnostic fix is to change the checked-out repo's
38-
# ownership to match what the container will run as (root, for
39-
# most Docker container actions), sidestepping the "dubious
40-
# ownership" check (CVE-2022-24765) entirely rather than trying to
41-
# whitelist around it via config.
42-
- name: Fix repo ownership for Docker container action
43-
run: sudo chown -R root:root "$GITHUB_WORKSPACE"
36+
# NOTE: do NOT `chown` the checkout to root here -- the job itself
37+
# runs as the normal non-root runner user, so doing that makes the
38+
# checkout unwritable to the job itself (this was tried and caused
39+
# EACCES permission errors instead).
40+
- name: Mark workspace as a safe git directory
41+
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
4442

4543
- uses: ropensci-review-tools/pkgcheck-action@main

R/access_wikiaves.R

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,12 @@
7979
#' are listed under Suggests rather than Imports since this workflow is
8080
#' only needed for the WikiAves data source and depends on a local Chrome-
8181
#' or Chromium-based browser installation and a usable display (e.g. the
82-
#' `DISPLAY` environment variable on Linux).
82+
#' `DISPLAY` environment variable on Linux). If either package is missing,
83+
#' in an interactive session the function asks for permission before
84+
#' installing them via `install.packages()`; declining stops the function
85+
#' with instructions to install manually. In a non-interactive session
86+
#' (e.g. within `R CMD check`, CI, or `Rscript`), the function cannot
87+
#' prompt and instead stops immediately with the same instructions.
8388
#'
8489
#' **Browser auto-detection.** When `chrome_bin = NULL` (the default), the
8590
#' function first checks whether the **chromote** package happens to be
@@ -202,15 +207,65 @@ access_wikiaves <- function(
202207
return(invisible(NULL))
203208
}
204209

205-
if (
206-
!requireNamespace("websocket", quietly = TRUE) ||
207-
!requireNamespace("later", quietly = TRUE)
208-
) {
209-
stop(
210-
"Packages 'websocket' and 'later' are required for this function. ",
211-
"Install them with: install.packages(c('websocket', 'later'))",
212-
call. = FALSE
210+
## check for required optional packages, offering to install them
211+
## interactively rather than just stopping
212+
required_pkgs <- c("websocket", "later")
213+
missing_pkgs <- required_pkgs[
214+
!vapply(required_pkgs, requireNamespace, logical(1), quietly = TRUE)
215+
]
216+
217+
if (length(missing_pkgs) > 0) {
218+
install_cmd <- paste0(
219+
"install.packages(c(",
220+
paste(sprintf('"%s"', missing_pkgs), collapse = ", "),
221+
"))"
213222
)
223+
224+
if (interactive()) {
225+
ans <- utils::menu(
226+
choices = c("Yes", "No"),
227+
title = paste0(
228+
"The following package(s) are required but not installed: ",
229+
paste(missing_pkgs, collapse = ", "),
230+
".\nInstall them now?"
231+
)
232+
)
233+
234+
if (ans == 1) {
235+
utils::install.packages(missing_pkgs)
236+
237+
# re-check in case installation failed silently for any of them
238+
still_missing <- missing_pkgs[
239+
!vapply(missing_pkgs, requireNamespace, logical(1), quietly = TRUE)
240+
]
241+
242+
if (length(still_missing) > 0) {
243+
stop(
244+
"Failed to install: ",
245+
paste(still_missing, collapse = ", "),
246+
". Please install manually with:\n ",
247+
install_cmd,
248+
call. = FALSE
249+
)
250+
}
251+
} else {
252+
stop(
253+
"Cannot proceed without required package(s). Install them with:\n ",
254+
install_cmd,
255+
call. = FALSE
256+
)
257+
}
258+
} else {
259+
# non-interactive sessions (CI, R CMD check, Rscript, etc.) cannot
260+
# be prompted, so fail immediately with clear instructions instead
261+
stop(
262+
"Package(s) '",
263+
paste(missing_pkgs, collapse = "', '"),
264+
"' are required for this function. Install them with:\n ",
265+
install_cmd,
266+
call. = FALSE
267+
)
268+
}
214269
}
215270

216271
os_type <- .Platform$OS.type # "windows" or "unix"

0 commit comments

Comments
 (0)