diff --git a/DESCRIPTION b/DESCRIPTION index 972e454..5fbaf77 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -17,7 +17,7 @@ License: MIT + file LICENSE Imports: attachment (>= 0.4.3), cli, - dockerfiler, + dockerfiler (>= 0.2.6), here, yesno Encoding: UTF-8 diff --git a/NEWS.md b/NEWS.md index 0fbde01..0313f1a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,10 @@ +# shiny2docker (development version) + +* `shiny2docker()` gains a `renv_version` parameter, forwarded to + `dockerfiler::dock_from_renv()`. Set to `NULL` to bootstrap with the + latest available renv (skipping the `remotes` dependency entirely). + # shiny2docker 0.0.3 * `set_gitlab_ci()` now accepts a `tags` parameter so you can specify one or diff --git a/R/shiny2docker.R b/R/shiny2docker.R index 4a8da14..a79dedf 100644 --- a/R/shiny2docker.R +++ b/R/shiny2docker.R @@ -25,6 +25,11 @@ #' non-working package, and/or the installation might fail.) #' @param sysreqs_platform System requirements platform.`ubuntu` by default. If `NULL`, then the current platform is used. Can be : "ubuntu-22.04" if needed to fit with the `FROM` Operating System. Only debian or ubuntu based images are supported #' @param folder_to_exclude Folder to exclude during scan to detect packages +#' @param renv_version character. Optional. Forwarded to +#' [dockerfiler::dock_from_renv()]. By default (parameter omitted), the +#' renv version recorded in the `renv.lock` file is used. Set to `NULL` +#' to install the latest available renv from the configured repos +#' (faster build, no `remotes` dependency). #' #' @return An object of class `dockerfiler`, representing the generated Dockerfile. This object can be further manipulated using `dockerfiler` functions before being written to disk. #' @@ -72,7 +77,8 @@ shiny2docker <- function(path = ".", user = NULL, dependencies = NA, sysreqs_platform = "ubuntu", - folder_to_exclude = c("renv")) { + folder_to_exclude = c("renv"), + renv_version) { if (missing(path)) { if (yesno::yesno2("path is missing. Do you want to use the current directory?")) { @@ -90,9 +96,8 @@ shiny2docker <- function(path = ".", create_dockerignore(path = file.path(dirname(output), ".dockerignore")) } - dock <- dockerfiler::dock_from_renv( + dock_from_renv_args <- list( lockfile = lockfile, - FROM = FROM, AS = AS, sysreqs = sysreqs, @@ -103,9 +108,16 @@ shiny2docker <- function(path = ".", user = user, dependencies = dependencies, sysreqs_platform = sysreqs_platform - - ) + # Forward renv_version only when supplied so that dock_from_renv() keeps + # its own default ("read the version from the lockfile") -- which differs + # from `renv_version = NULL` ("install the latest renv"). Single-bracket + # assignment on the list preserves an explicit NULL (the regular `$<-` / + # `[[<-` would delete the entry instead). + if (!missing(renv_version)) { + dock_from_renv_args["renv_version"] <- list(renv_version) + } + dock <- do.call(dockerfiler::dock_from_renv, dock_from_renv_args) dock$WORKDIR("/srv/shiny-server/") dock$COPY(from = ".", to = "/srv/shiny-server/") dock$EXPOSE(3838) diff --git a/man/shiny2docker.Rd b/man/shiny2docker.Rd index 3461f03..d3a9502 100644 --- a/man/shiny2docker.Rd +++ b/man/shiny2docker.Rd @@ -18,7 +18,8 @@ shiny2docker( user = NULL, dependencies = NA, sysreqs_platform = "ubuntu", - folder_to_exclude = c("renv") + folder_to_exclude = c("renv"), + renv_version ) } \arguments{ @@ -58,6 +59,12 @@ non-working package, and/or the installation might fail.) \item{sysreqs_platform}{System requirements platform.\code{ubuntu} by default. If \code{NULL}, then the current platform is used. Can be : "ubuntu-22.04" if needed to fit with the \code{FROM} Operating System. Only debian or ubuntu based images are supported} \item{folder_to_exclude}{Folder to exclude during scan to detect packages} + +\item{renv_version}{character. Optional. Forwarded to +\code{\link[dockerfiler:dock_from_renv]{dockerfiler::dock_from_renv()}}. By default (parameter omitted), the +renv version recorded in the \code{renv.lock} file is used. Set to \code{NULL} +to install the latest available renv from the configured repos +(faster build, no \code{remotes} dependency).} } \value{ An object of class \code{dockerfiler}, representing the generated Dockerfile. This object can be further manipulated using \code{dockerfiler} functions before being written to disk. diff --git a/tests/testthat/test-shiny2docker.R b/tests/testthat/test-shiny2docker.R index 2f94040..3851f07 100644 --- a/tests/testthat/test-shiny2docker.R +++ b/tests/testthat/test-shiny2docker.R @@ -20,3 +20,48 @@ unlink("dummy_app/renv.lock",force = TRUE) unlink("dummy_app/Dockerfile",force = TRUE) unlink("dummy_app/.dockerignore",force = TRUE) }) + +test_that("shiny2docker forwards renv_version to dock_from_renv", { + unlink("dummy_app/renv.lock", force = TRUE) + unlink("dummy_app/Dockerfile", force = TRUE) + unlink("dummy_app/.dockerignore", force = TRUE) + + if (isTRUE(testthat:::on_cran())) { + file.copy(from = "dummy_app/renv.lock.cran.lock", + to = "dummy_app/renv.lock") + } + + # When renv_version is forwarded as NULL, dock_from_renv() takes the + # "latest renv" branch and must NOT use remotes::install_version (which + # is the default branch when renv_version is missing). The exact install + # line differs across dockerfiler versions, but the absence of + # `install_version` is invariant. + out <- shiny2docker(path = "dummy_app/", renv_version = NULL) + expect_false(any(grepl("install_version", out$Dockerfile))) + + unlink("dummy_app/renv.lock", force = TRUE) + unlink("dummy_app/Dockerfile", force = TRUE) + unlink("dummy_app/.dockerignore", force = TRUE) +}) + +test_that("shiny2docker forwards an explicit renv_version to dock_from_renv", { + unlink("dummy_app/renv.lock", force = TRUE) + unlink("dummy_app/Dockerfile", force = TRUE) + unlink("dummy_app/.dockerignore", force = TRUE) + + if (isTRUE(testthat:::on_cran())) { + file.copy(from = "dummy_app/renv.lock.cran.lock", + to = "dummy_app/renv.lock") + } + + # An explicit version string must reach dock_from_renv() and produce a + # remotes::install_version("renv", version = "1.0.3") line. + out <- shiny2docker(path = "dummy_app/", renv_version = "1.0.3") + expect_true( + any(grepl("install_version.*renv.*1\\.0\\.3", out$Dockerfile)) + ) + + unlink("dummy_app/renv.lock", force = TRUE) + unlink("dummy_app/Dockerfile", force = TRUE) + unlink("dummy_app/.dockerignore", force = TRUE) +})