diff --git a/NEWS.md b/NEWS.md index 41198dc7..ce842983 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,7 @@ needed to be quoted. The resulting manifest lacked information about the Quarto runtime, which caused difficult-to-understand deployment errors. (#1037) +* Produce an error when Quarto content cannot be inspected. (#1032) # rsconnect 1.2.0 diff --git a/R/appMetadata-quarto.R b/R/appMetadata-quarto.R index 5e682731..07cccf93 100644 --- a/R/appMetadata-quarto.R +++ b/R/appMetadata-quarto.R @@ -1,3 +1,4 @@ +# Called only when the content is known to be Quarto. inferQuartoInfo <- function(metadata, appDir, appPrimaryDoc) { if (hasQuartoMetadata(metadata)) { return(list( @@ -11,10 +12,6 @@ inferQuartoInfo <- function(metadata, appDir, appPrimaryDoc) { appDir = appDir, appPrimaryDoc = appPrimaryDoc ) - if (is.null(inspect)) { - return(NULL) - } - list( version = inspect[["quarto"]][["version"]], engines = I(inspect[["engines"]]) @@ -37,20 +34,34 @@ quartoInspect <- function(appDir = NULL, appPrimaryDoc = NULL) { )) } - paths <- c(appDir, file.path(appDir, appPrimaryDoc)) + json <- suppressWarnings( + system2( + quarto, c("inspect", shQuote(appDir)), + stdout = TRUE, stderr = TRUE + ) + ) + status <- attr(json, "status") + + if (!is.null(status) && !is.null(appPrimaryDoc)) { + json <- suppressWarnings( + system2( + quarto, c("inspect", shQuote(file.path(appDir, appPrimaryDoc))), + stdout = TRUE, stderr = TRUE + ) + ) + status <- attr(json, "status") + } - for (path in paths) { - args <- c("inspect", shQuote(path.expand(path))) - inspect <- tryCatch( - { - json <- suppressWarnings(system2(quarto, args, stdout = TRUE, stderr = TRUE)) - parsed <- jsonlite::fromJSON(json) - return(parsed) - }, - error = function(e) NULL + if (!is.null(status)) { + cli::cli_abort( + c( + "Unable to run `quarto inspect` against your content:", + json + ) ) } - return(NULL) + parsed <- jsonlite::fromJSON(json) + return(parsed) } # inlined from quarto::quarto_path() diff --git a/tests/testthat/test-appMetadata-quarto.R b/tests/testthat/test-appMetadata-quarto.R index fa13ea5d..ecfa88e7 100644 --- a/tests/testthat/test-appMetadata-quarto.R +++ b/tests/testthat/test-appMetadata-quarto.R @@ -29,7 +29,7 @@ test_that("inferQuartoInfo correctly detects info when quarto is provided alone" expect_equal(quartoInfo$engines, I(c("knitr"))) }) -test_that("inferQuartoInfo extracts info from metadata", { +test_that("inferQuartoInfo prefers metadata over quarto inspect", { metadata <- fakeQuartoMetadata(version = "99.9.9", engines = c("internal-combustion")) quartoInfo <- inferQuartoInfo( @@ -43,30 +43,6 @@ test_that("inferQuartoInfo extracts info from metadata", { )) }) -test_that("inferQuartoInfo prefers using metadata over quarto inspect", { - skip_if_no_quarto() - - metadata <- fakeQuartoMetadata(version = "99.9.9", engines = c("internal-combustion")) - - quartoInfo <- inferQuartoInfo( - appDir = test_path("quarto-website-r"), - appPrimaryDoc = NULL, - metadata = metadata - ) - expect_equal(quartoInfo$engines, I(c("internal-combustion"))) -}) - -test_that("inferQuartoInfo returns NULL for non-quarto content", { - skip_if_no_quarto() - - quartoInfo <- inferQuartoInfo( - appDir = test_path("shinyapp-simple"), - appPrimaryDoc = NULL, - metadata = list() - ) - expect_null(quartoInfo) -}) - test_that("quartoInspect requires quarto", { local_mocked_bindings(quarto_path = function() NULL) expect_snapshot(error = TRUE, { @@ -74,7 +50,7 @@ test_that("quartoInspect requires quarto", { }) }) -test_that("quartoInspect identifies on Quarto projects", { +test_that("quartoInspect identifies Quarto projects", { skip_if_no_quarto() inspect <- quartoInspect(test_path("quarto-website-r")) @@ -123,9 +99,42 @@ test_that("quartoInspect processes content with filenames containing spaces", { expect_equal(inspect$engines, c("markdown")) }) -test_that("quartoInspect returns NULL on non-quarto Quarto content", { +test_that("quartoInspect produces an error when a document cannot be inspected", { + skip_if_no_quarto() + + dir <- local_temp_app(list("bad.qmd" = c( + "---", + "format: unsupported", + "---", + "this is a document using an unsupported format." + ))) + expect_error( + quartoInspect(dir, "bad.qmd"), + "Unable to run `quarto inspect` against your content", + fixed = TRUE + ) +}) + +test_that("quartoInspect produces an error when a project cannot be inspected", { skip_if_no_quarto() - inspect <- quartoInspect(test_path("shinyapp-simple")) - expect_null(inspect) + dir <- local_temp_app( + list( + "_quarto.yml" = c( + "project:", + " type: unsupported" + ), + "bad.qmd" = c( + "---", + "title: bad", + "---", + "this is a document using an unsupported format." + ) + ) + ) + expect_error( + quartoInspect(dir, "bad.qmd"), + "Unable to run `quarto inspect` against your content", + fixed = TRUE + ) })