Add a powered-by-orgo footer note, versioned at build time !1
4 files changed, +79 −10
Layout: unified · split
.gitbay/ci.yml +16 −8
| @@ -45,13 +45,20 @@ jobs: | ||
| 45 | 45 | # orgo is installed from crates.io and takes minutes to compile, so it is |
| 46 | 46 | # rebuilt only when this version changes. Nothing bumps it automatically: |
| 47 | 47 | # raise it by hand, which is also how you find out orgo broke the site. |
| 48 | # | |
| 49 | # --root pins where it lands, like ruff and lychee below. Without it cargo | |
| 50 | # installs under whatever cargo home the runner sets, which is not $HOME: | |
| 51 | # the binary goes somewhere this file does not name, and the next run's | |
| 52 | # `cargo install` declines to repeat itself because its metadata already | |
| 53 | # records the version as installed. | |
| 48 | 54 | - | |
| 49 | 55 | set -eu |
| 50 | 56 | v=0.22.0 |
| 51 | if ! "$HOME/.cargo/bin/orgo" --version 2>/dev/null | grep -qx "orgo $v"; then | |
| 52 | "$HOME/.cargo/bin/cargo" install orgo --version "$v" --locked | |
| 57 | if ! "$HOME/tools/orgo/bin/orgo" --version 2>/dev/null | grep -qx "orgo $v"; then | |
| 58 | "$HOME/.cargo/bin/cargo" install orgo --version "$v" --locked \ | |
| 59 | --root "$HOME/tools/orgo" | |
| 53 | 60 | fi |
| 54 | "$HOME/.cargo/bin/orgo" --version | |
| 61 | "$HOME/tools/orgo/bin/orgo" --version | |
| 55 | 62 | python3 --version |
| 56 | 63 | |
| 57 | 64 | # build.py deploys with rsync when DEPLOY=true and ENV=prod. This build |
| @@ -74,7 +81,7 @@ jobs: | ||
| 74 | 81 | exit 1 |
| 75 | 82 | EOF |
| 76 | 83 | chmod +x .ci-bin/rsync |
| 77 | PATH="$PWD/.ci-bin:$HOME/.cargo/bin:$PATH" ENV=prod BUILD=true python3 build.py | |
| 84 | PATH="$PWD/.ci-bin:$HOME/tools/orgo/bin:$PATH" ENV=prod BUILD=true python3 build.py | |
| 78 | 85 | |
| 79 | 86 | - | |
| 80 | 87 | set -eu |
| @@ -99,10 +106,11 @@ jobs: | ||
| 99 | 106 | | sh -s -- -y --no-modify-path --profile minimal |
| 100 | 107 | fi |
| 101 | 108 | v=0.22.0 |
| 102 | if ! "$HOME/.cargo/bin/orgo" --version 2>/dev/null | grep -qx "orgo $v"; then | |
| 103 | "$HOME/.cargo/bin/cargo" install orgo --version "$v" --locked | |
| 109 | if ! "$HOME/tools/orgo/bin/orgo" --version 2>/dev/null | grep -qx "orgo $v"; then | |
| 110 | "$HOME/.cargo/bin/cargo" install orgo --version "$v" --locked \ | |
| 111 | --root "$HOME/tools/orgo" | |
| 104 | 112 | fi |
| 105 | "$HOME/.cargo/bin/orgo" --version | |
| 113 | "$HOME/tools/orgo/bin/orgo" --version | |
| 106 | 114 | |
| 107 | 115 | # Prebuilt release binary, checksum-verified, kept in $HOME between runs. |
| 108 | 116 | - | |
| @@ -125,7 +133,7 @@ jobs: | ||
| 125 | 133 | # URLs to /img/, which is served from a different docroot and would look |
| 126 | 134 | # like 198 broken links here. The development output keeps them absolute, |
| 127 | 135 | # so the image host gets checked for real. |
| 128 | - $HOME/.cargo/bin/orgo build content -o .build-dev --strict | |
| 136 | - $HOME/tools/orgo/bin/orgo build content -o .build-dev --strict | |
| 129 | 137 | |
| 130 | 138 | # Internal links are the half worth gating on: they are entirely within |
| 131 | 139 | # this repo, so a failure is always a real defect and always fixable here. |
README.md +3 −2
| @@ -66,8 +66,9 @@ For users employing Doom Emacs, open any repository Org file using | ||
| 66 | 66 | |
| 67 | 67 | ## Building and Publishing the Site |
| 68 | 68 | |
| 69 | The `build.py` script wraps the build: it runs orgo, and then either | |
| 70 | deploys the result or serves it locally. | |
| 69 | The `build.py` script wraps the build: it runs orgo, rewrites the footer's | |
| 70 | orgo version to match the orgo that ran, and then either deploys the result | |
| 71 | or serves it locally. | |
| 71 | 72 | |
| 72 | 73 | Environment variables control what it does, and all default to off: |
| 73 | 74 | |
build.py +59
| @@ -4,6 +4,7 @@ This script automates the process of building and deploying the website. | ||
| 4 | 4 | It handles tasks such as: |
| 5 | 5 | |
| 6 | 6 | - Running orgo to generate site content. |
| 7 | - Rewriting the footer's orgo version to match the orgo that built the site. | |
| 7 | 8 | - Rewriting image URLs for the onion service (production only). |
| 8 | 9 | - Optionally deploying the built site to a remote server. |
| 9 | 10 | - Starting a local development server for previewing changes. |
| @@ -77,6 +78,63 @@ def rewrite_img_urls(build_dir=".build"): | ||
| 77 | 78 | print(f"Rewrote {count} img.cleberg.net references to /img/") |
| 78 | 79 | |
| 79 | 80 | |
| 81 | # The footer's "Powered by orgo <version>" note. Matching the whole phrase rewrites a | |
| 82 | # page carrying an old version as readily as one still carrying the template's | |
| 83 | # placeholder, and leaves prose that ends a paragraph with a link to orgo alone. | |
| 84 | ORGO_NOTE = re.compile( | |
| 85 | r'(Powered by <a href="https://gitbay\.org/krz/orgo">orgo</a> )[^<]*(</p>)' | |
| 86 | ) | |
| 87 | ||
| 88 | ||
| 89 | def orgo_version(): | |
| 90 | """The version reported by the orgo on PATH, e.g. "0.22.0".""" | |
| 91 | result = subprocess.run( | |
| 92 | ["orgo", "--version"], capture_output=True, text=True, check=False | |
| 93 | ) | |
| 94 | if result.returncode != 0: | |
| 95 | print("Could not read the orgo version:", file=sys.stderr) | |
| 96 | print(result.stderr, file=sys.stderr) | |
| 97 | sys.exit(1) | |
| 98 | # `orgo --version` prints "orgo X.Y.Z". Anything else means the output format | |
| 99 | # changed, and guessing at it would ship a wrong version to every page. | |
| 100 | parts = result.stdout.split() | |
| 101 | if len(parts) != 2 or parts[0] != "orgo": | |
| 102 | print(f"Unexpected `orgo --version` output: {result.stdout!r}", file=sys.stderr) | |
| 103 | sys.exit(1) | |
| 104 | return parts[1] | |
| 105 | ||
| 106 | ||
| 107 | def rewrite_orgo_version(build_dir): | |
| 108 | """Point the footer's orgo version at the orgo that just built the site. | |
| 109 | ||
| 110 | Runs over every page rather than only the re-rendered ones, because the build cache | |
| 111 | keys on a cache *format* version and not on orgo's release version: after a version | |
| 112 | bump that leaves the format alone, the pages carried over from the previous build | |
| 113 | would otherwise keep printing the old one. | |
| 114 | ||
| 115 | The whole point of this is that the note cannot go stale, so a footer that no longer | |
| 116 | matches is a failure and not a no-op — matching nothing anywhere means the note was | |
| 117 | removed or its markup changed, and a silent pass would ship the template's | |
| 118 | placeholder to every page. | |
| 119 | """ | |
| 120 | version = orgo_version() | |
| 121 | count = 0 | |
| 122 | for html in Path(build_dir).rglob("*.html"): | |
| 123 | text = html.read_text(encoding="utf-8") | |
| 124 | new_text, n = ORGO_NOTE.subn(rf"\g<1>{version}\g<2>", text) | |
| 125 | if n and new_text != text: | |
| 126 | html.write_text(new_text, encoding="utf-8") | |
| 127 | count += n | |
| 128 | if count == 0: | |
| 129 | print( | |
| 130 | "No 'Powered by orgo' note found in the build — the footer in " | |
| 131 | "content/templates/base.html no longer matches ORGO_NOTE", | |
| 132 | file=sys.stderr, | |
| 133 | ) | |
| 134 | sys.exit(1) | |
| 135 | print(f"Set the footer orgo version to {version} on {count} pages") | |
| 136 | ||
| 137 | ||
| 80 | 138 | def run_orgo_build(build_dir): |
| 81 | 139 | """ |
| 82 | 140 | Build the site with orgo. |
| @@ -164,6 +222,7 @@ def main(): | ||
| 164 | 222 | |
| 165 | 223 | if os.environ.get("BUILD", "").casefold() == "true": |
| 166 | 224 | run_orgo_build(build_dir) |
| 225 | rewrite_orgo_version(build_dir) | |
| 167 | 226 | # The onion needs same-origin images; dev previews keep the absolute URLs. |
| 168 | 227 | # Runs over every page, not just the re-rendered ones, so a page carried over |
| 169 | 228 | # from an earlier build is rewritten too. |
content/templates/base.html +1
| @@ -93,6 +93,7 @@ | ||
| 93 | 93 | <a href="{{ root }}tips/index.html">Tips</a> · |
| 94 | 94 | <a href="https://iheartrss.com/">I ♥ RSS</a> |
| 95 | 95 | <p>[ <a href="https://krz.sh">krz</a> · <a href="https://audit-labs.dev">audit labs</a> ]</p> |
| 96 | <p>Powered by <a href="https://gitbay.org/krz/orgo">orgo</a> ORGO_VERSION</p> | |
| 96 | 97 | </footer> |
| 97 | 98 | </body> |
| 98 | 99 | </html> |