cmc/cleberg.net
My personal web garden & blog.
clone: git clone https://gitbay.org/cmc/cleberg.net.git
main: .github/workflows/build.yml · raw
1name: Build
2
3on:
4 pull_request:
5 push:
6 branches: [main]
7
8permissions:
9 contents: read
10
11env:
12 # Pinned so a new ruff release adds rules on your schedule, not mid-PR.
13 RUFF_VERSION: "0.16.4"
14 # orgo is installed from crates.io, so nothing bumps this automatically —
15 # dependabot does not see `cargo install` in a workflow. Raise it by hand when
16 # a new orgo lands, which is also how you find out orgo broke the site.
17 ORGO_VERSION: "0.22.0"
18
19jobs:
20 # Separate from the build so a lint failure and a broken page are distinct
21 # signals. build.py runs `ruff check --fix` and `ruff format` on development
22 # builds; these are the verifying forms of the same two commands, reading
23 # the same ruff.toml, so CI cannot disagree with a local dev build.
24 lint:
25 runs-on: ubuntu-latest
26 steps:
27 - uses: actions/checkout@v7
28
29 - name: Install ruff
30 run: pipx install "ruff==$RUFF_VERSION"
31
32 - name: Lint
33 run: |
34 ruff --version
35 ruff check --no-fix
36
37 - name: Format
38 run: ruff format --check --diff
39
40 build:
41 runs-on: ubuntu-latest
42 steps:
43 - uses: actions/checkout@v7
44
45 # Compiling orgo takes minutes; the binary only changes when the pinned
46 # version does, so key the cache on it.
47 - name: Cache orgo
48 id: cache-orgo
49 uses: actions/cache@v6
50 with:
51 path: ~/.cargo/bin/orgo
52 key: orgo-${{ env.ORGO_VERSION }}-${{ runner.os }}
53
54 - name: Install orgo
55 if: steps.cache-orgo.outputs.cache-hit != 'true'
56 run: |
57 cargo --version
58 cargo install orgo --version "$ORGO_VERSION" --locked
59
60 - name: Show versions
61 run: |
62 orgo --version
63 python3 --version
64
65 # build.py deploys with rsync when DEPLOY=true and ENV=prod. CI passes
66 # neither, but "we did not set the variable" is an assumption, not a
67 # guarantee. Shadowing rsync with a failing stub turns it into one: if the
68 # deploy path is ever reached from CI, the job fails loudly instead of
69 # quietly reaching for a production host.
70 - name: Block the deploy path
71 run: |
72 mkdir -p "$RUNNER_TEMP/bin"
73 cat > "$RUNNER_TEMP/bin/rsync" <<'EOF'
74 #!/usr/bin/env bash
75 echo "::error::rsync was invoked from CI — the deploy path must never run here" >&2
76 exit 1
77 EOF
78 chmod +x "$RUNNER_TEMP/bin/rsync"
79 echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"
80
81 # ENV=prod is deliberate. The development path in build.py runs
82 # `ruff check --fix` and `ruff format`, which rewrite files in place —
83 # CI should verify the tree, not edit it. Production is also the build
84 # that actually ships, including the onion image-URL rewrite. DEPLOY is
85 # left unset, so main() builds and stops.
86 - name: Build the site
87 env:
88 ENV: prod
89 BUILD: "true"
90 run: python3 build.py
91
92 - name: Check the build produced pages
93 run: |
94 pages=$(find .build -name '*.html' | wc -l)
95 echo "built $pages html pages"
96 if [ "$pages" -lt 100 ]; then
97 echo "::error::only $pages pages built; expected the full site"
98 exit 1
99 fi