---
title: "How to update a released site"
output: rmarkdown::html_vignette
description: >
  A guide to updating the "released" version of your pkgdown site without
  having to release a new version of your package.
vignette: >
  %\VignetteIndexEntry{How to update a released site}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  eval = FALSE
)
```

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 a using recent version of our recommend [pkgdown action](https://github.com/r-lib/actions/blob/HEAD/examples/pkgdown.yaml). 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:

```{r}
gert::git_branch_checkout("main")
gert::git_pull()
```

Next figure out the released version that we're updating:

```{r}
ver <- desc::desc_get_version()[1, 1:3]
```

We'll use this to create and checkout the branch that you'll work in:

```{r}
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:

```{r}
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`:

```{r}
desc::desc_set_version(ver)
```

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

```{r}
pkgdown::build_site()
```

### Publish

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

```{r}
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*](https://pkgdown.r-lib.org/reference/build_site.html#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:

``` yaml
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](https://readr.tidyverse.org) documents the released version, i.e. what `install.packages()` would deliver.\
[readr.tidyverse.org/dev/](https://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 that 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 bascially 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`](https://github.com/r-lib/actions/blob/v2/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:

``` yaml
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/github-pages-deploy-action@4.1.4
        
        <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](https://docs.github.com/en/actions/using-workflows/manually-running-a-workflow), 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()`.
1. Click on the `pkgdown` workflow.
1. Click the "Run workflow".
1. 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](https://github.com/search?q=path%3A%22_pkgdown.yml%22+AND+%28org%3Atidyverse+OR+org%3Ar-lib%29&type=code) or [Michael Chirico's `r-ci-samples` repo](https://github.com/MichaelChirico/r-ci-samples/tree/master/pkgdown). For any given `_pkgdown.yml` file, remember that its History and Blame can be helpful for seeing how it has evolved over time.
