|
| 1 | +--- |
| 2 | +author: |
| 3 | + - name: "Mickaël CANOUIL, _Ph.D._" |
| 4 | + orcid: "0000-0002-3396-4549" |
| 5 | + url: "https://mickael.canouil.fr" |
| 6 | +title: "Quarto: Publishing to GitHub Pages" |
| 7 | +description: | |
| 8 | + In this guide, we'll explore various methods to publish your Quarto projects to GitHub Pages. |
| 9 | + We'll cover both manual and automated approaches to help you choose the best fit for your workflow. |
| 10 | +date: "2024-12-30" |
| 11 | +categories: [Quarto, "GitHub Pages", Publishing, Deployment, "GitHub Actions"] |
| 12 | +image: featured.png |
| 13 | +image-alt: | |
| 14 | + Quarto icon and text logo above GitHub Pages logo. |
| 15 | +toc-depth: 5 |
| 16 | +link-external-icon: true |
| 17 | +--- |
| 18 | + |
| 19 | +{fig-alt="Quarto icon and text logo above GitHub Pages logo." fig-align="center" width="50%"} |
| 20 | + |
| 21 | +[Originally published on [mickael.canouil.fr](https://mickael.canouil.fr/posts/2024-12-30-quarto-github-pages/).]{style="font-style: italic; opacity: 0.8;"} |
| 22 | + |
| 23 | +Publishing Quarto projects to GitHub Pages can seem daunting, but with the right approach, it's a breeze. |
| 24 | +This blog post will walk you through various methods to deploy your Quarto creations, from simple manual steps to automated workflows using GitHub Actions. |
| 25 | +By the end, you'll have the know-how to share your dynamic documents, books, and websites seamlessly with the world. |
| 26 | + |
| 27 | +Let's dive into the essentials of making your Quarto project live on GitHub Pages. |
| 28 | + |
| 29 | +## Prerequisites |
| 30 | + |
| 31 | +::: {.callout-important} |
| 32 | +Before proceeding, ensure you have enabled and configured GitHub Pages for your repository (*i.e.*, `https://github.com/<username>/<repository>/settings/pages`), see [GitHub Pages documentation](https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site) for more details. |
| 33 | +::: |
| 34 | + |
| 35 | +The following methods mostly assume your GitHub repository is public. |
| 36 | +If your repository is private, you may need to adjust the settings to allow GitHub Pages to access the repository using a personal access token. |
| 37 | + |
| 38 | +You can use the Quarto project created with the `quarto create project website` command as a demo project to try out the methods described in this guide. |
| 39 | +This will provide a practical example to follow along with. |
| 40 | + |
| 41 | +## Manual Approach |
| 42 | + |
| 43 | +### Using Quarto CLI |
| 44 | + |
| 45 | +The manual method involves using the Quarto Command Line Interface (CLI) to publish your project. |
| 46 | +This method is straightforward and requires minimal setup. |
| 47 | + |
| 48 | +```sh |
| 49 | +quarto publish gh-pages |
| 50 | +``` |
| 51 | + |
| 52 | +Check out the Quarto CLI help for more details on the `publish` command. |
| 53 | + |
| 54 | +```sh |
| 55 | +quarto publish --help |
| 56 | +``` |
| 57 | + |
| 58 | +::: {.callout-note} |
| 59 | +The `gh-pages` branch is used to publish to GitHub Pages. |
| 60 | + |
| 61 | +`quarto publish gh-pages` setups the `gh-pages` branch, renders your project, and pushes the output to the branch. |
| 62 | +You can use the `--no-render` flag to skip rendering and only push a previously rendered project. |
| 63 | +::: |
| 64 | + |
| 65 | +## Automated Approach |
| 66 | + |
| 67 | +Automation can streamline the publishing process and reduce the risk of errors. |
| 68 | +Here are two automated methods using GitHub Actions. |
| 69 | + |
| 70 | +::: {.callout-important} |
| 71 | +Ensure you have the necessary permissions to create and manage GitHub Actions workflows in your repository (*i.e.*, `https://github.com/<username>/<repository>/settings/actions`), see [GitHub Actions documentation](https://docs.github.com/en/actions) for more details. |
| 72 | +::: |
| 73 | + |
| 74 | +### Quarto Publish GitHub Action |
| 75 | + |
| 76 | +Quarto provides an official GitHub Action that simplifies the publishing process. |
| 77 | +This action takes care of the entire workflow but **requires** to use `quarto publish gh-pages` locally at least once to set up the `gh-pages` branch. |
| 78 | + |
| 79 | +```{.yaml filename=".github/workflows/deploy.yml"} |
| 80 | +name: Deploy |
| 81 | +
|
| 82 | +on: |
| 83 | + workflow_dispatch: |
| 84 | + push: |
| 85 | + branches: |
| 86 | + - main |
| 87 | +
|
| 88 | +permissions: |
| 89 | + contents: read |
| 90 | +
|
| 91 | +concurrency: |
| 92 | + group: ${{ github.workflow }} |
| 93 | + cancel-in-progress: true |
| 94 | +
|
| 95 | +jobs: |
| 96 | + deploy: |
| 97 | + runs-on: ubuntu-latest |
| 98 | + permissions: |
| 99 | + contents: write |
| 100 | + pages: write |
| 101 | + steps: |
| 102 | + - name: Checkout repository |
| 103 | + uses: actions/checkout@v4 |
| 104 | + - name: Install Quarto |
| 105 | + uses: quarto-dev/quarto-actions/setup@v2 |
| 106 | + with: |
| 107 | + version: pre-release |
| 108 | + # Add any additional steps as needed, such as installing dependencies |
| 109 | + - name: Build and Deploy |
| 110 | + uses: quarto-dev/quarto-actions/publish@v2 |
| 111 | + with: |
| 112 | + target: gh-pages |
| 113 | +``` |
| 114 | + |
| 115 | +::: {.callout-note} |
| 116 | +The `quarto-dev/quarto-actions` GitHub Actions are maintained by the Quarto team. |
| 117 | +You can find more information about these actions in the [Quarto Actions repository](https://github.com/quarto-dev/quarto-actions). |
| 118 | +::: |
| 119 | + |
| 120 | +### Custom GitHub Actions Workflow |
| 121 | + |
| 122 | +For more control over the publishing process, you can set up a custom GitHub Actions workflow. |
| 123 | +We'll discuss two scenarios: |
| 124 | + |
| 125 | +- [**Deploy from a branch**](#deploy-from-a-branch) ([Deploy from a branch - GitHub](https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-from-a-branch)) |
| 126 | + *Classic Pages experience, where the content is published from a specific branch root or `/docs` folder.* |
| 127 | + |
| 128 | +- [**GitHub Actions**](#github-actions) ([GitHub Actions - GitHub](https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-with-a-custom-github-actions-workflow)) |
| 129 | + *Best for using frameworks and customizing your build process.* |
| 130 | + |
| 131 | +#### Deploy From a Branch |
| 132 | + |
| 133 | +You can configure a workflow to publish your Quarto project whenever changes are pushed to a specific branch (*e.g.*, `main`) and deploy the output to GitHub Pages from a specific folder/branch. |
| 134 | + |
| 135 | +::: {.callout-note} |
| 136 | +The GitHub Action workflow described in [Quarto Publish GitHub Action](#quarto-publish-github-action) uses `gh-pages` root as the source for GitHub Pages. |
| 137 | +::: |
| 138 | + |
| 139 | +##### Deploying From the `docs` Folder (*e.g.*, `main` Branch) |
| 140 | + |
| 141 | +Using the `docs` folder as the source for GitHub Pages. Be sure to use a Quarto project (*i.e.*, `_quarto.yml`) to be able to set `output-dir`. |
| 142 | + |
| 143 | +```{.yaml filename=".github/workflows/deploy.yml"} |
| 144 | +name: Deploy |
| 145 | +
|
| 146 | +on: |
| 147 | + workflow_dispatch: |
| 148 | + push: |
| 149 | + branches: |
| 150 | + - main |
| 151 | +
|
| 152 | +permissions: |
| 153 | + contents: read |
| 154 | +
|
| 155 | +concurrency: |
| 156 | + group: ${{ github.workflow }} |
| 157 | + cancel-in-progress: true |
| 158 | +
|
| 159 | +jobs: |
| 160 | + deploy: |
| 161 | + runs-on: ubuntu-latest |
| 162 | + permissions: |
| 163 | + contents: write |
| 164 | + steps: |
| 165 | + - name: Checkout repository |
| 166 | + uses: actions/checkout@v4 |
| 167 | + - name: Install Quarto |
| 168 | + uses: quarto-dev/quarto-actions/setup@v2 |
| 169 | + with: |
| 170 | + version: pre-release |
| 171 | + # Add any additional steps as needed, such as installing dependencies |
| 172 | + - name: Build |
| 173 | + shell: bash |
| 174 | + run: | |
| 175 | + [ ! -f _quarto.yml ] && echo -e "project:\n output-dir: docs" > _quarto.yml |
| 176 | + if grep -q "output-dir: docs" _quarto.yml; then |
| 177 | + quarto render |
| 178 | + else |
| 179 | + quarto render --output-dir docs |
| 180 | + fi |
| 181 | + - name: Deploy |
| 182 | + shell: bash |
| 183 | + run: | |
| 184 | + git config --local user.name github-actions[bot] |
| 185 | + git config --local user.email 41898282+github-actions[bot]@users.noreply.github.com |
| 186 | + git add docs || echo "No changes." |
| 187 | + git commit -m "ci: quarto render" || echo "No changes." |
| 188 | + git push origin || echo "No changes." |
| 189 | +``` |
| 190 | + |
| 191 | +##### Deploying From the Root (*e.g.*, `gh-pages` Branch) |
| 192 | + |
| 193 | +Using the root of the `gh-pages` branch as the source for GitHub Pages. |
| 194 | + |
| 195 | +::: {.callout-tip} |
| 196 | +This method offers an advantage over `quarto publish gh-pages` as it does not necessitate a local run to create the `gh-pages` branch beforehand. |
| 197 | +Additionally, it provides some insight into the processes that occur behind the scenes when using `quarto publish gh-pages`, thus when using the [Quarto Publish GitHub Action](#quarto-publish-github-action). |
| 198 | +::: |
| 199 | + |
| 200 | +```{.yaml filename=".github/workflows/deploy.yml"} |
| 201 | +name: Deploy |
| 202 | +
|
| 203 | +on: |
| 204 | + workflow_dispatch: |
| 205 | + push: |
| 206 | + branches: |
| 207 | + - main |
| 208 | +
|
| 209 | +permissions: |
| 210 | + contents: read |
| 211 | +
|
| 212 | +concurrency: |
| 213 | + group: ${{ github.workflow }} |
| 214 | + cancel-in-progress: true |
| 215 | +
|
| 216 | +jobs: |
| 217 | + deploy: |
| 218 | + runs-on: ubuntu-latest |
| 219 | + permissions: |
| 220 | + contents: write |
| 221 | + steps: |
| 222 | + - name: Checkout repository |
| 223 | + uses: actions/checkout@v4 |
| 224 | + - name: Install Quarto |
| 225 | + uses: quarto-dev/quarto-actions/setup@v2 |
| 226 | + with: |
| 227 | + version: pre-release |
| 228 | + # Add any additional steps as needed, such as installing dependencies |
| 229 | + - name: Build |
| 230 | + shell: bash |
| 231 | + run: | |
| 232 | + [ ! -f _quarto.yml ] && echo -e "project:\n output-dir: _site" > _quarto.yml |
| 233 | + if grep -q "output-dir: _site" _quarto.yml; then |
| 234 | + quarto render |
| 235 | + else |
| 236 | + quarto render --output-dir _site |
| 237 | + fi |
| 238 | + - name: Deploy |
| 239 | + shell: bash |
| 240 | + env: |
| 241 | + GH_PAGES: gh-pages |
| 242 | + run: | |
| 243 | + git config --local user.name github-actions[bot] |
| 244 | + git config --local user.email 41898282+github-actions[bot]@users.noreply.github.com |
| 245 | + BUILD_DIR=$(mktemp -d) |
| 246 | + mv _site "${BUILD_DIR}/quarto-output" |
| 247 | + if git ls-remote --exit-code origin "${GH_PAGES}"; then |
| 248 | + git fetch origin "${GH_PAGES}" |
| 249 | + git checkout origin/"${GH_PAGES}" |
| 250 | + else |
| 251 | + git checkout --orphan "${GH_PAGES}" |
| 252 | + git rm -rf . |
| 253 | + fi |
| 254 | + mv ${BUILD_DIR}/quarto-output/* . |
| 255 | + git add . || echo "No changes." |
| 256 | + git commit --allow-empty -m "ci: quarto render" || echo "No changes." |
| 257 | + git push origin "${GH_PAGES}" || echo "No changes." |
| 258 | +``` |
| 259 | + |
| 260 | +#### GitHub Actions |
| 261 | + |
| 262 | +For more sophisticated workflows, you have the option to customise the build process, thus eliminating the need to set up the `gh-pages` or `docs` folder. |
| 263 | +This approach is particularly advantageous as it ensures that the source repository remains uncluttered, maintaining a clear separation between the source code and the build/deploy process and environment. |
| 264 | + |
| 265 | +```{.yaml filename=".github/workflows/deploy.yml"} |
| 266 | +name: Deploy |
| 267 | +
|
| 268 | +on: |
| 269 | + workflow_dispatch: |
| 270 | + push: |
| 271 | + branches: |
| 272 | + - main |
| 273 | +
|
| 274 | +permissions: |
| 275 | + contents: read |
| 276 | +
|
| 277 | +concurrency: |
| 278 | + group: "pages" |
| 279 | + cancel-in-progress: false |
| 280 | +
|
| 281 | +jobs: |
| 282 | + deploy: |
| 283 | + runs-on: ubuntu-latest |
| 284 | + permissions: |
| 285 | + pages: write |
| 286 | + id-token: write |
| 287 | + environment: |
| 288 | + name: github-pages |
| 289 | + url: ${{ steps.deployment.outputs.page_url }} |
| 290 | + steps: |
| 291 | + - name: Checkout repository |
| 292 | + uses: actions/checkout@v4 |
| 293 | + - name: Install Quarto |
| 294 | + uses: quarto-dev/quarto-actions/setup@v2 |
| 295 | + with: |
| 296 | + version: pre-release |
| 297 | + - name: Build |
| 298 | + shell: bash |
| 299 | + run: | |
| 300 | + [ ! -f _quarto.yml ] && echo -e "project:\n output-dir: _site" > _quarto.yml |
| 301 | + if grep -q "output-dir: _site" _quarto.yml; then |
| 302 | + quarto render |
| 303 | + else |
| 304 | + quarto render --output-dir _site |
| 305 | + fi |
| 306 | + - name: Configure GitHub Pages |
| 307 | + uses: actions/configure-pages@v5 |
| 308 | + - name: Upload Pages Artifact |
| 309 | + uses: actions/upload-pages-artifact@v3 |
| 310 | + with: |
| 311 | + path: "_site" |
| 312 | + - name: Deploy |
| 313 | + id: deployment |
| 314 | + uses: actions/deploy-pages@v4 |
| 315 | +``` |
| 316 | + |
| 317 | +::: {.callout-note} |
| 318 | +The workflow above utilises `_site` as the output directory, which is the default output directory for Quarto website projects. You can modify the output directory as necessary, provided it aligns with the `Upload Pages Artifact` step. |
| 319 | +::: |
| 320 | + |
| 321 | +### Keeping Your GitHub Actions Workflow Up-to-Date |
| 322 | + |
| 323 | +GitHub Actions workflows are versioned, and new versions are released periodically. |
| 324 | +To ensure your workflows are up-to-date, you can use Dependabot to automatically create pull requests when new versions of your dependencies are available. |
| 325 | + |
| 326 | +```{.yaml filename=".github/dependabot.yml"} |
| 327 | +version: 2 |
| 328 | +updates: |
| 329 | + - package-ecosystem: "github-actions" |
| 330 | + directory: "/" |
| 331 | + schedule: |
| 332 | + interval: "weekly" |
| 333 | +```` |
| 334 | +
|
| 335 | +This configuration file instructs Dependabot to check for updates to GitHub Actions workflows weekly. |
| 336 | +
|
| 337 | +For more information on Dependabot, see the [Dependabot documentation](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuring-dependabot-version-updates). |
| 338 | +
|
| 339 | +## Conclusion |
| 340 | +
|
| 341 | +By following these methods, you'll be able to publish your Quarto projects to GitHub Pages efficiently. |
| 342 | +Choose the approach that best suits your needs and workflow. |
| 343 | +
|
| 344 | +Happy publishing! |
0 commit comments