rstudio / rsconnect

Publish Shiny Applications, RMarkdown Documents, Jupyter Notebooks, Plumber APIs, and more

Home Page:http://rstudio.github.io/rsconnect/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

quarto: engines metadata is vector, not singular

aronatkins opened this issue · comments

Quarto content can report multiple engines, which arrives as the metadata argument to deployApp() and others.

That metadata is eventually serialized into a deployment record. The presence of multiple engines causes rsconnect to write two records into a single DCF file.

record <- rsconnect:::deploymentRecord(
    name = "the-name",
    title = "the-title",
    username = "the-username",
    account = "the-account",
    server = "the-server",
    metadata = list(quarto_engines = c("knitr","markdown"))
)
t <- tempfile()
rsconnect:::writeDeploymentRecord(record, t)
read.dcf(t)
#>      name       title       username       account       server       hostUrl
#> [1,] "the-name" "the-title" "the-username" "the-account" "the-server" ""     
#> [2,] "the-name" "the-title" "the-username" "the-account" "the-server" ""     
#>      appId bundleId url version quarto_engines
#> [1,] ""    ""       ""  "1"     "knitr"       
#> [2,] ""    ""       ""  "1"     "markdown"

We serialize envVars to a comma-separated list, but take no similar action for other multi-value fields.

deployments$envVars[is.na(deployments$envVars)] <- ""
if (is.character(deployments$envVars)) {
deployments$envVars <- strsplit(deployments$envVars, ", ")
}

envVars = if (length(envVars) > 0) paste0(envVars, collapse = ", ") else NA,

Discovered while investigating #1014

The RStudio IDE sends a vector of engines:

https://github.com/rstudio/rstudio/blob/afbabb533c00add040c124126438177457ba5592/src/cpp/session/modules/SessionRSConnect.cpp#L110-L111

The quarto R package also provides a vector:

https://github.com/quarto-dev/quarto-r/blob/2fd494eb69f0dd6495bf6f8303075f451f8e8186/R/publish.R#L399-L404

Additionally, rsconnect can compute a vector of engines:

list(
version = inspect[["quarto"]][["version"]],
engines = I(inspect[["engines"]])
)
}

The vector of engines is used when determining if R or Python are needed:

is.null(appMetadata$quartoInfo) ||
"knitr" %in% appMetadata$quartoInfo[["engines"]]

"jupyter" %in% appMetadata$quartoInfo$engines ||

That data is also sent in the manifest.json to guide environment reconstruction.

rsconnect/R/bundle.R

Lines 229 to 230 in 525289d

# indicate whether this is a quarto app/doc
manifest$quarto <- appMetadata$quartoInfo

We should convert metadata fields from vectors to a comma-separated string when writing the DCF file, but can probably leave them in that form when the DCF file is read.

A consequence of this problem: The RStudio IDE could show two target deployments when one existed, and publishing attempts fail with errors like:

── Preparing for deployment ────────────────────────────────────────────────────
Error in `rsconnect::deployApp()`:
! This directory has been previously deployed in multiple places.
Please use `appName`, `server` or `account` to disambiguate.
Known applications:
• quarto-failed-republish (server: SERVERNAME / username: USERNAME):
  <https://SERVERNAME/content/cf5960ea-484f-4285-9207-2b17aca4a27e/>
• quarto-failed-republish (server: SERVERNAME / username: USERNAME):
  <https://SERVERNAME/content/cf5960ea-484f-4285-9207-2b17aca4a27e/>
Backtrace:
    ▆
 1. └─rsconnect::deployApp(...)
 2.   └─rsconnect:::deploymentTarget(...)
 3.     └─rsconnect:::disambiguateDeployments(appDeployments, error_call = error_call)
 4.       └─rsconnect:::cli_menu(...)
 5.         └─cli::cli_abort(c(header, not_interactive), .envir = .envir, call = error_call)
 6.           └─rlang::abort(...)
Execution halted