altdoc-multiversion-docs.yml
Render an altdoc-based R package’s Quarto docs site and deploy multiple versions side by side on gh-pages: PRs to /pr-preview/pr-<number>/, pushes to the default branch to /dev/, published releases to /latest-tag/ and /vX.Y.Z/, and a root / redirect landing page into the default docs version. Ported from d-morrison/rpt’s bespoke docs.yaml into a reusable workflow (see UCD-SERG/serocalculator#504).
One-time setup: set Settings -> Pages -> Source to “Deploy from a branch”, branch gh-pages / (root). Requires an altdoc/quarto_website.yml navbar with a “Versions” menu entry for the version-dropdown step to rewrite (see the Example section).
Unlike the preview / preview-deploy family, this keeps a single job for build, deploy, and PR-preview cleanup, rather than splitting into a fork-safe read-only build half and a base-repo-context deploy half. Hardening that trust boundary is a possible follow-up, not part of this port.
Inputs
| Input | Type | Default | Description |
|---|---|---|---|
r-packages |
string | (see workflow file) |
r-lib/actions package specs to install. Must include local::. and any::altdoc (or a fork). |
needs |
string | "connect\nwebsite" |
r-lib/actions/setup-r-dependencies needs: list. |
apt-packages |
string | '' |
Extra apt packages to install before rendering (space-separated). |
setup-julia |
boolean | false |
Install Julia before rendering (for packages with a JuliaCall dependency). |
checkout-submodules |
string | 'recursive' |
Passed to actions/checkout’s submodules ('recursive', 'true', or 'false'). |
default-branch |
string | 'main' |
The repo’s default branch, used for dev-docs deploys and to read the dev version from DESCRIPTION even on release builds. |
quarto-config-path |
string | 'altdoc/quarto_website.yml' |
Path to the altdoc Quarto config file, relative to the repo root. |
docs-base-url |
string | '' |
Override the docs base URL. Leave empty to derive it from the calling repository. |
preview-branch |
string | 'gh-pages' |
Branch PR previews and version subdirectories are deployed to. |
timeout-minutes |
number | 30 |
Timeout for the docs job as a whole, and for the render step within it. Both are set from this one value. |
rewrite-pr-preview-links |
boolean | true |
On PR builds, repoint Quarto’s repo-action links and the navbar GitHub icon at the PR’s head branch and conversation page. |
rewrite-issue-links |
boolean | true |
Repoint rendered “Report an issue” links at the base repository’s issues page. |
dispatch-version |
string | '' |
Forward the caller’s workflow_dispatch version input ('dev' or 'stable'): a reusable workflow only sees with:-passed values. |
dispatch-release-tag |
string | '' |
Forward the caller’s workflow_dispatch release_tag input, required when dispatch-version is 'stable'. |
legacy-paths |
string | '' |
Retired docs subdirectories to keep working, as old=new pairs (e.g. main=dev). See Retired version directories. |
version-dropdown-title-template |
string | '{version}' |
Label for the navbar “Versions” menu, where {version} is the version being rendered. See Showing which version a reader is on. |
version-in-navbar-title |
boolean | true |
Show that version next to the navbar title, the way pkgdown does. |
Showing which version a reader is on
A reader who arrives at /v1.1.0/reference/index.html from a search result should be able to tell they are on an archived release without reading the URL. Two places say so, each switchable:
- The navbar “Versions” menu is labeled with the version this build renders –
v1.2.3 (stable),0.1.0.9000 (dev), or an archivedv1.1.0– matching the entry it corresponds to, rather than a static “Versions”. Setversion-dropdown-title-templateto change the format, e.g.'Version: {version}'. - The navbar title carries that version beside the package name, after pkgdown, muted for a release and red for a development build. Set
version-in-navbar-title: falseto leave the title alone.
The badge is written to Quarto’s website.navbar.title, not website.title, so the page <title>, the feed, and social-card metadata keep the plain site title.
Which version a build renders comes from the event: a release build renders its own tag, a workflow_dispatch with version: stable renders the tag it was given, and everything else – default-branch pushes and PR previews – renders the branch, so it is labeled as the development version.
Retired version directories
A site that previously published the default branch’s docs to /<branch>/ – the insightsengineering/r-pkgdown-multiversion layout – has every /main/... link broken by the move to /dev/, this workflow’s layout and pkgdown’s own development-mode convention.
Set legacy-paths to a comma- or newline-separated list of old=new pairs to keep the old links alive:
legacy-paths: main=devThat generates a site-root 404.html rewriting any request under /main/ to the same path under /dev/, so /main/reference/index.html lands on /dev/reference/index.html. GitHub Pages serves no server-side redirects but does serve a site-root 404.html for unresolved paths, which is what makes deep links work – a per-directory index.html meta-refresh only catches the directory root.
Two consequences worth knowing:
- Redirection needs JavaScript. Without it the page renders as a plain not-found notice linking to the docs root.
- The redirect replaces the site’s 404 page. Any path the site cannot resolve renders this page, not GitHub’s default one.
The pairs are explicit rather than derived from whichever version this build deployed, so /main/ resolves to the same place after a release build as after a default-branch build.
Permissions
Grant contents: write (deploys push to gh-pages), pull-requests: write, and issues: write (the PR-preview sticky comment and link rewrites).
Example
# Copy to .github/workflows/docs.yaml in your repo.
name: Docs
on:
push:
branches: [main]
release:
types: [published]
pull_request:
types: [opened, reopened, synchronize, closed]
workflow_dispatch:
inputs:
version:
description: Documentation version to deploy
required: true
default: dev
type: choice
options: [dev, stable]
release_tag:
description: Stable release tag to deploy when version=stable (e.g. v1.2.3)
required: false
type: string
jobs:
docs:
permissions:
contents: write
pull-requests: write
issues: write
uses: Morrison-Lab/gha/.github/workflows/altdoc-multiversion-docs.yml@v2
with:
dispatch-version: ${{ github.event.inputs.version }}
dispatch-release-tag: ${{ github.event.inputs.release_tag }}
# legacy-paths: main=dev # keep pre-migration /main/ links working
# version-dropdown-title-template: 'Version: {version}'
# version-in-navbar-title: falseYour altdoc/quarto_website.yml navbar needs a placeholder “Versions” entry for the version-dropdown step to find and rewrite:
website:
navbar:
right:
- text: Versions
menu:
- text: "$ALTDOC_PACKAGE_VERSION (dev)"
href: https://<owner>.github.io/<repo>/dev/See the examples/ directory for the full caller stub (altdoc-multiversion-docs.yml), with every optional input commented out.