I have one repository where I have two Shiny apps that share a great deal of code, in the form of functions, objects, and some data. Because of this, it is very convenient to have the two of them in the same git repository.
Because of being in the same repo, the main ".R" file for each of them must have a different name. However, I'm having a lot of trouble deploying them to Posit Connect:
-
At first, one of my apps had the name "data-download.R" for the main file. After consistently getting
✖ Deployment failed with error: Unable to locate data-download.R. Please update your code and republish.
I tried with "app.R". This worked, but the deployed app could not find files in subfolders (it did in the "R" folder, but not others), so I wrote a script calling rsconnect::deployApp(), which sorted it out.
-
Now, to be able to have the two apps with that same name, I tried moving this file to a subfolder, i.e., "apps/data-download/app.R", and use argument appDir = "apps/data-download" in the call to rsconnect::deployApp(), but I'm afraid it doesn't seem to find the dependency files (not even the "R" subfolder). I have tried starting the paths with and without "../..", and in neither case it finds them.
-
Without argument appDir = "apps/data-download" I have the same problem as in the first point, i.e., the complete path "apps/data-download/app.R" cannot be located.
What would be the optimal solution for my use case? Thanks community!
I'm not entirely sure I understand how your apps are structured or what you ended up scripting that resolved the issue initially--if you could send the output of tree or something that might help clarify.
That said: it sounds a little bit like some of the heuristics being applied by deployApp() aren't working for you--what I've done in similar situations is supply the explicit list of files I want to be included in my apps via the appFiles argument to deployApp(). As a debugging step or as part of adopting a programmatic deployment process you can also try writing a manifest, which will give you the opportunity to inspect the list of files rsconnect has identified as being necessary for your application, and then revising that as necessary.
Hope that helps!
Thanks @edavidaja ; I had tried writing the manifest, but I have done some more tests following your advice, and I'm finding something really weird about the generated manifest. My call is something like:
library(rsconnect)
writeManifest(
appFiles = c(
"data-download.R",
...
),
appPrimaryDoc = "data-download.R"
)
deployApp(
manifestPath = "manifest.json",
...
)
There is no other ".R" file in the main document, and "app.R" is not being added to the manifest through the appFiles argument. However, "data-download.R" does not appear in the manifest, and a "app.R" appears instead. Also, the appPrimaryDoc argument seems to have no effect on the generated manifest. Here's an excerpt of the result:
{
"version": 1,
"locale": "es_ES",
"platform": "4.6.1",
"metadata": {
"appmode": "shiny",
"primary_rmd": null,
"primary_html": null,
"content_category": null,
"has_parameters": false
},
"environment": {
"r": {
"requires": "~=4.6.0"
}
},
"packages": {
...
},
"files": {
".Renviron": {
"checksum": "1582ea08dd86be9110e0aa70d2a07edf"
},
".secrets/encrypted-oauth-token.rds": {
"checksum": "9951f507c13fcfaef6ab2ac0cff4eec3"
},
"app.R": {
"checksum": "6afd99e37d1369360aca0577be7e7e17"
},
...
},
"users": null
}
So, is it possible to get rsconnect::writeManifest() to write the files as I need them?
Thanks again!
Ah. What you're seeing from rsconnect reflects a behavior of Connect itself, which doesn't currently support arbitrary entrypoints for Shiny for R applications. rsconnect rewrites the entrypoint to app.R, which you've seen. You will probably need to restructure your apps: you could symlink the shared files so that both apps can make use of them (though this may not work if you adopt git-backed deployment); or, preferably, take the opportunity to package the shared code and have each application declare a dependency on it.
Well, I have tracked the issue iin rstudio::writeManifest() down to rsconnect:::bundleAppDir(), where it is explicitly stated that the entry point file is renamed (see Line 30).
I have already considered before packaging those files, but that would complicate my workflow at this point. I think I'm going to write instead a script for deploying each app that renames the corresponding entry point file to "app.R" and then renames it back. I don't see a better option right now...
Thanks a lot for your help!
EDIT: Oh great, I entered debug mode in rsconnect::writeManifest() before noticing your link... only to arrive at the same exact point
I could have saved myself half an hour diving through the code...
withr may be of use. Good luck!