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

writeManifest() gives confusing error if no app.R #1098

Open
hadley opened this issue Aug 12, 2024 · 3 comments
Open

writeManifest() gives confusing error if no app.R #1098

hadley opened this issue Aug 12, 2024 · 3 comments

Comments

@hadley
Copy link
Member

hadley commented Aug 12, 2024

i.e. create a new project with file foo.R containing library(shiny), then run writeManfiest():

> rsconnect::writeManifest()
Error in `quartoInspect()`:
! Failed to run `quarto inspect` against your content:
ERROR: /Users/hadleywickham/Desktop/madlibs2/madlibs.R is not a valid
Quarto input document

Presumably because it's using the wrong primary document, but why is it passing an R file to quarto? Should also log about the primary file.

@aronatkins
Copy link
Contributor

Background:

It is assumed that if you have an R script, nothing else indicates a different content type, and it is not a well-known filename (app.R, plumber.R), then it must be a standalone R script that you want to render with Quarto.

See inferAppMode():

rsconnect/R/appMetadata.R

Lines 192 to 199 in 9999fdb

if (hasR) {
# We have R scripts but it was not otherwise identified as Shiny or Plumber
# and also not accompanied by *.qmd or *.rmd files.
#
# Assume that this is a rendered script, as this is a better fall-back than
# "static".
return("quarto-static")
}

In general, we want Shiny applications in app.R files. Renaming of foo.R to app.R occurs very narrowly, mostly to support RStudio.

rsconnect/R/bundle.R

Lines 25 to 36 in 9999fdb

if (!is.null(appMode) && appMode == "shiny") {
# When deploying a single-file Shiny application and we have been provided
# appPrimaryDoc (usually by RStudio), rename that file to `app.R` so it
# will be discovered and run by shiny::runApp(getwd()).
#
# Note: We do not expect to see writeManifest(appPrimaryDoc="notapp.R").
if (is.character(appPrimaryDoc) &&
tolower(tools::file_ext(appPrimaryDoc)) == "r" &&
file == appPrimaryDoc) {
to <- file.path(bundleDir, "app.R")
}
}

That renaming workflow doesn't work when you're trying to produce a manifest.json, since the produced manifest needs to reference the original filename.

Connect uses shiny::runApp() to ask Shiny to run the application contained within the current directory. It does not supply a specific endpoint R file, but relies on the default Shiny behavior. When you try to use shiny::runApp() in a directory with foo.R, it complains:

R -s -e 'shiny::runApp()'
#> Loading required package: shiny
#> Error in `shinyAppDir()`:
#> ! App dir must contain either app.R or server.R.
#> Backtrace:
#>     ▆
#>  1. └─shiny::runApp()
#>  2.   ├─shiny::as.shiny.appobj(appDir)
#>  3.   └─shiny:::as.shiny.appobj.character(appDir)
#>  4.     └─shiny::shinyAppDir(x)
#>  5.       └─rlang::abort(...)

@aronatkins
Copy link
Contributor

We don't log the inferred app-mode nor why we made that choice.

@thomasp85
Copy link

Slightly related - the logic captured in

if (!is.null(appPrimaryDoc) &&
tolower(tools::file_ext(appPrimaryDoc)) == "r") {
appMode <- "shiny"

caught me quite off-guard. I was trying to be explicit about what the primary R script was but doing so makes writeManifest insist that it is a shiny app

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants