rstudio / rsconnect

Publish Shiny Applications, RMarkdown Documents, Jupyter Notebooks, Plumber APIs, and more
http://rstudio.github.io/rsconnect/
133 stars 82 forks source link

Deployment dry run #725

Open hadley opened 1 year ago

hadley commented 1 year ago

Make it easier to diagnose issues locally by running the app in an environment that simulates what you'll get on the server.

hadley commented 1 year ago

e.g. shim out install.packages(), devtools::install_*, remotes::install_*

Add shim to Sys.getenv() that reports when an environment variable is used.

jthomasmock commented 1 year ago

It would be nice to start dry_run() in terms of the deployment will absolutely fail:

But also report on warnings:

Also wanted to note:

Posit Connect will scan your logs for common errors and suggest troubleshooting steps if an error is found. If you have encountered an error that Posit Connect is not detecting or for which Posit Connect is not providing adequate troubleshooting steps, you may wish to contact your administrator or your Posit Support representative.

While there ARE API endpoints for many of the above item, a failed deploy that actually goes through to Connect obviously reports on a lot more. Perhaps it's in scope to summarize the success/failures of the long set of logs?

hadley commented 1 year ago

FWIW the goal is to start with (IMO) the most common problems: missing dependencies and missing env vars.

csgillespie commented 1 year ago

Hi @hadley . We're (Jumping Rivers) are working on something similar just now. With a bit of luck, we'll make it public / open source in the next week or so. Basically, you stick in your API key / server name, and it runs through a bunch of tests. Here's the current output:

``` ── Summary jrHealthCheckConnect v0.3.11 ── ℹ Server: https://rsc.jumpingrivers.cloud/ ℹ Server accessible: ✔ ℹ API KEY: ✔ ℹ rsconnect-python: ✔ ── Checking Server Version ── ℹ Your server is up to date ── Checking Server ── ℹ Status code: 200 ℹ access-control-allow-origin: Header not set (Docs) ℹ content-security-policy: Header not set (Docs) ℹ cookies: No cookies detected ℹ redirection: Redirects to HTTPS ℹ referrer-policy: Header not set (Docs) ℹ strict-transport-security: max_age present, but suggested value is 1 year (Docs) ℹ subresource-integrity: Subresource Integrity not implemented (Docs) ℹ x-content-type-options: Acceptable setting found ℹ x-frame-options: Acceptable setting found ℹ x-xss-protection: Header not set (Docs) ── User Summary ── ℹ Colin Gillespie ℹ Username: colin ℹ Role: administrator ── Checking Connect Users ── ℹ Users: 51 out of 100 ℹ User breakdown: Administrator: 9, Publisher: 18, Viewer: 24 ℹ 9 Administrators: andrew, astrid, colin, jack, josh, liam, martin, seb, and shane ℹ 0 applications owned by locked users ── R/Python/Quarto Versions ── ℹ R: installed (v3.5.3) latest (v3.5.3) ℹ R: installed (v3.6.3) latest (v3.6.3) ℹ R: installed (v4.0.5) latest (v4.0.5) ℹ R: installed (v4.1.3) latest (v4.1.3) ℹ R: installed (v4.2.1) latest (v4.2.3) ℹ R: installed (v4.2.3) latest (v4.2.3) ℹ R: installed (vNA) latest (v4.3.0) ℹ Python: installed (v3.7.13) latest (v3.7.16) ℹ Python: installed (v3.8.13) latest (v3.8.16) ℹ Python: installed (v3.9.13) latest (v3.9.16) ℹ Python: installed (v3.10.4) latest (v3.10.10) ℹ Python: installed (v3.11.1) latest (v3.11.3) ℹ Python: installed (v3.11.2) latest (v3.11.3) ℹ Quarto: installed (v1.2.475) latest (v1.2.475) ℹ Quarto: installed (vNA) latest (v1.3.340) ── Systems Libraries ── ℹ Unable to install 42 CRAN packages ℹ Missing sys_libs: libgpgme11-dev, libgsl0-dev, librdf0-dev, and libxslt-dev ℹ Note: this is not necessarily a bad thing ── Document Deployment Checks ── ℹ Starting check: deploy_git(public-github): Old Faithful ✔ Check finished ℹ Starting check: deploy_pins(rds): Read, write & delete pins ✔ Check finished ℹ Starting check: deploy_plumber(api): Plumber API deployment ✔ Check finished ℹ Starting check: deploy_python(flask): Deploy flask app ✔ Check finished ℹ Starting check: deploy_python(streamlit): Deploy streamlit app ✔ Check finished ℹ Starting check: render_quarto(beamer): Deploying beamer ✔ Check finished ℹ Starting check: render_quarto(docx): Deploying docx ✔ Check finished ℹ Starting check: render_quarto(html): Deploying html ✔ Check finished ℹ Starting check: render_quarto(observable): Deploying observable ✔ Check finished ℹ Starting check: render_quarto(pdf): Deploying pdf ✔ Check finished ℹ Starting check: render_quarto(python): Jupyter engine ✔ Check finished ℹ Starting check: render_quarto(rsvg_convert): Deploying rsvg_convert ✖ Check finished ℹ Starting check: render_rmd(html): Deploying html ✔ Check finished ℹ Starting check: render_rmd(pdf): Deploying pdf ✔ Check finished ℹ Starting check: render_rmd(word): Deploying word ✔ Check finished ℹ Starting check: deploy_shiny(basic_app): Deploy basic app ✔ Check finished ```

This seems to overlap with this issue? However, "our" package is trying to ensure that Connect is working as expected

We also have something similar for RSW

hadley commented 1 year ago

@csgillespie thanks, sounds like that's more about checking your connect instance is ok, not your content?

andpatt commented 1 year ago

sounds like that's more about checking your connect instance is ok, not your content?

For the majority aye, but I think there's a few bits that could crossover here.

There's a few bits that need access to the Connect API to check, but even if you didn't want to get bogged down in that, the following would still be doable:

If you were also willing to interact with the Connect API (Since you're going to need to do the deploy anyway) then I think the following features implemented in the package referenced above would also be useful:

If you wanted to get really involved in making sure that your content would deploy, then you could deploy a tiny plumber API which reads out the output of apt list --installed and cross reference that list against the system libraries needed by the packages your app uses.

But I suspect that's going a bit far for this function 😁

hadley commented 1 year ago

The first two are now more aggressively handled in addServer(), and since we now support redirects, I think the potential for problems after the fact are much slower. We have also have more checks for packages that are unlikely to work on the server, and you're right that restore() should capture the remaining cases.

The others seem ok to leave as server side errors to me as it's not like you can easily resolve the problem of mismatching R versions (which won't often cause problems?) or not having deploy access. Are these problems that you see a lot with users?

andpatt commented 1 year ago

The first two are now more aggressively handled in addServer()

Ah yeah okay true.

The others seem ok to leave as server side errors to me as it's not like you can easily resolve the problem of mismatching R versions (which won't often cause problems?) or not having deploy access.

Yep, don't disagree with that

Are these problems that you see a lot with users?

Yeah they are, but we're generally seeing them when we've first deployed an environment and people are trying to use it with old versions of R they never told us about, or they all used to have a shared admin account to the old Connect and now they all login individually (and some viewers used to be admins, etc)

The R versions thing still occasionally bites users every time we update connect instances (because we remove the oldest minor version when we add a new minor version (with the client's consent!)) but again it's occasional because, as you say, things don't tend to break when using later R versions.

hadley commented 1 year ago

@andpatt hmmmm, maybe a sitrep() method would be a useful addition to rsconnect? That could give you that basic info for different servers.