diff --git a/.github/workflows/mdbook.yml b/.github/workflows/mdbook.yml index 1f8af1e..a2dc7c7 100644 --- a/.github/workflows/mdbook.yml +++ b/.github/workflows/mdbook.yml @@ -18,7 +18,8 @@ concurrency: cancel-in-progress: false env: - # Repo path on GitHub Pages — change here if the repo is renamed. + # Repo path on GitHub Pages. Forwarded to scripts/build-site.sh so + # per-version SITE_URLs are correct. Change here if the repo moves. SITE_BASE: /meshcore-spec jobs: @@ -30,81 +31,23 @@ jobs: with: fetch-depth: 0 - - name: Install mise + pinned tools (mdbook, etc.) + - name: Install mise uses: jdx/mise-action@v2 with: - install: true + install: false cache: true + - name: Trust mise config + run: mise trust + + - name: Install pinned tools (mdbook, just) + run: mise install + - name: Configure Pages uses: actions/configure-pages@v5 - - name: Build all versions - run: | - set -euo pipefail - - mkdir -p _site - WORKSPACE="$PWD" - - # ---- latest (current ref) ---- - echo "::group::build latest" - MDBOOK_OUTPUT__HTML__SITE_URL="${SITE_BASE}/latest/" \ - mdbook build "$WORKSPACE" -d "$WORKSPACE/_site/latest" - echo "::endgroup::" - - # ---- each v* tag ---- - # Tags are built in worktrees so the workflow's own files (this - # file, the picker JS/CSS) don't bleed into older builds. - mapfile -t TAGS < <(git tag --list 'v*' --sort=-v:refname) - for tag in "${TAGS[@]:-}"; do - [ -z "$tag" ] && continue - echo "::group::build $tag" - wt="$(mktemp -d -t "mdbook-${tag//\//-}-XXXXXX")" - git worktree add --detach "$wt" "$tag" - # If a very old tag lacks book.toml, skip it but don't fail. - if [ -f "$wt/book.toml" ]; then - MDBOOK_OUTPUT__HTML__SITE_URL="${SITE_BASE}/${tag}/" \ - mdbook build "$wt" -d "$WORKSPACE/_site/${tag}" || { - echo "::warning::mdbook build failed for ${tag}; skipping" - rm -rf "$WORKSPACE/_site/${tag}" - } - else - echo "::warning::${tag} has no book.toml; skipping" - fi - git worktree remove --force "$wt" - echo "::endgroup::" - done - - # ---- versions.json (consumed by theme/version-picker.js) ---- - # Newest first; "latest" always at the top. - { - printf '[' - printf '"latest"' - for tag in "${TAGS[@]:-}"; do - [ -z "$tag" ] && continue - [ -d "_site/${tag}" ] || continue - printf ',"%s"' "$tag" - done - printf ']\n' - } > _site/versions.json - echo "versions.json:" - cat _site/versions.json - - # ---- root redirect to /latest/ ---- - cat > _site/index.html <<'HTML' - - -
- - - -Redirecting to the latest version…
- - - HTML + - name: Build full multi-version site + run: just build-site - name: Upload Pages artifact uses: actions/upload-pages-artifact@v3 diff --git a/.gitignore b/.gitignore index fd5bab0..f84d842 100644 --- a/.gitignore +++ b/.gitignore @@ -21,5 +21,6 @@ Thumbs.db /dist/ /references/ -# mdBook output +# mdBook output (single-version and multi-version) /book/ +/_site/ diff --git a/justfile b/justfile index e586b90..30a88fe 100644 --- a/justfile +++ b/justfile @@ -15,10 +15,15 @@ _default: setup: mise install -# Build the spec into ./book/. +# Build the spec into ./book/ (single-version; for local dev). build: mdbook build +# Build the full multi-version site into ./_site/ (latest + every v* tag). +# This is exactly what CI runs. +build-site: + sh scripts/build-site.sh + # Live-preview the spec at http://localhost:3000 with auto-reload. serve: mdbook serve --open --port 3000 diff --git a/mise.toml b/mise.toml index 5a8e3bb..03dd314 100644 --- a/mise.toml +++ b/mise.toml @@ -6,3 +6,4 @@ [tools] "cargo:mdbook" = "0.5.2" +just = "1.50.0" diff --git a/scripts/build-site.sh b/scripts/build-site.sh new file mode 100755 index 0000000..10dd600 --- /dev/null +++ b/scripts/build-site.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env sh +# Build the full multi-version site into ./_site/: +# - "latest" from the current HEAD +# - one subtree per v* git tag +# +# Each per-version build gets MDBOOK_OUTPUT__HTML__SITE_URL set so its +# canonical URL and sitemap are correct for the deployed location. +# Emits _site/versions.json (newest first; consumed by +# theme/version-picker.js) and a root index.html that redirects to +# /latest/. +# +# Intended to be called via `just build-site`. SITE_BASE can be +# overridden to deploy under a different URL prefix; the default +# targets https://swaits.github.io/meshcore-spec/. + +set -eu + +SITE_BASE="${SITE_BASE:-/meshcore-spec}" +WORKSPACE="$(pwd)" +SITE_DIR="$WORKSPACE/_site" + +# Section grouping for GitHub Actions logs; noop locally. +group() { printf '::group::%s\n' "$1"; } +endgroup() { printf '::endgroup::\n'; } +warn() { printf '::warning::%s\n' "$1"; } + +rm -rf "$SITE_DIR" +mkdir -p "$SITE_DIR" + +# ---- latest (current HEAD) ---- +group "build latest" +MDBOOK_OUTPUT__HTML__SITE_URL="${SITE_BASE}/latest/" \ + mdbook build "$WORKSPACE" -d "$SITE_DIR/latest" +endgroup + +# ---- each v* tag ---- +# Each tag is built from its own git worktree so today's mdbook config +# / theme files don't bleed into older builds. +TAGS="$(git tag --list 'v*' --sort=-v:refname 2>/dev/null || true)" +for tag in $TAGS; do + [ -z "$tag" ] && continue + group "build $tag" + wt="$(mktemp -d -t mdbook-tag-XXXXXX)" + git worktree add --detach "$wt" "$tag" + if [ -f "$wt/book.toml" ]; then + if ! MDBOOK_OUTPUT__HTML__SITE_URL="${SITE_BASE}/${tag}/" \ + mdbook build "$wt" -d "$SITE_DIR/${tag}"; then + warn "mdbook build failed for ${tag}; skipping" + rm -rf "${SITE_DIR:?}/${tag:?}" + fi + else + warn "${tag} has no book.toml; skipping" + fi + git worktree remove --force "$wt" + endgroup +done + +# ---- versions.json (consumed by theme/version-picker.js) ---- +# Newest first; "latest" always at the top. +{ + printf '[' + printf '"latest"' + for tag in $TAGS; do + [ -z "$tag" ] && continue + [ -d "$SITE_DIR/$tag" ] || continue + printf ',"%s"' "$tag" + done + printf ']\n' +} > "$SITE_DIR/versions.json" +echo "versions.json:" +cat "$SITE_DIR/versions.json" + +# ---- root redirect to /latest/ ---- +cat > "$SITE_DIR/index.html" <<'HTML' + + + + + + +Redirecting to the latest version…
+ + +HTML