preview.yml
The build half of the PR-preview family. Render the Quarto site read-only in the possibly-forked PR context and upload it plus PR metadata as the pr-preview-site artifact. The deploy half (preview-deploy.yml) publishes it to gh-pages. Keep this workflow’s name: in sync with the workflows: list in the deploy stub. The R and renv machinery is parameterized so non-rme repos can reuse it; turn it off for a pure-markdown site.
Inputs
| Input | Type | Default | Description |
|---|---|---|---|
path |
string | '.' |
Path in the caller repo to the Quarto project to render (the directory with _quarto.yml). Defaults to the repo root; set it for a subdirectory site (matches quarto-publish’s path). |
r-version |
string | '4.6.0' |
R version to install with r-lib/actions/setup-r. |
apt-packages |
string | (long; see workflow file) |
System apt packages to install before R/Quarto setup, space-separated. Defaults to the shared renv stack plus build helpers; set to an empty string to skip the apt step. |
use-renv |
boolean | true |
Restore R dependencies with renv. Set false for non-renv repos. |
r-packages |
string | '' |
R packages to install when use-renv is false (space-, comma-, or newline-separated). |
install-package |
boolean | true |
Run R CMD INSTALL <path> to install the caller repo as a local package before rendering. |
setup-chrome |
boolean | true |
Install Chrome (needed by Quarto for revealjs and screenshot rendering). |
tinytex |
boolean | false |
Install TinyTeX and enable PDF rendering. When false (default), TinyTeX is installed and PDF is rendered only when the PR is labeled preview:pdf. |
submodules |
string | 'recursive' |
Passed to actions/checkout submodules ('recursive', 'true', or 'false'). |
render-profile |
string | 'website' |
Quarto --profile to render with. |
output-dir |
string | '_site' |
Directory the rendered site is written to, relative to path. |
formats |
string | '' |
Space-separated list of formats to render (e.g. 'html docx pdf revealjs'). When empty (default), renders HTML plus any formats requested via PR labels (preview:docx, preview:pdf, preview:revealjs). Set to 'default' to run a single bare quarto render letting _quarto.yml decide formats (unlike quarto-publish where empty string defaults to bare render). |
extra-preview-labels |
string | '[]' |
JSON array string of additional PR label names that trigger a preview re-render on add or remove (e.g. '["preview:tracked-changes"]'), beyond the built-in set (clear freezer, preview:pdf, preview:docx, preview:revealjs). |
fail-on-render-warning |
boolean | false |
Fail the build if Quarto emits any render warnings (WARN in the render log). |
forbid-log-patterns |
string | '' |
Newline-separated fixed string patterns that fail the build if found in the render log (e.g. missing listing files). |
detect-changed-chapters |
boolean | false |
Compare this run’s render against the copy published on the deployed branch and expose which chapters differ as outputs. Implied by changed-chapters-banner. |
changed-chapters-banner |
boolean | false |
Add a banner to the preview home page naming the chapters that differ from the published render. |
changed-chapters-glob |
string | 'chapters/*.html' |
Glob, relative to the rendered site root, selecting the files the comparison treats as chapters. |
deployed-branch |
string | 'gh-pages' |
Branch holding the published render to compare against. |
deployed-subdir |
string | '' |
Path prefix, within the deployed branch, at which the published site root lives. Defaults to the branch root. |
changed-chapters-normalize-patterns |
string | '' |
Newline-separated regexes whose matches are blanked before comparison, in addition to the built-in ones (htmlwidget element ids and ISO-8601 datetimes). |
banner-index |
string | 'index.html' |
Home page the banner is inserted into, relative to the rendered site root. |
Outputs
Set only when detect-changed-chapters or changed-chapters-banner is on.
| Output | Description |
|---|---|
changed-chapters |
JSON array of chapter ids that differ from the published render. A chapter id is the rendered file’s path relative to the site root, with its extension removed. |
any-changed |
true when at least one chapter differs, false otherwise. |
detection-status |
compared when the published render was available, skipped when it was not. |
skip-reason |
Why the comparison was skipped; empty when it ran. |
Read detection-status before acting on an empty changed-chapters. An empty list means “nothing changed” only under compared; under skipped it means the comparison never ran, because nothing has been deployed to deployed-branch yet. Collapsing the two is the failure this capability was rewritten to avoid.
The comparison is against the deployed render, not the source diff, so a page whose content changed because shared code beneath it changed is reported, and a source edit that changes no rendered output is not.
Permissions
Only contents: read (the default). The build half is read-only and must never write to the base repo.
Example
# Copy to .github/workflows/preview.yml in your repo.
# Build half of the PR-preview family: renders the Quarto site in the (possibly
# fork) PR context and uploads it + PR metadata as an artifact. The deploy half
# (preview-deploy.yml) publishes it to gh-pages. This job is read-only
# (contents: read) --- it must never write to the base repo.
#
# IMPORTANT: keep this workflow's `name:` in sync with the `workflows:` list in
# preview-deploy.yml --- that's how the deploy half finds this run.
name: Quarto Preview Build
on:
pull_request:
types: [opened, reopened, synchronize, labeled, closed]
# Trim/extend these globs to the source paths that affect your rendered site.
paths:
- 'man/**'
- 'vignettes/**'
- '_extensions/**'
- '_quarto*.yml'
- '*.qmd'
- 'chapters/**/*.qmd'
- '_subfiles/**'
- '*.scss'
jobs:
build:
permissions:
contents: read
uses: Morrison-Lab/gha/.github/workflows/preview.yml@v2
# with:
# path: website # Quarto project lives in a subdir (default: repo root)
# r-version: '4.6.0'
# apt-packages: 'jags libglpk-dev' # override the default system-deps list
# use-renv: true # set false for non-renv repos
# r-packages: 'rmarkdown knitr' # packages to install when use-renv: false
# install-package: true # `R CMD INSTALL <path>` before rendering
# setup-chrome: true # needed for revealjs / screenshots
# tinytex: false # install TinyTeX unconditionally (default: label-gated)
# submodules: recursive
# render-profile: website
# output-dir: docs # render to a dir other than _site
# formats: 'html docx pdf' # space-separated list, or 'default' for bare render
# extra-preview-labels: '["preview:tracked-changes"]' # JSON array string of additional labels that trigger preview rebuilds
# fail-on-render-warning: true # fail if Quarto emits WARN in render log
# forbid-log-patterns: | # fail on specific forbidden substrings in render log
# doesn't match any files or folders
# detect-changed-chapters: true # expose which chapters differ from the deployed render
# changed-chapters-banner: true # and list them on the preview home page
# changed-chapters-glob: 'chapters/*.html'
# deployed-branch: gh-pages
# deployed-subdir: '' # set when gh-pages nests the site under a prefix
# banner-index: index.html
# changed-chapters-normalize-patterns: | # blank anything else that changes every render
# build-[0-9a-f]+See examples/preview.yml for the full caller stub.
Partial adoption for bespoke builds
If your site requires custom post-render processing or a build sequence that preview.yml does not model, you can maintain a custom build workflow and still use preview-deploy.yml and cleanup-pr-previews.yml. See Partial adoption and artifact contract for details on the three-file pr-preview-site artifact handoff.