Skip to content

Automated Deployment: GitHub Actions

Arvid Norlander edited this page May 11, 2024 · 27 revisions

The following examples show various ways to use GitHub Actions.

Some of these examples will publish to GitHub Pages.

Real-world examples

The examples below are simplified, intended to illustrate basic usage. Real-world projects tend to be more complicated or have more requirements. The following links are to some real-world projects, which you may want to look at for more complex examples:

Running Rust tests

If you want to run mdbook test to test Rust examples, the following GitHub Action will run the tests on every PR and push.

name: CI
on: [push, pull_request]

jobs:
  test:
    name: Test
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@master
    - name: Install Rust
      run: |
        rustup set profile minimal
        rustup toolchain install stable
        rustup default stable
    - name: Install latest mdbook
      run: |
        tag=$(curl 'https://api.github.com/repos/rust-lang/mdbook/releases/latest' | jq -r '.tag_name')
        url="https://github.com/rust-lang/mdbook/releases/download/${tag}/mdbook-${tag}-x86_64-unknown-linux-gnu.tar.gz"
        mkdir bin
        curl -sSL $url | tar -xz --directory=bin
        echo "$(pwd)/bin" >> $GITHUB_PATH
    - name: Run tests
      run: mdbook test

GitHub Pages Deploy

Using deploy via actions

The following example uses GitHub Pages's Deploy via Actions.

In Settings->Pages, choose GitHub Actions (gh-pages) instead of Deploy from a branch.

Add this file to .github/workflows/deploy.yml:

name: Deploy
on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: write  # To push a branch 
      pages: write  # To push to a GitHub Pages site
      id-token: write # To update the deployment status
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Install latest mdbook
        run: |
          tag=$(curl 'https://api.github.com/repos/rust-lang/mdbook/releases/latest' | jq -r '.tag_name')
          url="https://github.com/rust-lang/mdbook/releases/download/${tag}/mdbook-${tag}-x86_64-unknown-linux-gnu.tar.gz"
          mkdir mdbook
          curl -sSL $url | tar -xz --directory=./mdbook
          echo `pwd`/mdbook >> $GITHUB_PATH
      - name: Build Book
        run: |
          # This assumes your book is in the root of your repository.
          # Just add a `cd` here if you need to change to another directory.
          mdbook build
      - name: Setup Pages
        uses: actions/configure-pages@v4
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          # Upload entire repository
          path: 'book'
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

Raw Example

The following does not require any external actions or dependencies to deploy to GitHub Pages.

Add this file to .github/workflows/deploy.yml:

name: Deploy
on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: write  # To push a branch 
      pull-requests: write  # To create a PR from that branch
    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0
    - name: Install latest mdbook
      run: |
        tag=$(curl 'https://api.github.com/repos/rust-lang/mdbook/releases/latest' | jq -r '.tag_name')
        url="https://github.com/rust-lang/mdbook/releases/download/${tag}/mdbook-${tag}-x86_64-unknown-linux-gnu.tar.gz"
        mkdir mdbook
        curl -sSL $url | tar -xz --directory=./mdbook
        echo `pwd`/mdbook >> $GITHUB_PATH
    - name: Deploy GitHub Pages
      run: |
        # This assumes your book is in the root of your repository.
        # Just add a `cd` here if you need to change to another directory.
        mdbook build
        git worktree add gh-pages
        git config user.name "Deploy from CI"
        git config user.email ""
        cd gh-pages
        # Delete the ref to avoid keeping history.
        git update-ref -d refs/heads/gh-pages
        rm -rf *
        mv ../book/* .
        git add .
        git commit -m "Deploy $GITHUB_SHA to gh-pages"
        git push --force --set-upstream origin gh-pages

XAMPPRocky/deploy-mdbook

The following example uses an action from https://github.com/XAMPPRocky/deploy-mdbook to publish to GitHub Pages.

name: Deploy mdBook
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: write  # To push a branch 
      pull-requests: write  # To create a PR from that branch
    steps:
      - uses: actions/checkout@v4
      - uses: XAMPPRocky/[email protected]
        with:
            token: ${{ secrets.GITHUB_TOKEN }}

JamesIves/github-pages-deploy-action

The following example uses an action from https://github.com/JamesIves/github-pages-deploy-action to publish to GitHub Pages.

The following .github/workflows/main.yml will ensure that mdbook build and mdbook test run successfully, and deploy to GitHub Pages.

name: CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    name: Build, Test and Deploy
    runs-on: ubuntu-latest
    permissions:
      contents: write  # To push a branch 
      pull-requests: write  # To create a PR from that branch
    steps:
      - uses: actions/checkout@v4
      - uses: actions-rs/toolchain@v1
        with:
          toolchain: stable
      - run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4" mdbook)
      - run: mdbook build && mdbook test # In case of custom book path: mdbook build path/to/mybook && mdbook test path/to/mybook
      - uses: JamesIves/[email protected]
        with:
          branch: gh-pages # The branch the action should deploy to.
          folder: book # The folder the action should deploy.

Deploy to Vercel

The following workflow will build the book & deploy the contents to Vercel;

NOTE: The following Environment Variables should be added as "Encrypted Secrets in GitHub";

  • VERCEL_TOKEN refers to the special access token which will be used to authenticate the login session in the CI/CD environment. Refer to this support article on Vercel Access Token for more information.
  • The VERCEL_PROJECT_ID & VERCEL_ORG_ID are found inside the .vercel/project.json file. The said file is generated by invoking the vercel CLI in your project's local repository.
name: Build Book & Deploy to Vercel

env:
  VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
  VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}

on: [push]

jobs:
  buildAndDeploy:
    runs-on: ubuntu-latest
    permissions:
      contents: write  # To push a branch 
      pull-requests: write  # To create a PR from that branch
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4

      - name: Install mdBook
        uses: extractions/setup-crate@v1
        with:
          owner: rust-lang
          name: mdBook

      - name: Generate static content for the book
        run: mdbook build

      - name: Setup Node.js (required to install Vercel CLI)
        uses: actions/setup-node@v3

      - name: Install Vercel CLI
        run: npm install --global vercel

      - name: Pull Vercel environment information
        run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}

      - name: Deploy to Vercel
        run: vercel book --prod --token=${{ secrets.VERCEL_TOKEN }}