Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

produce an error when Quarto content cannot be inspected #1039

Merged
merged 3 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
40 changes: 25 additions & 15 deletions R/appMetadata-quarto.R
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Called only when the content is known to be Quarto.
inferQuartoInfo <- function(metadata, appDir, appPrimaryDoc) {
if (hasQuartoMetadata(metadata)) {
return(list(
Expand All @@ -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"]])
Expand All @@ -37,20 +34,33 @@ 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(
"Failed to run `quarto inspect` against your content:",
json
)
)
}
return(NULL)
jsonlite::fromJSON(json)
}

# inlined from quarto::quarto_path()
Expand Down
18 changes: 18 additions & 0 deletions tests/testthat/_snaps/appMetadata-quarto.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,21 @@
! `quarto` not found.
i Check that it is installed and available on your `PATH`.

# quartoInspect produces an error when a document cannot be inspected

Code
quartoInspect(dir, "bad.qmd")
Condition
Error in `quartoInspect()`:
! Failed to run `quarto inspect` against your content:
ERROR: Unknown format unsupported

# quartoInspect produces an error when a project cannot be inspected

Code
quartoInspect(dir, "bad.qmd")
Condition
Error in `quartoInspect()`:
! Failed to run `quarto inspect` against your content:
ERROR: Unsupported project type unsupported

85 changes: 56 additions & 29 deletions tests/testthat/test-appMetadata-quarto.R
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -43,38 +43,14 @@ 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, {
quartoInspect()
})
})

test_that("quartoInspect identifies on Quarto projects", {
test_that("quartoInspect identifies Quarto projects", {
skip_if_no_quarto()

inspect <- quartoInspect(test_path("quarto-website-r"))
Expand Down Expand Up @@ -123,9 +99,60 @@ 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", {
# Some versions of Quarto show Quarto stack traces with source references when
# inspect fails.
#
# Only preserve:
#
# Error in `quartoInspect()`:
# ! Failed to run `quarto inspect` against your content:
# ERROR: Unsupported project type unsupported
strip_quarto_trace <- function(lines) {
head(lines, 3)
}

test_that("quartoInspect produces an error when a document cannot be inspected", {
skip_if_no_quarto()

# Suppress colors from Quarto errors.
withr::local_envvar(NO_COLOR = "1")

dir <- local_temp_app(list("bad.qmd" = c(
"---",
"format: unsupported",
"---",
"this is a document using an unsupported format."
)))
expect_snapshot(
quartoInspect(dir, "bad.qmd"),
error = TRUE,
transform = strip_quarto_trace
)
})

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)
# Suppress colors from Quarto errors.
withr::local_envvar(NO_COLOR = "1")

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_snapshot(
quartoInspect(dir, "bad.qmd"),
error = TRUE,
transform = strip_quarto_trace
)
})
Loading