Skip to content

Commit

Permalink
Merge pull request #978 from rstudio/kegs-env-management
Browse files Browse the repository at this point in the history
Implement envManagement args for `::writeManifest()`
  • Loading branch information
dbkegley authored Aug 29, 2023
2 parents 92d35f8 + 11c0648 commit c46bf29
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 7 deletions.
12 changes: 12 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@

* Ignore `.env`, `.venv`, and `venv` files only when they reference Python
virtual environments. (#972)

* `deployApp()` and `writeManifest()` accept optional `envManagement`,
`envManagementR`, and `envManagementPy` arguments. These args specify whether
Posit Connect should install packages in the package cache.
If `envManagement` is `FALSE` then Connect will not perform any package
installation and it is the administrator's responsibility to ensure the
required R/Python packages are available in the runtime environment. This is
especially useful if off-host execution is enabled, when the execution
environment (specified by the `image` argument) already contains the required
packages. These values are ignored when
`Applications.ManifestEnvironmentManagementSelection = false`.
Requires Posit Connect `>=2023.07.0`. (#977)

# rsconnect 1.0.2

Expand Down
36 changes: 33 additions & 3 deletions R/bundle.R
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ createAppManifest <- function(appDir,
pythonConfig = NULL,
retainPackratDirectory = TRUE,
image = NULL,
envManagement = NULL,
envManagementR = NULL,
envManagementPy = NULL,
verbose = FALSE,
quiet = FALSE) {

Expand Down Expand Up @@ -191,9 +194,36 @@ createAppManifest <- function(appDir,
# add metadata
manifest$metadata <- metadata

# if there is a target image, attach it to the environment
if (!is.null(image)) {
manifest$environment <- list(image = image)
# handle shorthand arg to enable/disable both R and Python
if (!is.null(envManagement)) {
envManagementR <- envManagement
envManagementPy <- envManagement
}

# if envManagement is explicitly enabled/disabled,
# create an environment_management obj
envManagementInfo <- list()
if (!is.null(envManagementR)) {
envManagementInfo$r <- envManagementR
}
if (!is.null(envManagementPy)) {
envManagementInfo$python <- envManagementPy
}

# emit the environment field
if (!is.null(image) || length(envManagementInfo) > 0) {
manifest$environment <- list()

# if there is a target image, attach it to the environment
if (!is.null(image)) {
manifest$environment$image <- image
}

# if either environment_management.r or environment_management.python
# is provided, write the environment_management field
if (length(envManagementInfo) > 0) {
manifest$environment$environment_management <- envManagementInfo
}
}

# indicate whether this is a quarto app/doc
Expand Down
41 changes: 38 additions & 3 deletions R/deployApp.R
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,29 @@
#' @param image Optional. The name of the image to use when building and
#' executing this content. If none is provided, Posit Connect will
#' attempt to choose an image based on the content requirements.
#' @param envManagement Optional. Should Posit Connect install R and Python
#' packages for this content? (`TRUE`, `FALSE`, or `NULL`).
#' The default, `NULL`, will not write any values to the bundle manifest,
#' and Connect will fall back to the application default environment
#' management strategy, or the server default if no application default
#' is defined.
#'
#' (This option is a shorthand flag which overwrites the values of both
#' `envManagementR` and `envManagementPy`.)
#' @param envManagementR Optional. Should Posit Connect install R packages
#' for this content? (`TRUE`, `FALSE`, or `NULL`). The default, `NULL`, will
#' not write any values to the bundle manifest, and Connect will fall back to
#' the application default R environment management strategy, or the server
#' default if no application default is defined.
#'
#' (This option is ignored when `envManagement` is non-`NULL`.)
#' @param envManagementPy Optional. Should Posit Connect install Python packages
#' for this content? (`TRUE`, `FALSE`, or `NULL`). The default, `NULL`, will
#' not write any values to the bundle manifest, and Connect will fall back to
#' the application default Python environment management strategy, or the
#' server default if no application default is defined.
#'
#' (This option is ignored when `envManagement` is non-`NULL`.)
#' @examples
#' \dontrun{
#'
Expand Down Expand Up @@ -197,7 +220,10 @@ deployApp <- function(appDir = getwd(),
forceGeneratePythonEnvironment = FALSE,
quarto = NA,
appVisibility = NULL,
image = NULL
image = NULL,
envManagement = NULL,
envManagementR = NULL,
envManagementPy = NULL
) {

check_string(appDir)
Expand Down Expand Up @@ -424,7 +450,10 @@ deployApp <- function(appDir = getwd(),
quiet = quiet,
verbose = verbose,
pythonConfig = pythonConfig,
image = image
image = image,
envManagement = envManagement,
envManagementR = envManagementR,
envManagementPy = envManagementPy
)
size <- format(file_size(bundlePath), big.mark = ",")
taskComplete(quiet, "Created {size}b bundle")
Expand Down Expand Up @@ -589,7 +618,10 @@ bundleApp <- function(appName,
verbose = FALSE,
quiet = FALSE,
pythonConfig = NULL,
image = NULL) {
image = NULL,
envManagement = NULL,
envManagementR = NULL,
envManagementPy = NULL) {
logger <- verboseLogger(verbose)

# get application users (for non-document deployments)
Expand All @@ -615,6 +647,9 @@ bundleApp <- function(appName,
pythonConfig = pythonConfig,
retainPackratDirectory = TRUE,
image = image,
envManagement = envManagement,
envManagementR = envManagementR,
envManagementPy = envManagementPy,
verbose = verbose,
quiet = quiet
)
Expand Down
6 changes: 6 additions & 0 deletions R/writeManifest.R
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ writeManifest <- function(appDir = getwd(),
forceGeneratePythonEnvironment = FALSE,
quarto = NA,
image = NULL,
envManagement = NULL,
envManagementR = NULL,
envManagementPy = NULL,
verbose = FALSE,
quiet = FALSE) {
appFiles <- listDeploymentFiles(
Expand Down Expand Up @@ -61,6 +64,9 @@ writeManifest <- function(appDir = getwd(),
pythonConfig = pythonConfig,
retainPackratDirectory = FALSE,
image = image,
envManagement = envManagement,
envManagementR = envManagementR,
envManagementPy = envManagementPy,
verbose = verbose,
quiet = quiet
)
Expand Down
31 changes: 30 additions & 1 deletion man/deployApp.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions man/writeManifest.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions tests/testthat/test-writeManifest.R
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,29 @@ test_that("Sets environment.image in the manifest if one is provided", {
expect_null(manifest$environment)
})

test_that("Sets environment.environment_management in the manifest if envManagement is defined", {
withr::local_options(renv.verbose = TRUE)

appDir <- test_path("shinyapp-simple")

# test shorthand arg
manifest <- makeManifest(appDir, envManagement = FALSE, envManagementR = TRUE, envManagementPy = TRUE)
expect_equal(manifest$environment$environment_management$r, FALSE)
expect_equal(manifest$environment$environment_management$python, FALSE)

# test R and Python args
manifest <- makeManifest(appDir, envManagementR = TRUE)
expect_equal(manifest$environment$environment_management$r, TRUE)
expect_null(manifest$environment$environment_management$python)
manifest <- makeManifest(appDir, envManagementPy = TRUE)
expect_equal(manifest$environment$environment_management$python, TRUE)
expect_null(manifest$environment$environment_management$r)

# environment_management is not defined when envManagementR and envManagementPy are NULL
manifest <- makeManifest(appDir, image = "rstudio/content-base:latest")
expect_null(manifest$environment$environment_management)
})

# appMode Inference tests

test_that("content type (appMode) is inferred and can be overridden", {
Expand Down

0 comments on commit c46bf29

Please sign in to comment.