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.