Skip to content

Commit 7b0e371

Browse files
authored
Merge pull request #262 from eccenca/feature/zensical-mike
Zensical publishing: mike fork, publish task, preview
2 parents 84390da + 69aace3 commit 7b0e371

13 files changed

Lines changed: 1397 additions & 52 deletions

File tree

README.md

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,23 @@ If you consider to contribute to this project, please have a look on [CONTRIBUTI
1616
The site is built with [Zensical](https://zensical.org), the successor to Material for
1717
MkDocs. Run `task build` to build into `site/` and `task check` for the full check suite.
1818

19-
For previewing there are two tasks, and the difference matters:
19+
For previewing there are two tasks:
2020

21-
| Task | Live reload | Shows the site as it ships |
22-
| :--- | :---------- | :------------------------- |
23-
| `task serve` | yes | **no** |
24-
| `task preview` | no | yes |
21+
| Task | Live reload | Shows |
22+
| :--- | :---------- | :---- |
23+
| `task serve` | yes | the pages as you write them |
24+
| `task public:preview` | no | the site as it will be published |
2525

26-
`zensical serve` rebuilds into `site/` on every change, which would overwrite whatever the
27-
post-build steps produce - so its preview has no tag listings and still loads `glightbox`
28-
from a CDN. `task preview` builds once with every post-build step and serves the result on
29-
port 8001 (override with `PORT=…`). Use `serve` while writing prose, `preview` before you
30-
trust what you see.
26+
Use `serve` while writing prose. It rebuilds into `site/` on every change, which overwrites
27+
what the post-build steps produced, so it loads `glightbox` and the ResizeObserver polyfill
28+
from a CDN instead of from the vendored copies - invisible on screen, and nothing
29+
downstream trusts a `site/` left behind that way.
30+
31+
`task public:preview` is the one to run before publishing: it deploys into a throwaway copy
32+
of the `published` branch, serves that on port 8002 (override with `PORT=…`), and deletes
33+
the branch again when you stop it. Because it is `public:deploy` pointed at a scratch
34+
branch, what it serves is what publishing produces - versioned URLs, the version selector,
35+
the outdated-version banner and the root redirect included.
3136

3237
Two Material for MkDocs features are **not yet implemented by Zensical** and are
3338
therefore missing from the output. They are tracked in `tools/check_zensical_output.py`,
@@ -45,10 +50,29 @@ check** - the build fails if any of it regresses:
4550
| Feature | Replaced by |
4651
| :------ | :---------- |
4752
| Self-hosted fonts | `docs/assets/fonts.css` plus `theme.font: false` |
48-
| `tablesort`, `glightbox` | vendored under `docs/assets/`; `tools/localize_bundle_assets.py` rewrites the CDN URLs Zensical bakes into its JS bundle |
53+
| `tablesort`, `glightbox`, `resize-observer-polyfill` | vendored under `docs/assets/`; `tools/localize_bundle_assets.py` rewrites the CDN URLs Zensical bakes into its JS bundle |
4954
| Redirects | static stubs under `docs/` |
5055
| Comment opt-out | `overrides/partials/comments.html` |
5156

57+
### Vendored third-party assets
58+
59+
Serving these from our own origin is what keeps visitor IP addresses away from third
60+
parties - but it also makes us their redistributor, so each copy carries its licence:
61+
62+
| Asset | Version | Licence | Upstream |
63+
| :---- | :------ | :------ | :------- |
64+
| `assets/glightbox/glightbox.min.{js,css}` | 3.3.1 | MIT, © 2018 Biati Digital | [glightbox](https://github.com/biati-digital/glightbox) |
65+
| `assets/resize-observer-polyfill/ResizeObserver.global.js` | 1.5.1 | MIT, © 2016 Denis Rul | [resize-observer-polyfill](https://github.com/que-etc/resize-observer-polyfill) |
66+
| `assets/tablesort.min.js` | 5.2.1 | MIT, © 2021 Tristen Brown | [tablesort](http://tristen.ca/tablesort/demo/) |
67+
| `assets/fonts/*.woff2` | - | Apache-2.0 | Roboto and Roboto Mono via Google Fonts |
68+
69+
The files are byte-identical to their upstream builds except for a prepended `/*! … */`
70+
licence banner, which is the notice MIT asks to travel with a copy; the full licence text
71+
sits next to each one where upstream ships it. Three of the URLs Zensical bakes into its
72+
bundle are deliberately **not** vendored - mermaid, Ace and Pyodide are unreachable for
73+
this corpus, and `localize_bundle_assets.py` fails the build if a page ever starts using
74+
one.
75+
5276
Tag listings and the links from each page's tag chips to them are **native** as of
5377
Zensical 0.0.58. The local stand-ins for both - a post-build renderer and a `tags.html`
5478
partial override - are gone; the Markdown sources still carry Material's own

Taskfile.yml

Lines changed: 68 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ dotenv: ['.env']
77

88
vars:
99
PUBLIC_BRANCH: published
10+
# Throwaway branch used by public:preview. Never pushed, recreated on every
11+
# run and deleted again when the preview server stops.
12+
PREVIEW_BRANCH: publish-preview
1013
CURRENT_VERSION: 26.2
1114
# the markdown linter command, used by format:fix:path and check:rumdl
1215
RUMDL_CHECK: poetry run rumdl --config .markdownlint.jsonc check
@@ -42,6 +45,9 @@ tasks:
4245
run: once
4346
cmds:
4447
- rm -rf site
48+
# Only ever the throwaway branch of public:preview, which normally deletes
49+
# itself; this catches the run that was killed before it could.
50+
- git branch -D {{.PREVIEW_BRANCH}} >/dev/null 2>&1 || true
4551

4652
install:
4753
desc: Install needed dependencies
@@ -123,25 +129,19 @@ tasks:
123129

124130
serve:
125131
desc: Serve the page on localhost with live reload (no post-build steps)
126-
# `zensical serve` rebuilds into site/ on every change, which would overwrite
127-
# anything the post-build steps in `build` produce. So this preview still
128-
# loads glightbox from unpkg. Use `task preview` when you need to see the
129-
# site exactly as it ships.
132+
# `zensical serve` rebuilds into site/ on every change, which overwrites what
133+
# the post-build steps in `build` produced - so this preview loads glightbox
134+
# and the ResizeObserver polyfill from unpkg rather than from our vendored
135+
# copies. Nothing downstream consumes a site/ left behind this way: `build`
136+
# and `check:output` rebuild, and `public:deploy` refuses a site/ whose
137+
# canonical URL is unversioned, which such a rebuild always is.
138+
#
139+
# Use `task public:preview` to see the site as it will actually be published.
130140
deps:
131141
- task: install
132142
cmds:
133143
- poetry run zensical serve
134144

135-
preview:
136-
desc: Build with all post-build steps and serve the result (no live reload)
137-
deps:
138-
- task: build
139-
vars:
140-
PORT: '{{.PORT | default "8001"}}'
141-
cmds:
142-
- echo "Serving the fully built site on http://localhost:{{.PORT}} - Ctrl-C to stop"
143-
- python3 -m http.server {{.PORT}} --directory site
144-
145145
update:icons:
146146
desc: update the used eccenca icons from carbon
147147
cmds:
@@ -264,12 +264,28 @@ tasks:
264264

265265
public:deploy:
266266
desc: Publish the working directory as version {{.CURRENT_VERSION}}
267+
summary: |
268+
Builds the site and commits it as version {{.CURRENT_VERSION}} on the
269+
{{.PUBLIC_BRANCH}} branch. Nothing is pushed - that stays a deliberate
270+
`git push` afterwards.
271+
272+
Deliberately not `mike deploy`: that builds the site itself, without
273+
`--strict` and without the post-build steps below, and its rebuild would
274+
overwrite them anyway. So the build happens here and `dec-tool publish`
275+
hands the result to mike, which still owns versions.json, the aliases and
276+
the root redirect.
277+
278+
MIKE_DOCS_VERSION is what makes the pages carry a versioned canonical URL;
279+
`dec-tool publish` refuses to commit a site/ built without it.
267280
deps:
268281
- task: install
269282
cmds:
283+
- MIKE_DOCS_VERSION={{.CURRENT_VERSION}} task build
270284
- >
271-
poetry run mike deploy -b {{.PUBLIC_BRANCH}}
272-
--update-aliases {{.CURRENT_VERSION}} latest
285+
poetry run dec-tool publish
286+
--branch {{.PUBLIC_BRANCH}}
287+
--version {{.CURRENT_VERSION}}
288+
--alias latest
273289
274290
public:serve:
275291
desc: Start a webserver to manually validate the public branch
@@ -278,6 +294,42 @@ tasks:
278294
cmds:
279295
- poetry run mike serve -b {{.PUBLIC_BRANCH}}
280296

297+
public:preview:
298+
desc: Rehearse a deployment on a throwaway branch and serve it
299+
summary: |
300+
Deploys the working directory into a throwaway copy of the public branch,
301+
serves it on localhost, and deletes that branch again when the server
302+
stops. Nothing is pushed and {{.PUBLIC_BRANCH}} is never touched.
303+
304+
The rehearsal is public:deploy itself, pointed at the throwaway branch, so
305+
what it serves is exactly what publishing would produce.
306+
307+
Ctrl-C removes the branch. Should the process be killed harder than that,
308+
`task clean` removes it, as does the next run.
309+
310+
task public:preview PORT=9000
311+
deps:
312+
- task: install
313+
vars:
314+
PORT: '{{.PORT | default "8002"}}'
315+
cmds:
316+
# Deleted when the server stops: `defer` runs on Ctrl-C too, since that
317+
# reaches mike and Task alike.
318+
- defer: git branch -D {{.PREVIEW_BRANCH}} >/dev/null 2>&1 || true
319+
# Start from the branch as it stands - locally if it exists, otherwise as
320+
# last fetched - so the rehearsal shows the new version among the existing
321+
# ones: version selector, outdated banner and root redirect included.
322+
- |
323+
base={{.PUBLIC_BRANCH}}
324+
git show-ref --verify --quiet refs/heads/{{.PUBLIC_BRANCH}} \
325+
|| base=origin/{{.PUBLIC_BRANCH}}
326+
git branch -f --no-track {{.PREVIEW_BRANCH}} "$base"
327+
- task: public:deploy
328+
vars:
329+
PUBLIC_BRANCH: "{{.PREVIEW_BRANCH}}"
330+
- echo "Serving the deployment rehearsal on http://localhost:{{.PORT}} - Ctrl-C to stop and discard it"
331+
- poetry run mike serve -b {{.PREVIEW_BRANCH}} --dev-addr localhost:{{.PORT}}
332+
281333
format:fix:path:
282334
internal: true
283335
summary: |

docs/assets/glightbox/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2018 Biati Digital https://www.biati.digital
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)