docs/content/deploy/github-pages.md (3364B)
1 +++
2 title = "GitHub Pages"
3 description = "Where this site is, and the host that forced the design"
4 weight = 10
5 toc = true
6 +++
7
8 This site is built and deployed by the workflow below, from the same repository
9 as the tool. CI builds `docs/` with the binary it just compiled, so the
10 documentation is a regression test for the generator.
11
12 ## The workflow
13
14 ```yaml
15 name: Deploy docs
16
17 on:
18 push:
19 branches: [main]
20 workflow_dispatch:
21
22 permissions:
23 contents: read
24 pages: write
25 id-token: write
26
27 concurrency:
28 group: pages
29 cancel-in-progress: false
30
31 jobs:
32 build:
33 runs-on: ubuntu-latest
34 steps:
35 - uses: actions/checkout@v7
36 - uses: dtolnay/rust-toolchain@stable
37 - uses: Swatinem/rust-cache@v2
38 - uses: actions/configure-pages@v6
39 - run: cargo run --quiet -- build -i docs
40 - uses: actions/upload-pages-artifact@v5
41 with:
42 path: docs/public
43
44 deploy:
45 needs: build
46 runs-on: ubuntu-latest
47 environment:
48 name: github-pages
49 url: ${{ steps.deployment.outputs.page_url || steps.retry.outputs.page_url }}
50 steps:
51 - id: deployment
52 uses: actions/deploy-pages@v5
53 continue-on-error: true
54
55 - name: Wait for the previous deployment to settle
56 if: steps.deployment.outcome == 'failure'
57 run: sleep 90
58
59 - id: retry
60 if: steps.deployment.outcome == 'failure'
61 uses: actions/deploy-pages@v5
62 ```
63
64 `cancel-in-progress: false` is worth keeping. Cancelling a deploy that is
65 halfway through leaves the site partly updated, which is worse than waiting.
66
67 The retry is not defensive padding — it is the fix for a failure this site hit.
68 `concurrency` serialises workflow *runs*, but a Pages deployment outlives its
69 run: GitHub can still be processing the previous one after the workflow that
70 started it has finished. Push two commits close together and the second lands
71 in that window and dies with a 400, "due to in progress deployment". Waiting and
72 trying once more is enough, and it is safe: the deploy fails before it changes
73 anything, so a retry cannot leave the site half updated.
74
75 ## A custom domain
76
77 Put the domain in `static/CNAME`:
78
79 ```
80 sqzass.sqzer.com
81 ```
82
83 It is copied to the output with its name intact, and GitHub reads it from
84 there — so the domain survives every deploy without being configured in the
85 repository settings again.
86
87 Point DNS at `<user>.github.io` with a `CNAME` record. If your DNS provider
88 proxies traffic, **turn the proxy off for this record**. A proxy that
89 terminates TLS itself will stop GitHub from issuing and renewing the
90 certificate, and the failure shows up weeks later as an expired certificate
91 rather than immediately as a broken deploy.
92
93 ## Checking it
94
95 ```bash
96 curl -sI https://example.com/ | head -1 # 200, over HTTPS
97 curl -sI https://example.com/nonexistent/ # 404, not 200
98 ```
99
100 The second one matters. A host that answers 200 for a missing page will have
101 search engines index your 404.
102
103 ## What you give up
104
105 No custom headers — GitHub Pages serves everything with `max-age=600`. No
106 redirect rules. No preview deployments for pull requests.
107
108 The first two are the reason the output is built the way it is, and the third
109 is `sqzass serve`. If you later need real header control, the answer is moving
110 to a host that has it, not stacking a CDN in front of one that does not.