Running mdbook in Continuous Integration

While the following examples use Travis CI, their principles should straightforwardly transfer to other continuous integration providers as well.

Ensuring Your Book Builds and Tests Pass

Here is a sample Travis CI .travis.yml configuration that ensures mdbook build and mdbook test run successfully. The key to fast CI turnaround times is caching mdbook installs, so that you aren't compiling mdbook on every CI run.

language: rust
sudo: false

cache:
  - cargo

rust:
  - stable

before_script:
  - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update)
  - (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.3" mdbook)
  - cargo install-update -a

script:
  - mdbook build && mdbook test # In case of custom book path: mdbook build path/to/mybook && mdbook test path/to/mybook

Deploying Your Book to GitHub Pages

Following these instructions will result in your book being published to GitHub pages after a successful CI run on your repository's master branch.

First, create a new GitHub "Personal Access Token" with the "public_repo" permissions (or "repo" for private repositories). Go to your repository's Travis CI settings page and add an environment variable named GITHUB_TOKEN that is marked secure and not shown in the logs.

Whilst still in your repository's settings page, navigate to Options and change the Source on GitHub pages to gh-pages.

Then, append this snippet to your .travis.yml and update the path to the book directory:

deploy:
  provider: pages
  skip-cleanup: true
  github-token: $GITHUB_TOKEN
  local-dir: book # In case of custom book path: path/to/mybook/book
  keep-history: false
  on:
    branch: main

That's it!

Note: Travis has a new dplv2 configuration that is currently in beta. To use this new format, update your .travis.yml file to:

language: rust
os: linux
dist: xenial

cache:
  - cargo

rust:
  - stable

before_script:
  - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update)
  - (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.3" mdbook)
  - cargo install-update -a

script:
  - mdbook build && mdbook test # In case of custom book path: mdbook build path/to/mybook && mdbook test path/to/mybook
  
deploy:
  provider: pages
  strategy: git
  edge: true
  cleanup: false
  github-token: $GITHUB_TOKEN
  local-dir: book # In case of custom book path: path/to/mybook/book
  keep-history: false
  on:
    branch: main
  target_branch: gh-pages

Deploying to GitHub Pages manually

If your CI doesn't support GitHub pages, or you're deploying somewhere else with integrations such as Github Pages: note: you may want to use different tmp dirs:

$> git worktree add /tmp/book gh-pages
$> mdbook build
$> rm -rf /tmp/book/* # this won't delete the .git directory
$> cp -rp book/* /tmp/book/
$> cd /tmp/book
$> git add -A
$> git commit 'new book message'
$> git push origin gh-pages
$> cd -

Or put this into a Makefile rule:

.PHONY: deploy
deploy: book
	@echo "====> deploying to github"
	git worktree add /tmp/book gh-pages
	rm -rf /tmp/book/*
	cp -rp book/* /tmp/book/
	cd /tmp/book && \
		git add -A && \
		git commit -m "deployed on $(shell date) by ${USER}" && \
		git push origin gh-pages

Deploying Your Book to GitLab Pages

Inside your repository's project root, create a file named .gitlab-ci.yml with the following contents:

stages:
    - deploy

pages:
  stage: deploy
  image: rust
  variables:
    CARGO_HOME: $CI_PROJECT_DIR/cargo
  before_script:
    - export PATH="$PATH:$CARGO_HOME/bin"
    - mdbook --version || cargo install mdbook
  script:
    - mdbook build -d public
  rules:
    - if: '$CI_COMMIT_REF_NAME == "master"'
  artifacts:
    paths:
      - public
  cache:
    paths:
      - $CARGO_HOME/bin

After you commit and push this new file, GitLab CI will run and your book will be available!