-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
533 additions
and
0 deletions.
There are no files selected for viewing
14 changes: 14 additions & 0 deletions
14
_freeze/posts/2024-01-11_using_renv_with_blog/index/execute-results/html.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"hash": "152291ad15dffa8a6addf906d9880f7d", | ||
"result": { | ||
"markdown": "---\ntitle: \"Documenting blog posts with renv\"\ndescription:\n One solution to the 'ack I can't re-knit my post' problem\ndate: 2024-01-11\ndate-modified: today\nimage: https://i.giphy.com/W69vZGazsH2LDnKCzY.webp\ncitation:\n url: 2024-01-11_using_renv_with_blog\nlang: en\ncategories:\n - R\n - blogging\n - reproducibility\n---\n\n\n\n\n## TL;DR\n\nI show how to use the `renv::use()` function to document the R packages used to write a blogpost.\n\n## Help, I've fallen and I can't re-knit my post!\n\nOne perennial issue with blogging about R^[Technically this applies to blogging about anything that includes running code, but this is a blog about R so that's what you get] is that the blogger may find themselves unable to run the code in a particular post after some time has passed due to package updates that break the code.\nI call this the \"I can't re-knit my post\" problem.\n\nThere have been various solutions proposed to this vexing problem, including:\n\n1. [Freezing post computations using Quarto](https://quarto.org/docs/websites/website-blog.html#freezing-posts)\n2. [Writing the post as a static Markdown file](https://clauswilke.com/blog/2020/09/08/a-blogdown-post-for-the-ages/)\n3. [Using `renv` to maintain one R package library per post](https://www.rostrum.blog/posts/2022-03-15-renv-profiles/)\n\nI think Approach 1 (freezing the post) is the most straightforward solution to prevent unintended knit failures, but that does not document the packages used, so it does not help with actually re-running the code later.\n\nI tried [a variant of Approach 3](https://github.com/djnavarro/refinery) (one `renv` library per post) previously, but found that it was easy to get confused between different `renv` environments, and it ended up being more trouble than it was worth.\n\n## Using `use()`\n\nHere, I suggest a simple solution based on the [`use()` function](https://rstudio.github.io/renv/articles/use.html) from the [`renv` package](https://rstudio.github.io/renv/index.html), as suggested by that package's author, [\\@kevinushey](https://github.com/kevinushey).\nI take the liberty of copying some of the `use()` documentation here (but I recommend you [read the whole thing](https://rstudio.github.io/renv/articles/use.html) anyways)^[I also couldn't help but borrow the vignette title. Thanks [\\@kevinushey](https://github.com/kevinushey)!].\n\n`renv::use()` takes a list of packages and their versions, then:\n\n- Automatically downloads the requested packages\n- Installs the requested packages (plus their recursive package dependencies) to a temporary library path\n- Activates that library path, so that it's used subsequently in the script\n\nBasically, instead of maintaining a per-project package library, it **re-creates the library for a single script^[You might think this means it would take a terribly long time to start up the session each time you work on the script, but thanks to `renv`'s caching mechanism, it actually is quite fast after the first time]**.\n\n## Workflow\n\nFirst, some setup: if you use `renv` for your overall website, I recommend telling `renv` to ignore any scripts in the folder where you store your blog posts, since those will get documented on a per-post basis.\nFor example, if your blog post folder is called `posts`, add `posts` to the `.renvignore` file in the root of your project:\n\n```\nposts\n```\n\nThis allows us to have multiple, independent `renv.lock` files within a single website project without complete chaos.\n\nThe rest of the workflow goes like this:\n\n1. Create blog post, for example, `./posts/2024-01-11_my_post/index.qmd`.\n2. Open that post folder in its own instance of VScode or RStudio (so that your working directory is `./posts/2024-01-11_my_post/`).\n3. Write post, including code chunks.\n4. Run `renv::snapshot()`. This will write `./posts/2024-01-11_my_post/renv.lock`, but **will not modify `.Rprofile`** or create a project library.\n5. Include the line `renv::use(lockfile = \"renv.lock\")` in the setup chunk of your post (or a chunk at the very top with `#| include: false`).\n6. Go back to your main website project and run `quarto render` or `quarto preview` to knit the post. Your post will use the package versions stored in the lockfile for that post.\n7. If you need to update the post, repeat steps 2--4, and render again.\n\n## Example\n\nThis post hasn't used any code yet, so here is some by way of example.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(minimal) # my package for testing, which you probably don't have installed\nlibrary(digest)\n\ndigest(pi)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"6f6167522f32e131f999273c788e4930\"\n```\n:::\n:::\n\n\nI have gone through the workflow steps above and added the call to `renv::use()`.\nPlease have a look at the [source code of this blog post](https://github.com/joelnitta/joelnitta-home/tree/main/posts/2024-01-11_using_renv_with_blog/index.qmd) to see how this works.\n\n## Conclusion\n\nI like this approach because we don't actually create multiple `renv` projects, so we can avoid headaches related to project-switching (though you still need to use different working directories).\n\nOne downside is that given enough time, it may no longer be possible to install the R packages at their specified versions again.\nHowever, perhaps this isn't such a problem after all: it means whoever is trying to run your code most likely also cannot install the packages, so your post needs to be updated!\n\nAnother plus is that we can include an [appendix](#reproducibility) at the end of each post linking to the `renv.lock` file so any interested reader can see what package versions were used.\n\nFinally, this should be used in conjunction with the [freeze](https://quarto.org/docs/websites/website-blog.html#freezing-posts) functionality of Quarto to control when each post gets rendered.\n\nHappy blogging!\n\n## Reproducibility {.appendix}\n\n- [Source code](https://github.com/joelnitta/joelnitta-home/tree/main/posts/2024-01-11_using_renv_with_blog/index.qmd)\n- [`renv` lockfile](https://github.com/joelnitta/joelnitta-home/tree/main/posts/2024-01-11_using_renv_with_blog/renv.lock)", | ||
"supporting": [], | ||
"filters": [ | ||
"rmarkdown/pagebreak.lua" | ||
], | ||
"includes": {}, | ||
"engineDependencies": {}, | ||
"preserve": {}, | ||
"postProcess": true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
--- | ||
title: "Documenting blog posts with renv" | ||
description: | ||
One solution to the 'ack I can't re-knit my post' problem | ||
date: 2024-01-11 | ||
date-modified: today | ||
image: https://i.giphy.com/W69vZGazsH2LDnKCzY.webp | ||
citation: | ||
url: 2024-01-11_using_renv_with_blog | ||
lang: en | ||
categories: | ||
- R | ||
- blogging | ||
- reproducibility | ||
--- | ||
|
||
```{r} | ||
#| label: setup | ||
#| include: false | ||
renv::use(lockfile = "renv.lock") | ||
``` | ||
|
||
## TL;DR | ||
|
||
I show how to use the `renv::use()` function to document the R packages used to write a blogpost. | ||
|
||
## Help, I've fallen and I can't re-knit my post! | ||
|
||
One perennial issue with blogging about R^[Technically this applies to blogging about anything that includes running code, but this is a blog about R so that's what you get] is that the blogger may find themselves unable to run the code in a particular post after some time has passed due to package updates that break the code. | ||
I call this the "I can't re-knit my post" problem. | ||
|
||
There have been various solutions proposed to this vexing problem, including: | ||
|
||
1. [Freezing post computations using Quarto](https://quarto.org/docs/websites/website-blog.html#freezing-posts) | ||
2. [Writing the post as a static Markdown file](https://clauswilke.com/blog/2020/09/08/a-blogdown-post-for-the-ages/) | ||
3. [Using `renv` to maintain one R package library per post](https://www.rostrum.blog/posts/2022-03-15-renv-profiles/) | ||
|
||
I think Approach 1 (freezing the post) is the most straightforward solution to prevent unintended knit failures, but that does not document the packages used, so it does not help with actually re-running the code later. | ||
|
||
I tried [a variant of Approach 3](https://github.com/djnavarro/refinery) (one `renv` library per post) previously, but found that it was easy to get confused between different `renv` environments, and it ended up being more trouble than it was worth. | ||
|
||
## Using `use()` | ||
|
||
Here, I suggest a simple solution based on the [`use()` function](https://rstudio.github.io/renv/articles/use.html) from the [`renv` package](https://rstudio.github.io/renv/index.html), as suggested by that package's author, [\@kevinushey](https://github.com/kevinushey). | ||
I take the liberty of copying some of the `use()` documentation here (but I recommend you [read the whole thing](https://rstudio.github.io/renv/articles/use.html) anyways)^[I also couldn't help but borrow the vignette title. Thanks [\@kevinushey](https://github.com/kevinushey)!]. | ||
|
||
`renv::use()` takes a list of packages and their versions, then: | ||
|
||
- Automatically downloads the requested packages | ||
- Installs the requested packages (plus their recursive package dependencies) to a temporary library path | ||
- Activates that library path, so that it's used subsequently in the script | ||
|
||
Basically, instead of maintaining a per-project package library, it **re-creates the library for a single script^[You might think this means it would take a terribly long time to start up the session each time you work on the script, but thanks to `renv`'s caching mechanism, it actually is quite fast after the first time]**. | ||
|
||
## Workflow | ||
|
||
First, some setup: if you use `renv` for your overall website, I recommend telling `renv` to ignore any scripts in the folder where you store your blog posts, since those will get documented on a per-post basis. | ||
For example, if your blog post folder is called `posts`, add `posts` to the `.renvignore` file in the root of your project: | ||
|
||
``` | ||
posts | ||
``` | ||
|
||
This allows us to have multiple, independent `renv.lock` files within a single website project without complete chaos. | ||
|
||
The rest of the workflow goes like this: | ||
|
||
1. Create blog post, for example, `./posts/2024-01-11_my_post/index.qmd`. | ||
2. Open that post folder in its own instance of VScode or RStudio (so that your working directory is `./posts/2024-01-11_my_post/`). | ||
3. Write post, including code chunks. | ||
4. Run `renv::snapshot()`. This will write `./posts/2024-01-11_my_post/renv.lock`, but **will not modify `.Rprofile`** or create a project library. | ||
5. Include the line `renv::use(lockfile = "renv.lock")` in the setup chunk of your post (or a chunk at the very top with `#| include: false`). | ||
6. Go back to your main website project and run `quarto render` or `quarto preview` to knit the post. Your post will use the package versions stored in the lockfile for that post. | ||
7. If you need to update the post, repeat steps 2--4, and render again. | ||
|
||
## Example | ||
|
||
This post hasn't used any code yet, so here is some by way of example. | ||
|
||
```{r} | ||
#| label: example | ||
library(minimal) # my package for testing, which you probably don't have installed | ||
library(digest) | ||
digest(pi) | ||
``` | ||
|
||
I have gone through the workflow steps above and added the call to `renv::use()`. | ||
Please have a look at the [source code of this blog post](https://github.com/joelnitta/joelnitta-home/tree/main/posts/2024-01-11_using_renv_with_blog/index.qmd) to see how this works. | ||
|
||
## Conclusion | ||
|
||
I like this approach because we don't actually create multiple `renv` projects, so we can avoid headaches related to project-switching (though you still need to use different working directories). | ||
|
||
One downside is that given enough time, it may no longer be possible to install the R packages at their specified versions again. | ||
However, perhaps this isn't such a problem after all: it means whoever is trying to run your code most likely also cannot install the packages, so your post needs to be updated! | ||
|
||
Another plus is that we can include an [appendix](#reproducibility) at the end of each post linking to the `renv.lock` file so any interested reader can see what package versions were used. | ||
|
||
Finally, this should be used in conjunction with the [freeze](https://quarto.org/docs/websites/website-blog.html#freezing-posts) functionality of Quarto to control when each post gets rendered. | ||
|
||
Happy blogging! | ||
|
||
## Reproducibility {.appendix} | ||
|
||
- [Source code](https://github.com/joelnitta/joelnitta-home/tree/main/posts/2024-01-11_using_renv_with_blog/index.qmd) | ||
- [`renv` lockfile](https://github.com/joelnitta/joelnitta-home/tree/main/posts/2024-01-11_using_renv_with_blog/renv.lock) |
Oops, something went wrong.