blob: fc2c8504dc77af77c91b0dcad82f80adaf1bd852 [file] [edit]
name: CI for specs
on:
push:
branches: [ main ]
paths: [ .github/**, document/**, spectec/src/**, specification/** ]
pull_request:
branches: [ main ]
paths: [ .github/**, document/**, spectec/src/**, specification/** ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
permissions:
contents: read
# Path within the published site recording the commit the baseline was rendered
# from, both as provenance and so a run can tell the copy is still current.
env:
BASELINE_STAMP: upstream/baseline-sha
jobs:
ensure-wasm-latest:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Diff wasm-latest
if: ${{ github.repository == 'WebAssembly/spec' }}
run: cd specification && bash diff-wasm-latest.sh
# Forks (i.e. proposal repos) also render the spec at the commit where they
# last diverged from their parent repo, so the proposal can be compared
# against an unmodified baseline. That baseline is published under /upstream.
resolve-baseline:
runs-on: ubuntu-latest
outputs:
variants: ${{ steps.resolve.outputs.variants }}
# The commit the baseline is rendered from, empty when there is none. A
# baseline absent from variants is one already published under /upstream.
base-sha: ${{ steps.resolve.outputs.base-sha }}
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
# merge-base needs the full history
fetch-depth: 0
- name: Resolve upstream baseline
id: resolve
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail
# Written once on whichever path exits below, so these defaults stand
# unless the checks further down replace them.
variants='["head"]'
base=''
write_outputs() {
echo "variants=$variants" >> "$GITHUB_OUTPUT"
echo "base-sha=$base" >> "$GITHUB_OUTPUT"
}
trap write_outputs EXIT
if [ "$REPOSITORY" = "WebAssembly/spec" ]; then
echo "Canonical repo, no upstream baseline."
exit 0
fi
# A copy already on the site is left in place unless a newer baseline
# is rendered below.
published=''
if encoded=$(gh api "repos/$REPOSITORY/contents/$BASELINE_STAMP?ref=gh-pages" --jq .content 2>/dev/null); then
published=$(printf '%s' "$encoded" | base64 -d | tr -d '[:space:]')
fi
parent=$(gh api "repos/$REPOSITORY" --jq '.parent.full_name // ""' 2>/dev/null) || parent=''
if [ -z "$parent" ]; then
echo "::warning::Could not determine the parent repo, not rendering an upstream copy."
exit 0
fi
if ! git fetch --no-tags --quiet "https://github.com/$parent.git" main; then
echo "::warning::Could not fetch $parent, not rendering an upstream copy."
exit 0
fi
if ! merge_base=$(git merge-base HEAD FETCH_HEAD); then
echo "::warning::No common ancestor with $parent, no upstream copy."
exit 0
fi
if [ "$merge_base" = "$(git rev-parse HEAD)" ]; then
echo "::notice::No divergence from $parent, no upstream copy."
exit 0
fi
base=$merge_base
if [ "$base" = "$published" ]; then
echo "::notice::Baseline $base is already published, keeping that copy."
exit 0
fi
echo "Upstream baseline: $base (from $parent)"
variants='["head","upstream"]'
build-core-spec:
runs-on: ubuntu-latest
needs: resolve-baseline
strategy:
fail-fast: false
matrix:
variant: ${{ fromJSON(needs.resolve-baseline.outputs.variants) }}
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
submodules: "recursive"
ref: ${{ matrix.variant == 'upstream' && needs.resolve-baseline.outputs.base-sha || '' }}
- name: Setup OCaml
uses: ocaml/setup-ocaml@v3
with:
ocaml-compiler: 5.04.x
- name: Setup Dune
run: opam install --yes dune menhir mdx zarith && opam exec dune --version
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 16
- name: Setup Bikeshed
run: pip install bikeshed && bikeshed update
- name: Setup TexLive
run: sudo apt-get update -y && sudo apt-get install -y latexmk texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended
- name: Setup Sphinx
run: pip install six && pip install sphinx==8.1.3
- name: Build SpecTec
run: cd spectec && opam exec make
- name: Build main spec
run: cd document/core && opam exec make main
- name: Run Bikeshed
run: cd document/core && opam exec make bikeshed
- name: Stage artifact at its path on the site
run: mkdir -p _site && mv document/core/_build/html _site/core
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: core-rendered-${{ matrix.variant }}
path: _site
build-js-api-spec:
runs-on: ubuntu-latest
needs: resolve-baseline
strategy:
fail-fast: false
matrix:
variant: ${{ fromJSON(needs.resolve-baseline.outputs.variants) }}
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
ref: ${{ matrix.variant == 'upstream' && needs.resolve-baseline.outputs.base-sha || '' }}
- name: Setup Bikeshed
run: pip install bikeshed && bikeshed update
- name: Run Bikeshed
run: bikeshed spec "document/js-api/index.bs" "document/js-api/index.html"
- name: Stage artifact at its path on the site
run: mkdir -p _site/js-api && mv document/js-api/index.html _site/js-api/
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: js-api-rendered-${{ matrix.variant }}
path: _site
build-web-api-spec:
runs-on: ubuntu-latest
needs: resolve-baseline
strategy:
fail-fast: false
matrix:
variant: ${{ fromJSON(needs.resolve-baseline.outputs.variants) }}
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
ref: ${{ matrix.variant == 'upstream' && needs.resolve-baseline.outputs.base-sha || '' }}
- name: Setup Bikeshed
run: pip install bikeshed && bikeshed update
- name: Run Bikeshed
run: bikeshed spec "document/web-api/index.bs" "document/web-api/index.html"
- name: Stage artifact at its path on the site
run: mkdir -p _site/web-api && mv document/web-api/index.html _site/web-api/
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: web-api-rendered-${{ matrix.variant }}
path: _site
build-code-metadata-spec:
runs-on: ubuntu-latest
needs: resolve-baseline
strategy:
fail-fast: false
matrix:
variant: ${{ fromJSON(needs.resolve-baseline.outputs.variants) }}
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
submodules: "recursive"
ref: ${{ matrix.variant == 'upstream' && needs.resolve-baseline.outputs.base-sha || '' }}
- name: Setup TexLive
run: sudo apt-get update -y && sudo apt-get install -y latexmk texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended
- name: Setup Sphinx
run: pip install six && pip install sphinx==8.1.3
- name: Build main spec
run: cd document/metadata/code && make main
- name: Stage artifact at its path on the site
run: mkdir -p _site/metadata && mv document/metadata/code/_build/html _site/metadata/code
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: code-metadata-rendered-${{ matrix.variant }}
path: _site
build-legacy-exceptions-core-spec:
runs-on: ubuntu-latest
needs: resolve-baseline
strategy:
fail-fast: false
matrix:
variant: ${{ fromJSON(needs.resolve-baseline.outputs.variants) }}
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
submodules: "recursive"
ref: ${{ matrix.variant == 'upstream' && needs.resolve-baseline.outputs.base-sha || '' }}
- name: Setup TexLive
run: sudo apt-get update -y && sudo apt-get install -y latexmk texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended
- name: Setup Sphinx
run: pip install six && pip install sphinx==8.1.3
- name: Build main spec
run: cd document/legacy/exceptions/core && make main
- name: Stage artifact at its path on the site
run: mkdir -p _site/legacy/exceptions && mv document/legacy/exceptions/core/_build/html _site/legacy/exceptions/core
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: legacy-exceptions-core-rendered-${{ matrix.variant }}
path: _site
build-legacy-exceptions-js-api-spec:
runs-on: ubuntu-latest
needs: resolve-baseline
strategy:
fail-fast: false
matrix:
variant: ${{ fromJSON(needs.resolve-baseline.outputs.variants) }}
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
ref: ${{ matrix.variant == 'upstream' && needs.resolve-baseline.outputs.base-sha || '' }}
- name: Setup Bikeshed
run: pip install bikeshed && bikeshed update
- name: Run Bikeshed
run: bikeshed spec "document/legacy/exceptions/js-api/index.bs" "document/legacy/exceptions/js-api/index.html"
- name: Stage artifact at its path on the site
run: mkdir -p _site/legacy/exceptions/js-api && mv document/legacy/exceptions/js-api/index.html _site/legacy/exceptions/js-api/
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: legacy-exceptions-js-api-rendered-${{ matrix.variant }}
path: _site
build-spec-versions:
runs-on: ubuntu-latest
needs: resolve-baseline
strategy:
fail-fast: false
matrix:
variant: ${{ fromJSON(needs.resolve-baseline.outputs.variants) }}
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
ref: ${{ matrix.variant == 'upstream' && needs.resolve-baseline.outputs.base-sha || '' }}
- name: Stage artifact at its path on the site
run: mkdir -p _site && mv document/versions _site/versions
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: versions-rendered-${{ matrix.variant }}
path: _site
publish-spec:
runs-on: ubuntu-latest
permissions:
contents: write
needs:
- ensure-wasm-latest
- resolve-baseline
- build-core-spec
- build-js-api-spec
- build-web-api-spec
- build-code-metadata-spec
- build-legacy-exceptions-core-spec
- build-legacy-exceptions-js-api-spec
- build-spec-versions
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
# The baseline's index.html is read out of the history below
fetch-depth: 0
- name: Create output directory
run: mkdir _output && cp document/index.html _output/index.html
- name: Download rendered documents
uses: actions/download-artifact@v4
with:
pattern: '*-rendered-head'
merge-multiple: true
path: _output
- name: Download upstream baseline documents
if: contains(fromJSON(needs.resolve-baseline.outputs.variants), 'upstream')
uses: actions/download-artifact@v4
with:
pattern: '*-rendered-upstream'
merge-multiple: true
path: _output/upstream
- name: Record the upstream baseline
if: contains(fromJSON(needs.resolve-baseline.outputs.variants), 'upstream')
env:
BASE_SHA: ${{ needs.resolve-baseline.outputs.base-sha }}
run: |
set -euo pipefail
git show "$BASE_SHA:document/index.html" > _output/upstream/index.html
echo "$BASE_SHA" > "_output/$BASELINE_STAMP"
- name: Keep the upstream baseline copy already published
if: needs.resolve-baseline.outputs.base-sha != '' && !contains(fromJSON(needs.resolve-baseline.outputs.variants), 'upstream')
run: |
set -euo pipefail
# Publishing replaces the whole site, so the copy has to be carried
# over explicitly rather than just left in place.
git fetch --no-tags --depth 1 origin gh-pages
git archive FETCH_HEAD upstream | tar -x -C _output
- name: Publish to GitHub Pages
if: github.ref == 'refs/heads/main'
uses: peaceiris/actions-gh-pages@v4
with:
publish_dir: ./_output
github_token: ${{ secrets.GITHUB_TOKEN }}