rstudio / renv

renv: Project environments for R.

Home Page:https://rstudio.github.io/renv/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

should `init()` gitignore the project's `.Renviron` ?

arthur-shaw opened this issue · comments

Let's imagine that a project wants to store secrets in a project-level .Renviron file as discussed here. Are there any renv functions that gitignore the project-level .Renviron file so that the secrets it contains don't get commited by accident?

If there aren't any functions that do this as a file-system side-effect, would it make sense to do this on the user's behalf, perhaps through a safety-oriented default that can be changed by the user as needed (e.g., renv::init(ignore_renviron = TRUE))?

To unpack this idea bit more, I don't see any guardrails to prevent leaking secrets stored in a project-level .Renviron. Here's some pseudo-code for project setup steps that I could imagine folks would follow:

# instantiate a project
usethis::create_project("foo_bar_baz")

# set up renv
renv::init()

# set project-level secrets as environment variables while in the project session
usethis::edit_r_environ(scope = "project")

# remember to gitignore `.Renviron` but share secrets with team via some other safe means
# maybe run `usethis::edit_gitignore()` or directly editing `.gitignore`
# if secrets nevertheless get committed, panic and `git reset --hard HEAD`

This seems reasonable, but I think this is outside of renv's purview. Can you elaborate on why you think this should be renv's responsibility?

That's a great question. Indeed, I hesitated about where to post this issue.

My main rationale is that renv, more so than other packages, deals with capturing and managing project environments, and .Renviron is a piece of the project environment. Another piece is that if folks are using project-specific .Renviron files, renv is a likely touch point in their process of capturing the project environment and sharing that reproducible environment with others (or putting it into production). Hence, if renv is either a go-to tool for adjacent problems, perhaps it would be good place to help users put in place guardrails so that the safe parts of the project environments are tracked (e.g., R version, packages, package versions) and the dangerous parts are ignored (i.e., .Renviron that may contain secrets).

My counter-argument is that this problem is somewhat orthogonal to what I understand renv to be doing. While renv does some things with .Renviron (e.g., renv.config.user.environ), my understanding is that it doesn't do much (yet).

Also, perhaps there are other packages that should deal with this issue instead. My first thought is usethis--for example, having, usethis::create_package() gitignore any project-level .Renviron. That function already creates a project-level .gitignore and could simply add a line to ignore .Renviron.

So, I guess the question is where in the project setup process is best to ignore project-level .Renviron files. If one wants to aim large (at the risk of confusing users), perhaps usethis::create_project() is the right place. If one wants to target users that are probably most apt to come up against this problem, perhaps renv is the right place.

If not renv, what other pacakges would be a good, natural place for this functionality?

Also, perhaps there are other packages that should deal with this issue instead. My first thought is usethis--for example, having, usethis::create_package() gitignore any project-level .Renviron. That function already creates a project-level .gitignore and could simply add a line to ignore .Renviron.

I think I agree with this -- usethis::use_package() could ask the user whether they'd like to include the project .Renviron in the .gitignore file on startup.

I think part of the challenge here is that I could see reasons to include the .Renviron in some cases too -- for example, you might have project-specific environment variables that are not sensitive, and could / should be shared with the project. (For example, you're sharing this project with collaborators, and you'd like to make sure those collaborators have the same environment variables set in their session.)

To wit -- I wonder if .Renviron / .Rprofile are really the right place for credentials? It feels like these should be read and managed separately of any project files...

You make some good points. I think I agree with both.

For the question of which package should gitignore the project-specific ,Renviron, I think we're both agreed that usethis would be a good candidate.

For the question of whether .Renviron is the best vehicle for storing secrets, I think I'm sold that while .Renviron could serve this purpose, it might not the best approach. If .Renviron only contains secrets, gitignoring it makes sense. If .Renviron includes other things, then it's best not to gitignore it.

However, I'm not entirely sure what the best approach is for cases where one would like to share a project and its environment--notably including (API) secrets--with other collaborators.

I see a few packages developed by Posit that might scratch this itch:

Whether in its professional products or in the advice it gives to clients, does Posit have a preferred approach for managing API secrets in shared project--or one (key)ring to rule them all?