Scripts and Hooks
scripts-and-hooks.RmdScripts and hooks customize projr’s build process. Scripts control which documents to render; hooks run custom R code before or after builds.
Both are configured in _projr.yml and have separate
settings for production builds (projr_build_patch(), etc.)
and development builds (projr_build_dev()).
Build Scripts
Build scripts specify which documents or R scripts projr should render.
Configuration format
Scripts are plain character vectors in _projr.yml. No
sub-keys or nested structures are allowed.
Priority
Production builds resolve scripts in this order:
-
fileparameter passed to the build function -
build.scriptsin_projr.yml -
_quarto.ymlor_bookdown.ymlproject file - Auto-detection of
.Rmd,.qmd,.Rfiles
Development builds follow the same order, but check
dev.scripts before falling back to
build.scripts:
-
fileparameter -
dev.scriptsin_projr.yml -
build.scriptsin_projr.yml -
_quarto.ymlor_bookdown.yml - Auto-detection
When dev.scripts is set, it completely replaces
build.scripts for dev builds. To include production scripts
in dev builds, list them explicitly under dev.scripts.
All specified scripts are validated before the build starts. Missing files cause an immediate error.
Managing scripts with R
# Add scripts
projr_yml_script_add(c("analysis.qmd", "report.Rmd"))
# Remove a script
projr_yml_script_rm("report.Rmd")
# Remove all scripts
projr_yml_script_rm_all()Example: separate dev and production scripts
# _projr.yml
build:
scripts:
- full-analysis.qmd
- supplementary.Rmd
- appendix.Rmd
dev:
scripts:
- quick-test.qmd
projr_build_dev() # renders quick-test.qmd only
projr_build_patch() # renders all three documentsExample: one-off builds
projr_build_dev("exploratory-analysis.Rmd")
projr_build_dev(c("methods.Rmd", "results.Rmd"))Build Hooks
Hooks run custom R scripts at specific points in the build process.
Configuration format
Hooks are plain character vectors organized by stage. Three stage
keys are available: pre (before the build),
post (after the build), and both (runs at both
stages). File paths are relative to the project root.
build:
hooks:
pre:
- hooks/setup.R
- hooks/download-data.R
post:
- hooks/cleanup.R
both:
- hooks/log-timestamp.R
dev:
hooks:
pre: hooks/dev-setup.Rbuild.hooks are ignored in dev builds.
dev.hooks are ignored in production builds. Unlike scripts,
there is no fallback between them.
Execution details
Hooks within a stage run in the order listed. Each hook runs in an
isolated child environment of the global environment, so objects created
in one hook are not available in subsequent hooks. To share data between
hooks, save to disk (e.g., saveRDS()).
Where hooks run in the build flow:
Production build:
1. Pre-build hooks
2. Version bump
3. Clear output directories
4. Git commit (if configured)
5. Render scripts
6. Git commit outputs (if configured)
7. Distribute to remotes
8. Post-build hooks
Development build:
1. Dev pre-build hooks
2. Clear output directories
3. Render scripts
4. Dev post-build hooks
Like scripts, all hook files are validated before the build starts. A missing hook file causes an immediate error. If a hook fails at runtime, the build stops.
Managing hooks with R
projr_yml_hooks_add(path = "hooks/setup.R", stage = "pre")
projr_yml_hooks_add_pre("hooks/check-auth.R")
projr_yml_hooks_add_post("hooks/cleanup.R")
# Append instead of overwriting
projr_yml_hooks_add("hooks/extra.R", stage = "pre", overwrite = FALSE)
# Remove all hooks
projr_yml_hooks_rm_all()Example: data preparation hook
# hooks/prepare-data.R
data_url <- Sys.getenv("DATA_URL")
if (!nzchar(data_url)) stop("DATA_URL not set")
download.file(data_url, destfile = "_raw_data/data.csv")
data <- read.csv("_raw_data/data.csv")
stopifnot(nrow(data) > 0)
message("Data preparation complete")Example: separate dev and production hooks
# hooks/dev-setup.R
message("Setting up dev environment...")
Sys.setenv(PROJR_OUTPUT_LEVEL = "debug")Tips
- Use relative paths for portability.
- Keep each hook focused on one task. Use descriptive filenames (e.g.,
validate-credentials.Rrather thanhook1.R). - Wrap external operations in
tryCatch()so error messages are actionable. - Test hooks outside a build with
source("hooks/my-hook.R").
See Also
-
?projr_yml_hooks_add- Add hooks programmatically -
?projr_yml_script_add- Add scripts programmatically -
?projr_build_dev- Development builds -
?projr_build_patch- Production builds