Home

Awesome

capsule

capsule status badge

Installation

R Universe

install.packages(
   "capsule", 
   repos = c(mm = "https://milesmcbain.r-universe.dev", getOption("repos")))

Overview

A capsule is a stable project-specific R package library that you consciously choose to execute code within. Think of it as representing 'production', while your normal interactive R session represents 'development'.

You develop interactively in a dynamic package environment. You run code for real in a well-defined static capsule. Periodically you'll want to have your development environment reflected in the capsule as new stuff is integrated.

When sharing with others, a capsule is the fallback that ensures your code can always be run, no matter what issues appear in your collaborator's development environment.

Usage

There are 3 functions you need to know about to use capsule: capsule::create(), capsule::run(), capsule::recreate().

create() a capsule for my pipeline

> capsule::create("./packages.R")
Finding R package dependencies ... Done!
* Discovering package dependencies ... Done!
* Copying packages into the cache ... [132/132] Done!
The following package(s) will be updated in the lockfile:

# CRAN ===============================
- anytime          [* -> 0.3.6]
- askpass          [* -> 1.1]
...TRUNCATED...
- BH               [* -> 1.69.0-1]
- spatial          [* -> 7.3-11]
- survival         [* -> 2.44-1.1]

# GitHub =============================
- geojsonsf        [* -> SymbolixAU/geojsonsf]
- h3jsr            [* -> obrl-soil/h3jsr]
- jsonify          [* -> SymbolixAU/jsonify]
- qfes             [* -> milesmcbain/qfes]
- renv             [* -> rstudio/renv]

* Lockfile written to 'c:/repos/capsule/renv.lock'.

You supply a vector of file paths to extract dependencies from. The default is "./packages.R". These dependencies are copied from your regular (dev) library to your local capsule.

Notice how this is easier when you keep your library calls all in one place? :wink:

You'll notice some things created in your project folder. Assuming you have the project under version control... you definitely want to commit the ./renv.lock file. This will allow someone else to run() code in the capsule context.

run() code in the capsule

Render a document in the capsule:

capsule::run(rmarkdown::render("doc/analysis.Rmd"))

Or run your {targets} plan in the capsule:

capsule::run(targets::tar_make())

So what about code that you've just been handed? It has a renv.lock but no local library? How do you build the library to run the code? You don't! run() will check to see if a local library exists, and build it if required. (You can do this manually with reproduce_lib(), if that feels better before calling run()).

recreate() the capsule

You've done some development work, updated a few dependencies, and the output has tested successfully. You can make the capsule reflect the project dependencies installed in your dev environment using recreate().

Other Useful Stuff

Debugging in the capsule with a REPL

Try capsule::repl() to attach a REPL for a new R process in the context of the capsule. This is handy for interactive work like debugging. The tradeoff here is that depending what editor you use strange behaviour may be induced by the outer REPL being overtaken. In ESS I lose my autocompletions.

Automating lockfile creation with capshot()

capshot() is designed to create a lockfile for your project very quickly so that it can be integrated into your build or rendering pipeline. On my {tflow} projects laden with dependencies it typically takes 1-2 seconds to detect the dependencies and write the lockfile.

Unlike create() it does not populate a local library automatically. See:

Helpers

It's an renv in the end

A capsule is an renv. The full power of renv can always be used to manipulate the lockfile and library if you wish.