How to update a released site

This vignette shows you how to update the released version of your site to match the dev version of the site, so the first step is to ensure that the dev site looks the way that you want it.

This site assumes that you’re using a recent version of our recommended pkgdown action. If your workflow does not contain workflow_dispatch, you will need to update .github/actions/pkgdown.yaml by running use_github_action("pkgdown").

Process

If you’re up to speed with the basic idea and just want some code to follow, here it is. Otherwise, read more below.

Setup

First, make sure you’re in the main branch, and you have the latest version:

gert::git_branch_checkout("main")
gert::git_pull()

Next figure out the released version that you’re updating:

ver <- desc::desc_get_version()[1, 1:3]

You will use this to create and checkout the branch that you’ll work in:

gert::git_branch_create(paste0("pkgdown-v", ver), paste0("v", ver))

Backport changes

Now you need to backport changes from the dev site into this branch. Run this R code to generate the git code to pull changes for the most common locations:

files <- c(
  # overall site config
  "_pkgdown.yml",
  # the workflow that builds the site
  ".github/workflows/pkgdown.yaml",
  # readme and vignettes
  "README.md", "vignettes",
  # logo and favicon
  "man/figures/", "pkgdown/",
  # Author metadata and Config/Needs/Website
  "DESCRIPTION"
)

glue::glue("git checkout v{ver} -- {files}")

If you backport DESCRIPTION, you’ll also need undo the change to the Version:

desc::desc_set_version(ver)

Now build the site locally and check that it looks as expected:

pkgdown::build_site()

Publish

Now you need to publish the site. First push your branch to GitHub:

usethis:::git_push_first()

Then trigger the pkgdown workflow:

  1. Go to your package’s GHA page, e.g. with usethis::browse_github_actions()).
  2. Select the pkgdown workflow.
  3. Click Run workflow and select the branch you just pushed.

If there’s no dropdown menu for this, that means your pkgdown workflow config is not current.

Context

Before we talk about how to update a released site, we first establish why you might need to do this. What is a released site? What other kind of pkgdown site could you have? Why does updating a released site take special effort?

Automatic development mode

Every pkgdown site has a so-called development mode, which can be specified via the development field in _pkgdown.yml. If unspecified, the default is mode: release, which results in a single pkgdown site. Despite the name, this single site reflects “the current package state”, which could be either a released state or a development state.

For packages with a substantial user base, it is recommended instead to specify mode: auto like so:

development:
  mode: auto

This directs pkgdown to “generate different sites for the development and released versions of your package.”

The readr package demonstrates what happens in automatic development mode:

readr.tidyverse.org documents the released version, i.e. what install.packages() will deliver.
readr.tidyverse.org/dev/ documents the dev version, i.e. what you’d get by installing from GitHub.

In this mode, pkgdown::build_site(), consults DESCRIPTION to learn the package’s version number. For a development version number, the rendered site is written to docs/dev/. For a released version number, the site is written to docs/. (There are also other signals to alert users that they are reading documentation for a dev version vs. a released version.)

Automatic development mode is recommended for packages with a broad user base because it maximizes the chance that a user will read web-based documentation which reflects the package version that is locally installed.

Publishing

Now that we’ve established the meaning of a released (vs dev) site, we have to consider how the site is built (i.e. how the HTML is generated) and deployed (i.e. how the HTML is published to a website so people can see it.).

We recommend usethis::use_pkgdown_github_pages() to do basic pkgdown setup and configure a GitHub Actions (GHA) workflow to automatically render and publish the site to GitHub Pages. This function is basically a shortcut for calling the following functions individually:

  • use_pkgdown()
  • use_github_pages()
  • use_github_action("pkgdown")

It then adds the pkgdown site’s URL to _pkgdown.yml, the URL field of DESCRIPTION, and the GitHub repo.

As a result, the publishing cadence of many pkgdown sites is governed by the workflow maintained at r-lib/actions/examples/pkgdown.yaml. (Do not confuse _pkgdown.yml, which gives instructions to the pkgdown package, with .github/workflows/pkgdown.yaml, which gives instructions to GHA.)

Here are some of the most important bits of the GHA workflow config:

on:
  push:
    branches: [main, master]
  pull_request:
    branches: [main, master]
  release:
    types: [published]
  workflow_dispatch:

<snip, snip>

      - name: Build site
        run: Rscript -e 'pkgdown::build_site_github_pages(...)'

      - name: Deploy to GitHub pages 🚀
        if: github.event_name != 'pull_request'
        uses: JamesIves/[email protected]

        <snip, snip>

Altogether this means that we:

  • Build and deploy for pushes to main.

  • Build, but don’t deploy, for pull requests against main. This reveals any pkgdown errors, but ensures the live site isn’t updated until the pull request is merged (because the code is pushed to main).

  • Build and deploy when we publish a GitHub release. By convention, we assume that a GitHub release coincides with a CRAN release. So this is the primary mechanism for building the released pkgdown site.

pkgdown::build_site_github_pages() consults the version in DESCRIPTION to detect whether it’s building from a released version or a dev version. That determines the dest_dir, e.g. docs/ for released and docs/dev/ for dev. For a package in automatic development mode, this means that almost all of your pushes trigger an update to the dev site. The released site is only updated when you push a state with a non-development version number or when you publish a GitHub release.

So how do you tweak things about the released site in between releases?

That brings us to workflow_dispatch:. (Yes that dangling colon is correct.)

The inclusion of workflow_dispatch as a trigger means the pkgdown workflow can be run on demand, most importantly from the browser.

Construct a branch for the update

The overall goal is to create a branch that combines some features of the released website (e.g. the released version) and the development version (e.g. improvements to your _pkgdown.yml). The easiest way is to start your branch using the latest release tag, then bring in selected changes or files from the development version.

For example, if readr’s latest release is 2.1.1:

git checkout -b update-pkgdown-2-1-1 v2.1.1

And here is the general pattern:

git checkout -b NEW-BRANCH-NAME NAME-OF-RELEASE-TAG

Now you should port innovations from the development site that you want to apply to your released site.

Files you must update:

  • .github/workflows/pkgdown.yaml
  • _pkgdown.yml
  • Config/Needs/website field of DESCRIPTION (And, probably, only this field! In particular, do not mess with the version number.)

Other likely candidates:

  • README.Rmd + README.md, e.g., if you’ve updated badges.
  • Any documentation fixes that apply to the released version. This is the only reason to touch anything below R/ and even then it should only affect roxygen comments. Don’t forget to document() if you do this!
  • Any new vignettes or articles that apply to the released version.

Here are some tips on backporting specific changes into this branch. If you are lucky, there are specific commits in your default branch that contain all the necessary changes. In that case, we can cherry pick such a commit by its SHA:

git cherry-pick SHA

If that doesn’t cover everything for each file you want to update, identify a Git reference (meaning: a SHA, tag, or branch) where the file is in the desired state. Checkout that specific file path from that specific ref:

git checkout main -- path/to/the/file

For example, readr recently gained a new vignette that applies to the released version of readr, i.e. it does not document any dev-only features or functions. We can bring that into the current branch with:

git checkout main -- vignettes/column-types.Rmd

Commit and push this new branch to GitHub. usethis::pr_push() can be handy for this. Just don’t bother opening a pull request (the branch will still be pushed).

Now we will use the workflow_dispatch GHA trigger:

  1. Go to the Actions page of your repo, maybe via usethis::browse_github_actions().
  2. Click on the pkgdown workflow.
  3. Click the “Run workflow”.
  4. In the “Use workflow from” dropdown menu, select the branch you’ve just made and pushed, then click “Run workflow”.

This should kick off a pkgdown build-and-deploy and, specifically, it should cause updates to the released site.

You can keep this branch around for a while, in case you didn’t get everything right the first time or if more things crop up that you’d like backport to the released site, before your next CRAN release.

Problem-solving

Another great problem solving technique is to get a bunch of other people’s _pkgdown.yml files in front of your eyeballs. There are two ways to do this: GitHub search or Michael Chirico’s r-ci-samples repo. For any given _pkgdown.yml file, remember that its History and Blame can be helpful for seeing how it has evolved over time.