I have been enjoying learning some Rust and some Macroquad game development via Olle Wreede’s tutorial (Swedish only so far, sorry!). When I sent some pull requests towards the tutorial I lacked a deployed version attached to the PR. I decided to add that, and my goto for such things is Netlify. However, the tutorial is authored with mdBook, and there doesn’t seem to be a straightforward way to get Netlify to build this.
I figured out a bit of a roundabout way, but before I describe the solution, let’s look at what the problem is about.
I want to solve it with Netlify’s build system, without involving a second CI/CD for it.
Netlify has
rustup
andcargo
pre-installed, but the support seems to be designed to build Rust apps and/or libraries. At least to get caching of the dependencies.The book in question depends not only on
mdbook
, but also onmdbook-quiz
,mdbook-catppuccin
, andmdbook-admonish
.Doing a straight
cargo install mdbook mdbook-quiz mdbook-catppuccin
takes an awful lot of time. Like 5 minutes. I don’t have that kind of patience waiting for feedback.
I did find a closed
issue, with a solution that people seemed happy with, on Netlify
about support for mdBook. It was about downloading an
mdbook
binary. I imagine it is quicker than
cargo install
, but I would still have to install the
plugins and it seemed a bit messy to download individual binaries for
each.
My solution was to “trick” Netlify to cache the dependencies by
creating a dummy Rust app in the repository, and add the mdBook build
tools to build-dependencies
of that dummy app. Then to run
mdbook build
with the directory of these binaries on the
PATH
.
Here follows the relevant files to make this work. Please note that
the repository has the actual book project in a subdirectory,
macroquad-introduction-book
.
Netlify needs a Rust toolchain file,
macroquad-introduction-book/rust-toolchain.toml
:
[toolchain]
channel = "stable"
To get the caching of the dependencies I need a cargo configuration
in macroquad-introduction-book/Cargo.toml
:
# Dummy project to cache book build dependencies with Netlify
[package]
name = "macroquad-introduktion"
version = "0.1.0"
edition = "2021"
[build-dependencies]
mdbook = "*"
mdbook-quiz = "*"
mdbook-catppuccin = "*"
mdbook-admonish = "*"
The cargo
command needs either a
\[\[bin\]\]
configuration (or so it tells me, and I am too
noobish to understand how it works) or a main.rs
file. I
chose the latter,
macroquad-introduction-book/src/main.rs
:
// Dummy project to cache book build dependencies with Netlify
fn main() {
println!("Hello, world!");
}
We also need to configure Netlify. I like to do it via
netlify.toml
, rather than clicking around in the web
UI:
[build]
base = "macroquad-introduction-book"
publish = "book"
command = "cargo build --release && export
PATH=\"$PATH:$(pwd)/target/release/build\" && mdbook build"
[context.master]
command = "cargo build --release && export
PATH=\"$PATH:$(pwd)/target/release/build\" && mdbook build"
[context.branch-deploy]
command = "cargo build --release && export
PATH=\"$PATH:$(pwd)/target/release/build\" && mdbook build"
In this configuration, the important part is the
command
. We use cargo build
to build the dummy
app and force the caching of the mdbook
tools. Then we
place the build
directory on the path before we run
mdbook build
. This way the mdbook
command is
found and the plugins will be found as well.
And there it is. With the caching, subsequent builds of the book goes from 5+ minutes to 15 seconds. 15 seconds is an OK wait time for the result of a pull request to build, I think.