-
-
Notifications
You must be signed in to change notification settings - Fork 0
156 lines (146 loc) · 7.66 KB
/
Copy pathpublish.yaml
File metadata and controls
156 lines (146 loc) · 7.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
name: publishing
on:
push:
branches:
# `main` is the ONLY publishing branch. It declares everything it
# publishes in docs-version.yml, including the RIDDL 1.x maintenance
# line, which lives in sites/riddl-1x/ rather than on a branch of its own
# (TASK G, 2026-07-31). Work branches are deliberately absent: work in
# progress must not refresh the production site.
- main
permissions:
contents: write
# Kept even though only one branch publishes now. Two pushes to main in quick
# succession still start two runs, both committing to gh-pages, and the second
# would be rejected with "fetch first" -- its deploy silently lost. That
# happened for real when main and docs/1.x were pushed seconds apart.
#
# cancel-in-progress is deliberately FALSE: these runs publish, so cancelling
# one drops a deploy rather than deferring it.
#
# Do NOT reach for mike's --ignore-remote-status as a workaround. It does not
# serialise anything; it just overwrites whatever the other run published.
concurrency:
group: gh-pages-deploy
cancel-in-progress: false
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# mike commits into the gh-pages branch, so its history must be
# present locally. The default shallow checkout does not fetch it.
fetch-depth: 0
- name: Configure Git Credentials
run: |
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
- uses: actions/setup-python@v5
with:
python-version: 3.x
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
- uses: actions/cache@v4
with:
key: mkdocs-material-${{ env.cache_id }}
path: .cache
restore-keys: |
mkdocs-material-
- run: pip install -r requirements.txt
- run: pip install -e .
# Shared logos and CSS live once in common/ and are copied into each
# sub-site's docs tree. The copies are gitignored, so this is required
# before any build -- without it every page loses its stylesheet.
- name: Sync shared assets
run: ./scripts/sync-shared-assets.sh
# Cross-site links are absolute, so MkDocs treats them as external and
# never checks them. --strict proves the intra-site links; this proves
# the rest. Run before deploying anything.
- name: Check cross-site links
run: python3 scripts/check-cross-site-links.py
- name: Deploy each versioned sub-site
run: |
python - <<'PY' > /tmp/deploy.sh
import yaml, shlex
cfg = yaml.safe_load(open("docs-version.yml"))
for s in cfg.get("sites") or []:
url = f"https://ossum.tech/{s['prefix']}/{s['version']}/"
args = " ".join(shlex.quote(a) for a in (s.get("aliases") or []))
# --alias-type copy is REQUIRED, not a preference. mike's default
# is `symlink`, and GitHub Pages does not serve symlinked content
# -- so /riddl/latest/... would 404 in production while working
# perfectly under a local `python -m http.server`, which DOES
# follow symlinks. A passing local rehearsal cannot catch it.
print(f"echo '--> {s['prefix']} {s['version']} [{args}]'")
print(f"DOCS_SITE_URL={shlex.quote(url)} mike deploy --push "
f"--update-aliases --alias-type copy "
f"--deploy-prefix {shlex.quote(s['prefix'])} "
f"-F {shlex.quote(s['config'])} "
f"{shlex.quote(s['version'])} {args}")
# Point <prefix>/index.html at this product's default alias.
# NEVER run set-default without --deploy-prefix: it would write a
# redirect over the shell's index.html at the site root.
# -F is required too -- set-default reads mkdocs.yml from the
# working directory to resolve the remote and branch, and there
# is no config at the repo root any more.
default = (s.get("aliases") or [s["version"]])[0]
print(f"mike set-default --push --deploy-prefix "
f"{shlex.quote(s['prefix'])} -F {shlex.quote(s['config'])} "
f"{shlex.quote(default)}")
PY
cat /tmp/deploy.sh
bash -euo pipefail /tmp/deploy.sh
# The shell is not versioned, so mike is not involved. It is built and
# committed to the gh-pages root, touching only the paths it owns --
# never the product prefixes or their versions.json.
- name: Deploy the shell and rebuild the search index
run: |
git fetch origin gh-pages
git worktree add /tmp/ghp origin/gh-pages
# The shell is only published by the branch that declares it. Every
# other branch skips this part but still reaches the indexing step
# below -- see the comment there for why that matters.
SHELL_CFG=$(python -c "import yaml;c=yaml.safe_load(open('docs-version.yml'));print((c.get('shell') or {}).get('config',''))")
if [ -n "$SHELL_CFG" ]; then
DOCS_SITE_URL=https://ossum.tech/ mkdocs build -f "$SHELL_CFG" -d /tmp/shell
# rsync --delete, NOT cp. `cp -r` only ever adds, so a page deleted
# from the shell stayed on gh-pages forever -- /coming-soon/ and
# /find/ both kept serving 200 after being removed from the source.
#
# The excludes are what make --delete safe at the site root: they
# cover everything the shell does NOT own -- the product prefixes
# published by mike, the generated search index and robots.txt, the
# 404 handler copied in below, and the worktree's own .git file.
# Getting this list wrong deletes another product's entire site,
# so add a new prefix here whenever one is added to docs-version.yml.
rsync -a --delete \
--exclude '/riddl/' --exclude '/riddlg/' --exclude '/synapify/' \
--exclude '/pagefind/' --exclude '/robots.txt' \
--exclude '/404.html' --exclude '/.nojekyll' --exclude '/.git' \
/tmp/shell/ /tmp/ghp/
# Copied after, deliberately: the shell build emits its own 404.html
# and this one -- which redirects legacy unversioned links -- wins.
cp scripts/gh-pages-404.html /tmp/ghp/404.html
else
echo "This branch does not publish the shell."
fi
# The cross-site index is rebuilt on EVERY publishing branch, not
# just the one that owns the shell. It indexes each product's
# `latest` alias, and docs/1.x owns riddl/latest -- so if this only
# ran where the shell is built, a docs/1.x push would update the
# published pages while search kept returning their old text, with
# nothing to indicate the index had gone stale.
"$GITHUB_WORKSPACE/scripts/build-search-index.sh" /tmp/ghp
# robots.txt is generated for the same reason: each build writes its
# own sitemap.xml inside its own version directory, and nothing at the
# root references them. A hand-written file would stop listing new
# versions the day after it was written.
"$GITHUB_WORKSPACE/scripts/build-robots-txt.sh" /tmp/ghp
cd /tmp/ghp
git add -A
if git diff --cached --quiet; then
echo "Shell and search index unchanged."
else
git commit -m "Deploy the shell and refresh the cross-site search index"
git push origin HEAD:gh-pages
fi