├── practical-renv.pdf ├── .gitignore └── README.md /practical-renv.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shannonpileggi/practical-renv/HEAD/practical-renv.pdf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # History files 2 | .Rhistory 3 | .Rapp.history 4 | 5 | # Session Data files 6 | .RData 7 | .RDataTmp 8 | 9 | # User-specific files 10 | .Ruserdata 11 | 12 | # Example code in package build process 13 | *-Ex.R 14 | 15 | # Output files from R CMD build 16 | /*.tar.gz 17 | 18 | # Output files from R CMD check 19 | /*.Rcheck/ 20 | 21 | # RStudio files 22 | .Rproj.user/ 23 | 24 | # produced vignettes 25 | vignettes/*.html 26 | vignettes/*.pdf 27 | 28 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 29 | .httr-oauth 30 | 31 | # knitr and R markdown default cache directories 32 | *_cache/ 33 | /cache/ 34 | 35 | # Temporary files created by R markdown 36 | *.utf8.md 37 | *.knit.md 38 | 39 | # R Environment Variables 40 | .Renviron 41 | 42 | # pkgdown site 43 | docs/ 44 | 45 | # translation temp files 46 | po/*~ 47 | 48 | # RStudio Connect folder 49 | rsconnect/ 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # practical {renv} 2 | 3 | A posit::conf(2025) talk. 4 | 5 | # abstract 6 | 7 | The {renv} package aims to *help* users create reproducible environments for R projects. In theory, this is great! In practice, restoring a package environment can be a frustrating process due to overlooked R configuration requirements. Join me to better understand the source of environment restoration issues and learn strategies for successful maintenance of {renv}-backed projects. 8 | 9 | # slides 10 | 11 | Made in google slides. [practical-renv.pdf](practical-renv.pdf) 12 | 13 | * text `#E8E9F0`; background `#30304B`; accent `#C3D350` 14 | 15 | * [pudgy penguin gifs](https://giphy.com/pudgypenguins) from GIPHY 16 | 17 | # background 18 | 19 | * {packrat} 20 | 21 | + Sep 2014 {packrat} 0.4.1 first released to CRAN 22 | 23 | + Sep 2023 {packrat} 0.9.2 last release 24 | 25 | + {packrat} has been soft-deprecated and is now superseded by {renv}. 26 | 27 | * {renv} 28 | 29 | + Oct 2019 v0.8.0 released to CRAN 30 | 31 | + Jul 2023 [v1.0.0](https://github.com/rstudio/renv/releases/tag/v1.0.0) released 32 | 33 | - May 2023 substantial documentation updates 34 | 35 | + Jan 2025 v1.1.0 released 36 | 37 | # related talks 38 | 39 | * rstudio::conf(2020), Kevin Ushey, [renv: Project Environments for R](https://youtu.be/yjlEbIDevOs?si=xGEZ3NDMfclwNzf7) 40 | 41 | * rstudio::conf(2022), E. David Aja, [You should use renv](https://www.youtube.com/watch?v=GwVx_pf2uz4) 42 | 43 | * posit::conf(2025), Shannon Pileggi [practical {renv}](https://www.youtube.com/watch?v=l01u7Ue9pIQ&t=2s) 44 | 45 | # tips 46 | 47 | These are tips that I did not have the time to include in the presentation. 48 | 49 | ## general tips 50 | 51 | 1. Manage expectations when using {renv}. Keep in mind that {renv} is a tool that falls in the middle of the reproducibilty spectrum; accordingly, there is user responsibility to ensure package installation requirements are met. 52 | 2. The happy path is to update R and packages regularly. 53 | 3. Keep projects small in scope. 54 | + When you update R and packages, test everything to make sure it still works without error. More items to test means more possible failure points. 55 | + More package dependencies could also potential points of failure in {renv} restoration. 56 | 5. Install binaries when available to speed up installation and reduce complications from source installation. 57 | 58 | ## non-{renv} tips 59 | 60 | 1. You can install/use multiple R versions and switch as needed for different projects. Consider [rig](https://github.com/r-lib/rig) to manage your R versions. 61 | 62 | 2. Use the `SETUP` interface on p3m at <[https://packagemanager.posit.co/client/#/](https://packagemanager.posit.co/client/#/repos/cran/setup)> to retrieve the URL for your operating system, 63 | snapshot date, and environment. 64 | 65 | 3. Set your default repository for package installation to p3m. You can add multiple repositories. This url is for latest package versions on Windows. 66 | 67 | -> `usethis::edit_r_profile()` 68 | 69 | -> in .Rprofile, add `options("repos" = c("p3m" = "https://packagemanager.posit.co/cran/latest"))` 70 | 71 | 4. Inspect the packages installed in your libraries 72 | 73 | + names only `lapply(.libPaths(), list.files)` 74 | 75 | + data frame with full details 76 | 77 | ``` 78 | df_pkg <- lapply(.libPaths(), \(x) as.data.frame(installed.packages(x))) |> 79 | tibble::enframe() |> 80 | tidyr::unnest(cols = c(value)) 81 | ``` 82 | 83 | 5. Check if you can compile packages from source with [`pkgbuild::check_build_tools()`](https://pkgbuild.r-lib.org/reference/has_build_tools.html). Another handy function that returns more details about your system setup is [`devtools::dev_sitrep()`](https://devtools.r-lib.org/reference/dev_sitrep.html). 84 | 85 | 5. Watch the [Personal R Administration](https://www.youtube.com/watch?v=m2eihAhl8so) workshop from the 2025 R in Medicine conference for more details on these topics. 86 | 87 | ## factors that can affect {renv} behavior 88 | 89 | 1. {renv} version 90 | 2. configured repositories 91 | 3. whether or not packages are already installed vs not yet installed in system library / cache. 92 | 93 | ## {renv} tips 94 | 95 | 1. The location of the global cache has changed with different versions of {renv}. This can lead to confusing results/messaging if you are switching between {renv} versions (e.g., seeing that a package is not installed but you thought it was). 96 | 97 | 2. You should probably use {renv} ≥ v1.1.0. 98 | 99 | 3. `renv::upgrade()` is expected to work for {renv} versions ≥ 1.0.1. To upgrade from prior versions of {renv}, users should 100 | ``` 101 | renv::deactivate() 102 | install.packages("renv") 103 | renv::activate() 104 | renv::record("renv") 105 | ``` 106 | 107 | 4. The default mode for capturing package dependencies is implicit, in which `renv::dependencies()` parses all .R, .Rmd, .qmd and DESCRIPTION files for packages used. This can lead to slow project start up or restart up if there are many files to scan. You can change this to [explict](https://rstudio.github.io/renv/articles/faq.html?q=explicit#capturing-explicit-dependencies), which captures dependencies in the `DESCRIPTION` file only (no longer parses files). 108 | 109 | 5. `renv::checkout()` is recommended for use after 2023-07-07 (v1.0.0 of {renv}, when the checkout function was released). Note that using `renv::checkout(date = "xxxx-xx-xx")` also forces the version of {renv} to be latest available at that date. 110 | 111 | 6. [`renv::restore()`](https://rstudio.github.io/renv/reference/restore.html) has a lot of arguments. Read the help file! In particular, if you suffer from a time consuming installation in which one single package fails and you have to start over with all of your installations, try `renv::restore(transactional = FALSE)`. 112 | 113 | 7. You can see different installation behaviors depending on the version of {renv} and whether or not your cache has any version of that package populated vs no version at all of that package. 114 | 115 | 8. When all else fails, force installation of latest versions. 116 | ``` 117 | pkgs <- renv::lockfile_read("renv.lock") 118 | install.packages(names(pkgs$Packages)) 119 | ``` 120 | 121 | ## resume project: decisions 122 | 123 | 1. "freeze" packages (maintain package versions) 124 | ``` 125 | # 3 options ---- 126 | # install package versions from repository specified in lockfile 127 | renv::restore() 128 | 129 | # install package versions from P3M 130 | renv::restore(repos = c("P3M" = "https://packagemanager.posit.co/cran/latest")) 131 | 132 | # install date-based package versions from P3M 133 | renv::checkout(date = "2025-02-01") 134 | ``` 135 | 136 | 2. "manage" packages (one off package upgrades) 137 | ``` 138 | # 2 steps ---- 139 | # install latest package version from repository specified in lockfile 140 | renv::install("jsonlite") 141 | renv::snapshot() 142 | ``` 143 | 3. update packages (bring all packages to latest versions) 144 | ``` 145 | # 3 steps ---- 146 | # use latest version of renv 147 | renv::upgrade() 148 | 149 | # install all latest package versions 150 | renv::install() 151 | 152 | # record changes to both R version and package versions in lockfile 153 | renv::snapshot() 154 | ``` 155 | 156 | # example projects 157 | 158 | I created two example projects to demonstrate resuming projects over time. Both have the package repository set to CRAN at . 159 | 160 | | | project | R version | {renv} version | package | simulated initialization date | 161 | | - | -----------------------------------------------------------------------| --------- | -------------- | ------------- | ----------------------------- | 162 | | 1 | [glue-example](https://github.com/shannonpileggi/glue-example) | 4.3.1 | 1.0.0 | glue 1.6.2 | 2023-08-01 | 163 | | 2 | [jsonlite-example](https://github.com/shannonpileggi/jsonlite-example) | 4.4.2 | 1.1.0 | jsonlite 1.8.9 | 2025-02-01 | 164 | 165 | I intially started working with the {glue} example. However, enough changed between the 1.0.0 and 1.1.0 release of {renv} to substantially complicate the presentation. 166 | As {glue} has few releases, {jsonlite} ended up being a better package to demonstrate changes over time that line up with more recent {renv} releases. However, it may 167 | have also been a poor example choice as {jsonlite} is listed as a "Suggests" for {renv}. 168 | 169 | # project playground 170 | 171 | I experimented with {renv} on both my local Windows computer and in docker containers. 172 | 173 | ``` 174 | docker run --rm -ti -e DISABLE_AUTH=true -p 127.0.0.1:8787:8787 rocker/rstudio:4.5.1 175 | ``` 176 | 177 | Open `localhost:8787` in browser to see RStudio interface. 178 | 179 | ``` 180 | git clone https://github.com/shannonpileggi/jsonlite-example 181 | ``` 182 | 183 | # contributions welcome 184 | 185 | Other tips you want to add or anything else? Feel free to create an issue. 186 | --------------------------------------------------------------------------------