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

Respect renv lockfiles #791

Merged
merged 57 commits into from
May 8, 2023
Merged

Respect renv lockfiles #791

merged 57 commits into from
May 8, 2023

Conversation

hadley
Copy link
Member

@hadley hadley commented Mar 21, 2023

@aronatkins and @kevinushey: this is still an early draft, but I thought it would be useful to get some feedback now that I've put a couple of hours into it. It still needs a bunch of testing, and I doubt i have all the details of the renv -> packrat translation are fully correct yet, but this overall this feels like a solid approach to me. What do you think?

Fixes #671. Fixes #809.

R/bundleFiles.R Show resolved Hide resolved
NEWS.md Outdated Show resolved Hide resolved
R/bundleFiles.R Show resolved Hide resolved
R/renv.R Outdated Show resolved Hide resolved
R/renv.R Outdated Show resolved Hide resolved
R/renv.R Outdated Show resolved Hide resolved
R/renv.R Outdated Show resolved Hide resolved
Copy link
Contributor

@aronatkins aronatkins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we renv->manifest rather than renv->packrat->manifest?

NEWS.md Outdated Show resolved Hide resolved
R/renv.R Outdated Show resolved Hide resolved
@hadley hadley requested review from aronatkins and kevinushey April 22, 2023 13:31
@hadley
Copy link
Member Author

hadley commented Apr 22, 2023

I'm still fighting some buglet with BioC packages. In a project that uses Biobase, I get the following error:

# Installing required R packages with `packrat::restore()` ---------------------
Installing BiocGenerics (0.44.0) ... 
Using cached BiocGenerics.
	OK (symlinked cache)
Installing BiocManager (1.30.18) ... 
Using cached BiocManager.
	OK (symlinked cache)
Installing BiocVersion (3.16.0) ... 
curl: HTTP 200 https://bioconductor.org/packages/3.16/data/annotation/src/contrib/PACKAGES.rds
curl: HTTP 200 https://bioconductor.org/packages/3.16/data/experiment/src/contrib/PACKAGES.rds
curl: HTTP 200 https://bioconductor.org/packages/3.16/bioc/src/contrib/PACKAGES.rds
curl: HTTP 200 https://bioconductor.org/packages/3.16/workflows/src/contrib/PACKAGES.rds
curl: HTTP 200 https://colorado.posit.co/rspm/all/latest/src/contrib/PACKAGES.rds
curl: HTTP 404 https://bioconductor.org/packages/3.16/data/annotation/src/contrib/Archive/BiocVersion/BiocVersion_3.16.0.tar.gz
curl: (22) The requested URL returned error: 404 Not Found
curl: HTTP 404 https://bioconductor.org/packages/3.16/data/annotation/src/contrib/Archive/BiocVersion/BiocVersion_3.16.0.tar.gz

The manifest looks ok to me:

    "BiocVersion": {
      "Package": "BiocVersion",
      "Version": "3.16.0",
      "Source": "Bioconductor",
      "Repository": "https://bioconductor.org/packages/3.16/bioc",

I suspect there's some small mistake that will hopefully be obvious when I look at it on Monday.

R/writeManifest.R Outdated Show resolved Hide resolved
@hadley
Copy link
Member Author

hadley commented May 2, 2023

BioC install problem was caused by colorado only having 4.1 installed. Works on rstudioservices.

Copy link
Contributor

@toph-allen toph-allen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, I think this change makes sense, especially because packrat is itself using a vendored version of renv to snapshot dependencies.

It seems like a lot of the complexity here is within the blocks that standardize the different ways packrat, renv, and pak record package metadata, as well as assumptions they make about packages that aren't just structural differences (and how these have evolved over time). I appreciate having links to the relevant source in the comments. (The one that stood out to me was the check for isDevVersion()).

The Bitbucket name capitalization is the only required change I noticed. But I only noticed it because I spent long enough with Bitbucket when I was implementing support for restoring those packages in Connect. We'll probably want to do some real-world tire-kicking of those sorts of scenarios in case there are other small things like that we missed. Either that or build out more examples in tests.

R/bundlePackageRenv.R Outdated Show resolved Hide resolved
tests/testthat/test-bundlePackageRenv.R Outdated Show resolved Hide resolved
R/bundlePackagePackrat.R Outdated Show resolved Hide resolved
Copy link
Contributor

@aronatkins aronatkins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some questions about package+repository handling, but this is probably far enough along to merge and get folks to start actively using it.

#' 2. Otherwise, rsconnect will call `renv::snapshot()` to find all packages
#' used by your code. If you'd instead prefer to only use the packages
#' declared in a `DESCRIPTION` file, run
#' `renv::settings$snapshot.type("explicit")` to activate renv's "explicit"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think that folks will need an explicit snapshot type for deploys and another snapshot type for all other workflows? Put another way: Do we need a way to toggle the snapshot type just for deploys?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renv::snapshot() does accept a type argument so this would be straightforward to wire up, at least.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My sense is that once we enable support for renv lockfile, we'll get quite a few feature requests so we might as well just let them accumulate for a while to get a sense for what people actually want, rather than doing too much prospectively.

R/appDependencies.R Show resolved Hide resolved
@@ -179,7 +179,7 @@ ignoreBundleFiles <- function(dir, contents) {
# rsconnect packages
"rsconnect", "rsconnect-python", "manifest.json",
# packrat + renv,
"renv", "renv.lock", "packrat",
"renv", "packrat",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The renv/settings.json isn't included; does this mean that a snapshot.type set in a previous session will not be available?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but I don't think that should matter because the settings only really affect interactive usage, and the consequence of those settings will be encoded in the lockfile.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The recommendation to use renv::settings$snapshot.type("explicit") presents a challenge, then, if we expect folks to set that ahead of each deploy operation but do so in a way that does not modify their existing renv project settings. What is your suggested workflow?

packages_list <- lapply(seq_len(nrow(packages)), function(i) {
out <- as.list(packages[i, , drop = FALSE])
# Manifest packages used to generate packrat file on Connect
# https://github.com/rstudio/connect/blob/v2023.03.0/src/connect/manifest/convert.go#L261-L320
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This is an internal source reference.

@@ -179,7 +179,7 @@ ignoreBundleFiles <- function(dir, contents) {
# rsconnect packages
"rsconnect", "rsconnect-python", "manifest.json",
# packrat + renv,
"renv", "renv.lock", "packrat",
"renv", "packrat",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this cause renv.lock to be included in the bundle?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes; that's necessary so that we can process it in bundlePackages(). Do you foresee a problem with including this in the deployed bundle? If so, I can delete. (But I think you could also renv::restore() directly from that file without having to convert the manifest back into a packrat spec).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am torn on this one.

On the one hand, including only the manifest.json in the bundle is quite nice because it means we have a single source-of-truth. Folks have been confused by the presence of both manifest.json and packrat.lock in our bundles, as well as the relationship between the two (and duplication of information).

On the other hand, I like including the renv.lock, as it gives us a future option of directly using that file without reconstructing it from the manifest.

Mostly, my struggle is that I had thought about this change as "manifest-only, no packrat.lock" rather than "manifest plus renv.lock; except when we create the renv.lock on the fly".

Let's go forward with the (sometimes) inclusion, but probably document the change.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like it would be a bit more consistent to include lock file, even when we generate it? I'm currently explicitly deleting it, but it seems reasonable to remove that code and preserve the lock file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A generated lock file isn't on the set of "bundle files" that was computed much earlier in the workflow... I'm OK either way, but if we do include a generated lock file, let's include it only when we have tracked dependencies (e.g. not for static).

} else {
# $Repository comes from DESCRIPTION and is set by repo, so can be
# anything. So we must look up from the package name
pkg$Repository <- findRepoUrl(pkg$Package, availablePackages)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: during restore, renv first favors a matching repository name before falling back to "any" repository. not sure if we want that same pattern here or want to rely available.packages order like we do for Packrat.

Maybe this is: prefer the Repository named in renv.lock and prefer available.packages for snapshots.

Also worth considering: Should we prefer the renv.lock repository list or the list in the current R session?

https://github.com/rstudio/renv/blob/81fecb07fcc78cabb61b5309875e59484727b090/R/retrieve.R#L875-L880

Copy link
Contributor

@kevinushey kevinushey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM!

DESCRIPTION Outdated
@@ -28,13 +28,15 @@ Imports:
lifecycle,
openssl (>= 2.0.0),
packrat (>= 0.6),
renv,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if you need it for this PR, but if you'd like to depend on renv internals without risking breakage from new renv releases, you can also use renv::embed() to embed a local copy of renv here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related thought: Do we need a version constraint on renv?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to embed because we're only using exported functions so far, but will keep it in mind for the future.

I've add a requirement for the latest version from CRAN.

#' 2. Otherwise, rsconnect will call `renv::snapshot()` to find all packages
#' used by your code. If you'd instead prefer to only use the packages
#' declared in a `DESCRIPTION` file, run
#' `renv::settings$snapshot.type("explicit")` to activate renv's "explicit"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renv::snapshot() does accept a type argument so this would be straightforward to wire up, at least.

R/bundlePackagePackrat.R Outdated Show resolved Hide resolved
local_version <- record$Version
repo_version <- availablePackages[record$Package, "Version"]

package_version(local_version) > package_version(repo_version)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also detect whether the trailing version component is "large"? In case a local version is 1.0.0-9000 but CRAN has 1.0.1?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not a version used by every package, so I worry that would dilute the impact of this change.

R/bundlePackageRenv.R Show resolved Hide resolved
R/bundlePackageRenv.R Outdated Show resolved Hide resolved
R/bundlePackageRenv.R Outdated Show resolved Hide resolved
R/utils.R Show resolved Hide resolved
@hadley
Copy link
Member Author

hadley commented May 3, 2023

I think this is done, and I've finally managed to knock of the CI failure. Unless anyone spots any problems, I'll aim to merge tomorrow.

Copy link
Contributor

@toph-allen toph-allen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looked through the changes since my last review, and they all look good.

@hadley hadley merged commit 003fdae into main May 8, 2023
@hadley hadley deleted the renv-support branch May 8, 2023 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
6 participants