diff --git a/NEWS.md b/NEWS.md index 26cad305..01764eb9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,11 @@ * Do not use `getOption("available_packages_filters")` option when calling `available.packages()`. (#1002) +* Improve reporting of errors returned by shinyapps.io. (#997) + +* Remove most directory layout validation checks. (#998) + + # rsconnect 1.1.0 * Fixed analysis of directories that were smaller than the diff --git a/R/appMetadata.R b/R/appMetadata.R index 3dfb249b..105e097f 100644 --- a/R/appMetadata.R +++ b/R/appMetadata.R @@ -82,8 +82,6 @@ appMetadata <- function(appDir, checkAppLayout <- function(appDir, appPrimaryDoc = NULL) { appFilesBase <- tolower(list.files(appDir)) - wwwFiles <- tolower(list.files(file.path(appDir, "www/"))) - primaryIsRScript <- identical(tolower(tools::file_ext(appPrimaryDoc)), "r") # check for single-file app collision @@ -93,29 +91,8 @@ checkAppLayout <- function(appDir, appPrimaryDoc = NULL) { ) } - # Do some checks for a valid application structure - satisfiedLayouts <- c( - shinyAndUi = all(c("server.r", "ui.r") %in% appFilesBase), - shinyAndIndex = "server.r" %in% appFilesBase && "index.html" %in% wwwFiles, - app = primaryIsRScript || any("app.r" %in% appFilesBase), - Rmd = any(grepl(glob2rx("*.rmd"), appFilesBase)), - Qmd = any(grepl(glob2rx("*.qmd"), appFilesBase)), - static = any(grepl("(?:html?|pdf)$", appFilesBase)), - plumber = any(c("entrypoint.r", "plumber.r") %in% appFilesBase) - ) - - if (any(satisfiedLayouts)) { - return() - } - - cli::cli_abort(c( - "Cancelling deployment: invalid project layout.", - i = "Expecting one of the following publication types:", - " " = "1. A Shiny app with `app.R` or `server.R` + `ui.R`", - " " = "2. R Markdown (`.Rmd`) or Quarto (`.qmd`) documents.", - " " = "3. A website containing `.html` and/or `.pdf` files.", - " " = "4. A plumber API with `plumber.R` or `entrypoint.R`." - )) + # all other layouts are allowed; the server determines (with the required packages) if the content + # can be run/served. } # infer the mode of the application from files in the root dir diff --git a/tests/testthat/_snaps/appMetadata.md b/tests/testthat/_snaps/appMetadata.md index b5327b67..d105f445 100644 --- a/tests/testthat/_snaps/appMetadata.md +++ b/tests/testthat/_snaps/appMetadata.md @@ -18,24 +18,11 @@ # checkLayout() errors if primary doc & app.R Code - checkAppLayout(dir, "myscript.R") + checkAppLayout(dir, appPrimaryDoc = "myscript.R") Condition Error in `checkAppLayout()`: ! Project must not contain both 'app.R' and a single-file Shiny app. -# checkLayout fails if no known structure - - Code - checkAppLayout(dir) - Condition - Error in `checkAppLayout()`: - ! Cancelling deployment: invalid project layout. - i Expecting one of the following publication types: - 1. A Shiny app with `app.R` or `server.R` + `ui.R` - 2. R Markdown (`.Rmd`) or Quarto (`.qmd`) documents. - 3. A website containing `.html` and/or `.pdf` files. - 4. A plumber API with `plumber.R` or `entrypoint.R`. - # errors if no files with needed extension Code diff --git a/tests/testthat/test-appMetadata.R b/tests/testthat/test-appMetadata.R index ef8fcff7..bd1841dc 100644 --- a/tests/testthat/test-appMetadata.R +++ b/tests/testthat/test-appMetadata.R @@ -65,30 +65,43 @@ test_that("checkLayout() errors if primary doc & app.R", { "myscript.R" = "" )) - expect_snapshot(checkAppLayout(dir, "myscript.R"), error = TRUE) -}) - -test_that("checkLayout fails if no known structure", { - dir <- local_temp_app(list( - "data.txt" = "", - "cats.csv" = "" - )) - - expect_snapshot(checkAppLayout(dir), error = TRUE) + expect_snapshot(checkAppLayout(dir, appPrimaryDoc = "myscript.R"), error = TRUE) }) test_that("checkLayout succeeds with some common app structures", { rmd <- local_temp_app(list("foo.Rmd" = "")) expect_no_error(checkAppLayout(rmd)) + qmd <- local_temp_app(list("foo.qmd" = "")) + expect_no_error(checkAppLayout(qmd)) + + # perhaps script.R is a pre-render script that generates *.qmd + project <- local_temp_app(list("_quarto.yml" = "", "script.R" = "")) + expect_no_error(checkAppLayout(project)) + + md <- local_temp_app(list("_quarto.yml" = "", "index.md" = "")) + expect_no_error(checkAppLayout(md)) + shiny1 <- local_temp_app(list("app.R" = "")) - expect_no_error(checkAppLayout(rmd)) + expect_no_error(checkAppLayout(shiny1)) shiny2 <- local_temp_app(list("server.R" = "", "ui.R" = "")) - expect_no_error(checkAppLayout(rmd)) + expect_no_error(checkAppLayout(shiny2)) + + api <- local_temp_app(list("plumber.R" = "")) + expect_no_error(checkAppLayout(api)) static <- local_temp_app(list("foo.html" = "")) - expect_no_error(checkAppLayout(rmd)) + expect_no_error(checkAppLayout(static)) + + staticxml <- local_temp_app(list("data.xml" = "")) + expect_no_error(checkAppLayout(staticxml)) + + staticdata <- local_temp_app(list( + "data.txt" = "", + "cats.csv" = "" + )) + expect_no_error(checkAppLayout(staticdata)) }) # inferAppMode ------------------------------------------------------------