rsconnect icon indicating copy to clipboard operation
rsconnect copied to clipboard

writeManifest does not work with renv profiles

Open tomjemmett opened this issue 1 year ago • 3 comments

In computePackageDependencies the check for whether an renv.lock file exists only checks for a file in the bundleDir. If you are using renv profiles the check returns FALSE, so it falls back to the case of trying to create a new renv lock file.

It would be nice if writeManifest could accept as an argument the name of an renv profile to use, or automatically detect the currently active renv profile.

Locally, I've monkey-patched renvLockFile to return the path to the profile in use in my specific project. This seems to work and successfully generates the manifest.json file for me

assignInNamespace(
  "renvLockFile",
  \(...) "renv/profiles/dev/renv.lock",
  "rsconnect"
)

tomjemmett avatar Feb 01 '24 10:02 tomjemmett

Background:

When renv has a default profile, it writes the name of that profile to renv/profile. This indicates that the renv/profiles/{NAME}/renv.lock is in use. Alternatively, the RENV_PROFILE environment variable can name the active profile.

rsconnect should consume the renv.lock associated with the active profile.

renv does not appear to have public functions which expose the name of the active profile or lock file.

It has internal functions:

  • renv:::renv_profile_get() returns NULL or the name of the profile.
  • renv:::renv_profile_prefix() returns NULL or the path to the renv directory for the profile.

@kevinushey - Do you have thoughts about how to best consume the renv.lock for the active renv profile from rsconnect? Should we rely on renv:::renv_profile_get() as a public interface? Will we always have a project renv.lock (default profile) when there are named renv profiles?

aronatkins avatar Feb 26 '24 21:02 aronatkins

renv does not appear to have public functions which expose the name of the active profile or lock file.

There is this:

> Sys.setenv(RENV_PROFILE = "test")
> renv::paths$lockfile()
[1] "/Users/kevin/r/pkg/renv/renv/profiles/test/renv.lock"

Maybe we should create and export lockfile_path(), as a companion to the other existing lockfile functions?

That said, the RENV_PROFILE environment variable is the de-facto source of truth for the active profile.

Will we always have a project renv.lock (default profile) when there are named renv profiles?

It's possible that you could have project-specific lockfiles available without any default lockfile, although that might be rare in theory.

kevinushey avatar Feb 27 '24 20:02 kevinushey

Although sometimes I want the renv.lock for my current active profile in my current project, there's also times where I'm currently in an renv and writing a manifest for a different project (or maybe want to specify a different profile, without reloading the project in that profile). In that case, I don't want it to use my active renv.lock, I want to use the renv.lock of my choosing.

Here's a possibility: if we add a renvLockFile arg to writeManifest() with the following signature, it'd be backward compatible with the current behavior:

writeManifest(
  appDir = getwd(),
  ...
  renvLockFile = file.path(appDir, "renv.lock")
)

But then it'd still allow me to call: writeManifest(renvLockFile = renv::paths$lockfile() if I wished to use the current profile.

It's possible that you could have project-specific lockfiles available without any default lockfile, although that might be rare in theory.

I have a project with a setup like this! I have lockfiles for each environment the app needs to run & develop on, but by default it doesn't use renv (so no renv.lock in the project root)

khusmann avatar May 21 '25 21:05 khusmann