-
Notifications
You must be signed in to change notification settings - Fork 3
/
renv.Rmd
119 lines (76 loc) · 6.62 KB
/
renv.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# Control dependencies with `renv`
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, collapse = TRUE, eval = FALSE)
```
For production readiness --- and project safety --- it is important to control the dependencies of a piece of development. This can be done at project level using the package [`renv`](https://rstudio.github.io/renv/).
In an `renv` project, dependencies are resolved and tracked in a lock-file. As a new R session starts, `renv` detects whether installed dependencies are out of sync compared to the lock-file, ensuring the same virtual environment applies each time the project is opened.
This approach ensures that the set of dependencies is collaboratively shared and maintained. Moreover, it can be used to align the development environment to the production stage. Managing and controlling dependencies all the way up from development to production improves reproducibility and empowers automated deployments, a key requirement in enterprise.
Finally, as the control is at project level, it is possible to have different virtual environments (with different packages version) for different projects, while keeping the maintenance of the versioned package library efficient through caching.
## Install `renv`
`renv` can be installed from CRAN as:
```{r, echo = TRUE, eval = FALSE}
install.packages("renv")
```
## Set-up an `renv` project
In order resolve and track dependencies of a project, `renv` needs to discover what the required packages are. Although `renv` supports discovering dependencies by scanning all files in the project (_implicit mode_), we strongly advise to define the required dependencies in a `DESCRIPTION` file, and rely on `renv`'s _explicit mode_ (see ['Snapshot types'](https://rstudio.github.io/renv/reference/snapshot.html#snapshot-types) in the documentation for details).
To initialize `renv` for a project where dependencies are explicitly stated in the `DESCRIPTION` file, run:
```{r, echo = TRUE, eval = FALSE}
renv::init(settings = list(snapshot.type = "explicit"))
```
This ensures that the dependencies of the projects, listed in the `DESCRIPTION` file, are considered for initializing the virtual environment.
The `renv` initialization causes:
- the creation of the lock-file `renv.lock`, which tracks the version of the resolved transitive package dependencies, along with the R version and package repositories information;
- the set-up of `renv` infrastructure for the project including a specific library, where packages are installed at the versions tracked in `renv.lock`;
- the creation of a new `renv` folder containing:
- a settings file `settings.json`,
- a script `activate.R` to activate the project-specific virtual environment;
- the inclusion of the activation script in `.Rprofile`, which ensures activation upon session start in the project;
- an update of the `.Rbuildignore` because the `renv`-specific files are not part of the R package infrastructure;
Note that, by default, `renv` will use the repository from **Posit Public Package Manager** (_PPM_) CRAN mirror for package installation.
Having all the `renv` infrastructure committed under version control ensures that the same `renv` set-up and environment is available to anyone working on the same project.
Upon session startup, `renv` would detect mismatches between the package versions recorded in `renv.lock` and those installed in the project library, hinting at actions to ensure consistency. In particular,
```{r, echo = TRUE , eval = FALSE}
renv::status()
```
would check and provide information about packages whose version is out-of-sync, whereas
```{r, echo = TRUE , eval = FALSE}
renv::restore()
```
would restore the versions as listed in `renv.lock`, and is the go-to command to ensure the local environment is always aligned with the locked dependencies.
### Development dependencies
By default, development dependencies (like those specified under `Suggests:` in the `DESCRIPTION` file), are not included in `renv.lock`. They can be however included via
```{r, echo = TRUE, eval = FALSE}
renv::snapshot(dev = TRUE)
```
Note that, given the default behavior with respect to development dependencies, `renv` might report out-of-sync dependencies upon session startup. Make sure to use
```{r, echo = TRUE, eval = FALSE}
renv::status(dev = TRUE)
```
if you are included development dependencies in `renv.lock`.
Given that only packages _explicitly_ mentioned in the `DESCRIPTION` file are taken care of by `renv`, additional packages used for development, such as `devtools` or `usethis`, should be installed for the specific project via `install.packages()` or `renv::install()`, and are never included in the lock-file.
### Control package versions
If the `DESCRIPTION` file does not request a specific package version, `renv` will use the latest version in the repository, which is always the case for indirect/transitive dependencies. Although the locking mechanism allows to freeze such versions, it might be desirable to have a stricter control over the versions of packages used in a project. To do so, one can leverage the **date-based CRAN snapshots** provided by PPM, e.g.
```{r , echo = TRUE, eval = FALSE}
# Install all dependencies from a specific CRAN snapshot date on PPM
options(repos = "https://packagemanager.posit.co/cran/2024-01-02")
```
Date-based CRAN snapshots have built-in support in `renv` with [`renv::checkout()`](https://rstudio.github.io/renv/reference/checkout.html), w/o the need for `(options(repos = ...))`:
```{r , echo = TRUE, eval = FALSE}
# check out packages from PPM using the date '2023-01-02'
renv::checkout(date = "2024-01-02")
# or provide the repos URL explicitly
renv::checkout(repos = "https://packagemanager.posit.co/cran/2024-01-02")
```
By default, `renv::checkout()` would ensure packages in the project library are installed from the specific date, w/o updating `renv.lock`. This implies you will have to run `renv::snapshot()` to updated the lock-file. As an alternative, you could use the `actions` argument to control the behavior of `renv::checkout()`. In particular,
```{r , echo = TRUE, eval = FALSE}
renv::checkout(date = "2023-01-02", actions=c("snapshot", "restore"))
```
would install packages and lock the corresponding versions (as well as the used repository) at the same time.
Note that `renv::checkout()` can also be use for a subset of packages (and their transitive dependencies)
```{r , echo = TRUE, eval = FALSE}
renv::checkout(packages = "dplyr", date = "2024-01-02")
```
## Removing the `renv` setup from a project
If you would like to remove the `renv` set-up from a project:
- run `renv::deactivate()` to fall back on an `renv`-free set-up;
- delete `renv.lock` and the `renv` folder.