From 5ef486d101246a3b788c3b3e41af40b6cb2dfd04 Mon Sep 17 00:00:00 2001 From: vincent guyader Date: Mon, 1 Jul 2024 14:03:32 +0200 Subject: [PATCH] remove the distro parameter (#73) * remove the distro parameter * add dependencies parameter * update doc --- NEWS.md | 1 + R/dock_from_renv.R | 86 ++++----------- R/gen_base_image.R | 12 +-- dev/flat_dock_from_renv.Rmd | 138 +++++++++++------------- man/dock_from_renv.Rd | 17 ++- tests/testthat/test-dock_from_renv.R | 39 +++++-- vignettes/dockerfile-from-renv-lock.Rmd | 1 + 7 files changed, 140 insertions(+), 154 deletions(-) diff --git a/NEWS.md b/NEWS.md index b521661..a8bdb64 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,6 +3,7 @@ - remove sysreqs.r-hub.io to use {pak} instead for system requirement detection - move from `pak::pkg_system_requirements` to `pak::pkg_sysreqs()` thanks to @B0ydT - `dock_from_renv` allow to specify user to use in Dockerfile +- the `dependencies` parameter in `dock_from_renv` if set to `TRUE` will install required dependencies plus optional and development dependencies. defaut is `NA` only required (hard) dependencies, # dockerfile 0.2.2 diff --git a/R/dock_from_renv.R b/R/dock_from_renv.R index e31190a..ac15120 100644 --- a/R/dock_from_renv.R +++ b/R/dock_from_renv.R @@ -1,14 +1,5 @@ # WARNING - Generated by {fusen} from dev/flat_dock_from_renv.Rmd: do not edit by hand -# ignoring opensuse for the time being -available_distros <- c( - "xenial", - "bionic", - "focal", - "centos7", - "centos8" -) - #' @importFrom memoise memoise pkg_sysreqs_mem <- memoise::memoise( pak::pkg_sysreqs @@ -20,7 +11,7 @@ pkg_sysreqs_mem <- memoise::memoise( #' @param lockfile Path to an `renv.lock` file to use as an input.. #' @param FROM Docker image to start FROM Default is FROM rocker/r-base #' @param AS The AS of the Dockerfile. Default it `NULL`. -#' @param distro One of "focal", "bionic", "xenial", "centos7",or "centos8". See available distributions at https://hub.docker.com/r/rstudio/r-base/. +#' @param distro - deprecated - only debian/ubuntu based images are supported #' @param sysreqs boolean. If `TRUE`, the Dockerfile will contain sysreq installation. #' @param expand boolean. If `TRUE` each system requirement will have its own `RUN` line. #' @param repos character. The URL(s) of the repositories to use for `options("repos")`. @@ -33,6 +24,13 @@ pkg_sysreqs_mem <- memoise::memoise( #' If you set it to `NULL`, the latest available version of renv will be used. #' @param use_pak boolean. If `TRUE` use pak to deal with dependencies during `renv::restore()`. FALSE by default #' @param user Name of the user to specify in the Dockerfile with the USER instruction. Default is `NULL`, in which case the user from the FROM image is used. +#' @param dependencies What kinds of dependencies to install. Most commonly +#' one of the following values: +#' - `NA`: only required (hard) dependencies, +#' - `TRUE`: required dependencies plus optional and development +#' dependencies, +#' - `FALSE`: do not install any dependencies. (You might end up with a +#' non-working package, and/or the installation might fail.) #' @importFrom utils getFromNamespace #' @return A R6 object of class `Dockerfile`. #' @details @@ -59,7 +57,7 @@ pkg_sysreqs_mem <- memoise::memoise( #' } dock_from_renv <- function( lockfile = "renv.lock", - distro = "focal", + distro = NULL, FROM = "rocker/r-base", AS = NULL, sysreqs = TRUE, @@ -68,9 +66,9 @@ dock_from_renv <- function( extra_sysreqs = NULL, use_pak = FALSE, user = NULL, + dependencies = NA, renv_version ) { - distro <- match.arg(distro, available_distros) try(dockerfiler::renv$initialize(),silent=TRUE) lock <- dockerfiler::renv$lockfile_read(file = lockfile) # using vendored renv # https://rstudio.github.io/renv/reference/vendor.html?q=vendor#null @@ -79,7 +77,6 @@ dock_from_renv <- function( R_major_minor <- lock$R$Version dock <- Dockerfile$new( FROM = gen_base_image( - distro = distro, r_version = R_major_minor, FROM = FROM ), @@ -101,58 +98,18 @@ dock_from_renv <- function( message("renv version = ", ifelse(!is.null(renv_version),renv_version,"the must up to date in the repos") ) + + + # ici il faut connaire l'image utilisé par l'image. + - distro_args <- switch( - distro, - centos7 = list( - sysreqs_platform = "centos-7" - ), - centos8 = list( - sysreqs_platform = "centos-8" - ), - xenial = list( - sysreqs_platform = "ubuntu-16.04" - ), - bionic = list( - sysreqs_platform = "ubuntu-18.04" - ), - focal = list( - sysreqs_platform = "ubuntu-20.04" - ), - jammy = list( - sysreqs_platform = "ubuntu-2.04" - ) - ) - - install_cmd <- switch( - distro, - centos7 = "yum install -y", - centos8 = "yum install -y", - xenial = "apt-get install -y", - bionic = "apt-get install -y", - focal = "apt-get install -y", - jammy = "apt-get install -y" - ) - - update_cmd <- switch( - distro, - centos7 = "yum update -y", - centos8 = "yum update -y", - xenial = "apt-get update -y", - bionic = "apt-get update -y", - focal = "apt-get update -y", - jammy = "apt-get update -y" - ) + # distro_args <- list(sysreqs_platform = "ubuntu-22.04") + + distro_args <- list(sysreqs_platform = "ubuntu") - clean_cmd <- switch( - distro, - centos7 = "yum clean all && rm -rf /var/cache/yum", - centos8 = "yum clean all && rm -rf /var/cache/yum", - xenial = "rm -rf /var/lib/apt/lists/*", - bionic = "rm -rf /var/lib/apt/lists/*", - focal = "rm -rf /var/lib/apt/lists/*", - jammy = "rm -rf /var/lib/apt/lists/*" - ) + install_cmd <- "apt-get install -y" + update_cmd <-"apt-get update -y" + clean_cmd <- "rm -rf /var/lib/apt/lists/*" pkgs <- names(lock$Packages) @@ -176,7 +133,8 @@ dock_from_renv <- function( pkgs, FUN = function(x) { c( - list(pkg = x), + list(pkg = x, + dependencies = dependencies), distro_args ) } diff --git a/R/gen_base_image.R b/R/gen_base_image.R index c6db29e..72e32df 100644 --- a/R/gen_base_image.R +++ b/R/gen_base_image.R @@ -7,15 +7,15 @@ #' @keywords internal #' @noRd gen_base_image <- function( - distro = "bionic", + distro = NULL, r_version = "4.0", FROM = "rstudio/r-base" ) { - distro <- match.arg(distro, available_distros) - if (FROM == "rstudio/r-base") { - glue::glue("{FROM}:{r_version}-{distro}") - } else { +if (!is.null(distro)){ + warning("the `distro` parameter is not used anymore, only debian/ubuntu based images are supported") +} + glue::glue("{FROM}:{r_version}") - } + } diff --git a/dev/flat_dock_from_renv.Rmd b/dev/flat_dock_from_renv.Rmd index efd2c33..65fc061 100644 --- a/dev/flat_dock_from_renv.Rmd +++ b/dev/flat_dock_from_renv.Rmd @@ -22,17 +22,17 @@ library(testthat) #' #' @keywords internal gen_base_image <- function( - distro = "bionic", + distro = NULL, r_version = "4.0", FROM = "rstudio/r-base" ) { - distro <- match.arg(distro, available_distros) - if (FROM == "rstudio/r-base") { - glue::glue("{FROM}:{r_version}-{distro}") - } else { +if (!is.null(distro)){ + warning("the `distro` parameter is not used anymore, only debian/ubuntu based images are supported") +} + glue::glue("{FROM}:{r_version}") - } + } ``` @@ -41,17 +41,9 @@ gen_base_image <- function( # Create a Dockerfile from a renv.lock file + ```{r function-dock_from_renv} -# ignoring opensuse for the time being -available_distros <- c( - "xenial", - "bionic", - "focal", - "centos7", - "centos8" -) - #' @importFrom memoise memoise pkg_sysreqs_mem <- memoise::memoise( pak::pkg_sysreqs @@ -63,7 +55,7 @@ pkg_sysreqs_mem <- memoise::memoise( #' @param lockfile Path to an `renv.lock` file to use as an input.. #' @param FROM Docker image to start FROM Default is FROM rocker/r-base #' @param AS The AS of the Dockerfile. Default it `NULL`. -#' @param distro One of "focal", "bionic", "xenial", "centos7",or "centos8". See available distributions at https://hub.docker.com/r/rstudio/r-base/. +#' @param distro - deprecated - only debian/ubuntu based images are supported #' @param sysreqs boolean. If `TRUE`, the Dockerfile will contain sysreq installation. #' @param expand boolean. If `TRUE` each system requirement will have its own `RUN` line. #' @param repos character. The URL(s) of the repositories to use for `options("repos")`. @@ -76,6 +68,13 @@ pkg_sysreqs_mem <- memoise::memoise( #' If you set it to `NULL`, the latest available version of renv will be used. #' @param use_pak boolean. If `TRUE` use pak to deal with dependencies during `renv::restore()`. FALSE by default #' @param user Name of the user to specify in the Dockerfile with the USER instruction. Default is `NULL`, in which case the user from the FROM image is used. +#' @param dependencies What kinds of dependencies to install. Most commonly +#' one of the following values: +#' - `NA`: only required (hard) dependencies, +#' - `TRUE`: required dependencies plus optional and development +#' dependencies, +#' - `FALSE`: do not install any dependencies. (You might end up with a +#' non-working package, and/or the installation might fail.) #' @importFrom utils getFromNamespace #' @return A R6 object of class `Dockerfile`. #' @details @@ -97,7 +96,7 @@ pkg_sysreqs_mem <- memoise::memoise( #' @export dock_from_renv <- function( lockfile = "renv.lock", - distro = "focal", + distro = NULL, FROM = "rocker/r-base", AS = NULL, sysreqs = TRUE, @@ -106,9 +105,9 @@ dock_from_renv <- function( extra_sysreqs = NULL, use_pak = FALSE, user = NULL, + dependencies = NA, renv_version ) { - distro <- match.arg(distro, available_distros) try(dockerfiler::renv$initialize(),silent=TRUE) lock <- dockerfiler::renv$lockfile_read(file = lockfile) # using vendored renv # https://rstudio.github.io/renv/reference/vendor.html?q=vendor#null @@ -117,7 +116,6 @@ dock_from_renv <- function( R_major_minor <- lock$R$Version dock <- Dockerfile$new( FROM = gen_base_image( - distro = distro, r_version = R_major_minor, FROM = FROM ), @@ -139,58 +137,18 @@ dock_from_renv <- function( message("renv version = ", ifelse(!is.null(renv_version),renv_version,"the must up to date in the repos") ) + + + # ici il faut connaire l'image utilisé par l'image. + - distro_args <- switch( - distro, - centos7 = list( - sysreqs_platform = "centos-7" - ), - centos8 = list( - sysreqs_platform = "centos-8" - ), - xenial = list( - sysreqs_platform = "ubuntu-16.04" - ), - bionic = list( - sysreqs_platform = "ubuntu-18.04" - ), - focal = list( - sysreqs_platform = "ubuntu-20.04" - ), - jammy = list( - sysreqs_platform = "ubuntu-2.04" - ) - ) - - install_cmd <- switch( - distro, - centos7 = "yum install -y", - centos8 = "yum install -y", - xenial = "apt-get install -y", - bionic = "apt-get install -y", - focal = "apt-get install -y", - jammy = "apt-get install -y" - ) - - update_cmd <- switch( - distro, - centos7 = "yum update -y", - centos8 = "yum update -y", - xenial = "apt-get update -y", - bionic = "apt-get update -y", - focal = "apt-get update -y", - jammy = "apt-get update -y" - ) + # distro_args <- list(sysreqs_platform = "ubuntu-22.04") + + distro_args <- list(sysreqs_platform = "ubuntu") - clean_cmd <- switch( - distro, - centos7 = "yum clean all && rm -rf /var/cache/yum", - centos8 = "yum clean all && rm -rf /var/cache/yum", - xenial = "rm -rf /var/lib/apt/lists/*", - bionic = "rm -rf /var/lib/apt/lists/*", - focal = "rm -rf /var/lib/apt/lists/*", - jammy = "rm -rf /var/lib/apt/lists/*" - ) + install_cmd <- "apt-get install -y" + update_cmd <-"apt-get update -y" + clean_cmd <- "rm -rf /var/lib/apt/lists/*" pkgs <- names(lock$Packages) @@ -214,7 +172,8 @@ dock_from_renv <- function( pkgs, FUN = function(x) { c( - list(pkg = x), + list(pkg = x, + dependencies = dependencies), distro_args ) } @@ -377,7 +336,6 @@ test_that("dock_from_renv works", { out <- dock_from_renv( lockfile = the_lockfile, - distro = "focal", FROM = "rocker/verse", ) expect_s3_class( @@ -388,6 +346,9 @@ test_that("dock_from_renv works", { out, "R6" ) + #python3 is not a direct dependencies from custom_packages + expect_false( any(grepl("python3",out$Dockerfile))) + # read Dockerfile out$write( file.path( @@ -412,6 +373,7 @@ test_that("dock_from_renv works", { 1 ) + # System dependencies are different when build in interactive environment? # yes. strange. skip_if_not(interactive()) @@ -442,6 +404,34 @@ test_that("dock_from_renv works", { expect_equal(dock_created, dock_expected) }) # rstudioapi::navigateToFile(file.path(dir_build, "Dockerfile")) + +test_that("dock_from_renv works with full dependencies", { + # testthat::skip_on_cran() + # skip_if_not(interactive()) + # Create Dockerfile + + out <- dock_from_renv( + dependencies = TRUE, + lockfile = the_lockfile, + FROM = "rocker/verse", + ) + expect_s3_class( + out, + "Dockerfile" + ) + expect_s3_class( + out, + "R6" + ) + #python3 is a un-direct dependencies from custom_packages + expect_true( any(grepl("python3",out$Dockerfile))) +}) +# rstudioapi::navigateToFile(file.path(dir_build, "Dockerfile")) + + + + + unlink(dir_build) # repos_as_character ---- @@ -461,14 +451,12 @@ test_that("repos_as_character works", { # gen_base_image ---- test_that("gen_base_image works", { out <- dockerfiler:::gen_base_image( - distro = "focal", r_version = "4.0", FROM = "rstudio/r-base" ) - expect_equal(out, "rstudio/r-base:4.0-focal") + expect_equal(out, "rstudio/r-base:4.0") out <- dockerfiler:::gen_base_image( - distro = "focal", r_version = "4.0", FROM = "rocker/verse" ) @@ -489,12 +477,10 @@ for (renv_version in list(NULL,"banana","missing")){ if (!is.null(renv_version) && renv_version == "missing") { out <- dock_from_renv(lockfile = lf, - distro = "focal", FROM = "rocker/verse") } else{ out <- dock_from_renv( lockfile = lf, - distro = "focal", FROM = "rocker/verse", renv_version = renv_version ) diff --git a/man/dock_from_renv.Rd b/man/dock_from_renv.Rd index d177359..8692541 100644 --- a/man/dock_from_renv.Rd +++ b/man/dock_from_renv.Rd @@ -6,7 +6,7 @@ \usage{ dock_from_renv( lockfile = "renv.lock", - distro = "focal", + distro = NULL, FROM = "rocker/r-base", AS = NULL, sysreqs = TRUE, @@ -15,13 +15,16 @@ dock_from_renv( extra_sysreqs = NULL, use_pak = FALSE, user = NULL, + dependencies = NA, renv_version ) } \arguments{ \item{lockfile}{Path to an \code{renv.lock} file to use as an input..} -\item{distro}{One of "focal", "bionic", "xenial", "centos7",or "centos8". See available distributions at https://hub.docker.com/r/rstudio/r-base/.} +\item{distro}{\itemize{ +\item deprecated - only debian/ubuntu based images are supported +}} \item{FROM}{Docker image to start FROM Default is FROM rocker/r-base} @@ -40,6 +43,16 @@ Will be installed with apt-get install.} \item{user}{Name of the user to specify in the Dockerfile with the USER instruction. Default is \code{NULL}, in which case the user from the FROM image is used.} +\item{dependencies}{What kinds of dependencies to install. Most commonly +one of the following values: +\itemize{ +\item \code{NA}: only required (hard) dependencies, +\item \code{TRUE}: required dependencies plus optional and development +dependencies, +\item \code{FALSE}: do not install any dependencies. (You might end up with a +non-working package, and/or the installation might fail.) +}} + \item{renv_version}{character. The renv version to use in the generated Dockerfile. By default, it is set to the version specified in the \code{renv.lock} file. If the \code{renv.lock} file does not specify a renv version, the version of renv bundled with dockerfiler, diff --git a/tests/testthat/test-dock_from_renv.R b/tests/testthat/test-dock_from_renv.R index 92b3d7a..4f6d753 100644 --- a/tests/testthat/test-dock_from_renv.R +++ b/tests/testthat/test-dock_from_renv.R @@ -42,7 +42,6 @@ test_that("dock_from_renv works", { out <- dock_from_renv( lockfile = the_lockfile, - distro = "focal", FROM = "rocker/verse", ) expect_s3_class( @@ -53,6 +52,9 @@ test_that("dock_from_renv works", { out, "R6" ) + #python3 is not a direct dependencies from custom_packages + expect_false( any(grepl("python3",out$Dockerfile))) + # read Dockerfile out$write( file.path( @@ -77,6 +79,7 @@ test_that("dock_from_renv works", { 1 ) + # System dependencies are different when build in interactive environment? # yes. strange. skip_if_not(interactive()) @@ -107,6 +110,34 @@ test_that("dock_from_renv works", { expect_equal(dock_created, dock_expected) }) # rstudioapi::navigateToFile(file.path(dir_build, "Dockerfile")) + +test_that("dock_from_renv works with full dependencies", { + # testthat::skip_on_cran() + # skip_if_not(interactive()) + # Create Dockerfile + + out <- dock_from_renv( + dependencies = TRUE, + lockfile = the_lockfile, + FROM = "rocker/verse", + ) + expect_s3_class( + out, + "Dockerfile" + ) + expect_s3_class( + out, + "R6" + ) + #python3 is a un-direct dependencies from custom_packages + expect_true( any(grepl("python3",out$Dockerfile))) +}) +# rstudioapi::navigateToFile(file.path(dir_build, "Dockerfile")) + + + + + unlink(dir_build) # repos_as_character ---- @@ -126,14 +157,12 @@ test_that("repos_as_character works", { # gen_base_image ---- test_that("gen_base_image works", { out <- dockerfiler:::gen_base_image( - distro = "focal", r_version = "4.0", FROM = "rstudio/r-base" ) - expect_equal(out, "rstudio/r-base:4.0-focal") + expect_equal(out, "rstudio/r-base:4.0") out <- dockerfiler:::gen_base_image( - distro = "focal", r_version = "4.0", FROM = "rocker/verse" ) @@ -154,12 +183,10 @@ for (renv_version in list(NULL,"banana","missing")){ if (!is.null(renv_version) && renv_version == "missing") { out <- dock_from_renv(lockfile = lf, - distro = "focal", FROM = "rocker/verse") } else{ out <- dock_from_renv( lockfile = lf, - distro = "focal", FROM = "rocker/verse", renv_version = renv_version ) diff --git a/vignettes/dockerfile-from-renv-lock.Rmd b/vignettes/dockerfile-from-renv-lock.Rmd index 5063bfe..661f4bc 100644 --- a/vignettes/dockerfile-from-renv-lock.Rmd +++ b/vignettes/dockerfile-from-renv-lock.Rmd @@ -34,6 +34,7 @@ library(dockerfiler) # Create a Dockerfile from a renv.lock file + ```{r example-dock_from_renv}