From fb80fa83ccab52988987c6e48973bd19023110ff Mon Sep 17 00:00:00 2001 From: Rochet2 Date: Wed, 27 May 2026 04:44:45 +0300 Subject: [PATCH 1/3] Fix asset cache busting on GitHub Pages builds. Commit _data/assets.yml to the repo and validate it in CI, since Pages runs its own Jekyll build and never sees files generated only in Actions. --- .github/workflows/jekyll.yml | 4 +-- .gitignore | 1 - README.md | 4 +-- _data/assets.yml | 1 + _layouts/default.html | 2 +- script/asset_version.py | 54 ++++++++++++++++++++++++++++++++---- 6 files changed, 54 insertions(+), 12 deletions(-) delete mode 100644 .gitignore create mode 100644 _data/assets.yml diff --git a/.github/workflows/jekyll.yml b/.github/workflows/jekyll.yml index 0104ba7..19bad16 100644 --- a/.github/workflows/jekyll.yml +++ b/.github/workflows/jekyll.yml @@ -30,8 +30,8 @@ jobs: - name: Check WebP derivatives run: python script/generate_webp.py --check - - name: Generate asset version - run: python script/asset_version.py + - name: Check asset version + run: python script/asset_version.py --check - name: Setup Pages uses: actions/configure-pages@v5 diff --git a/.gitignore b/.gitignore deleted file mode 100644 index d7f5ac8..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -_data/assets.yml diff --git a/README.md b/README.md index 017a867..d179e28 100644 --- a/README.md +++ b/README.md @@ -97,9 +97,9 @@ CI runs `python script/generate_webp.py --check` to ensure WebP copies are prese ### CSS/JS cache busting -CI runs `python script/asset_version.py` before each Jekyll build. It hashes `css/style.css`, `css/github_markdown.css`, and `js/gallery.js`, then writes `_data/assets.yml`. Layout templates append `?v=` that hash to stylesheet and script URLs so browsers fetch new copies when those files change. +Run `python script/asset_version.py` after changing `css/style.css`, `css/github_markdown.css`, or `js/gallery.js`. It updates `_data/assets.yml`, which is committed to the repo so GitHub Pages can read it during its own Jekyll build. -For a local Jekyll preview, run the same script first: +CI runs `python script/asset_version.py --check` to ensure that file matches the current CSS/JS content (same idea as the WebP check). ```bash python script/asset_version.py diff --git a/_data/assets.yml b/_data/assets.yml new file mode 100644 index 0000000..5327bc1 --- /dev/null +++ b/_data/assets.yml @@ -0,0 +1 @@ +assets_version: "e7eb82e9" diff --git a/_layouts/default.html b/_layouts/default.html index 711f509..224bb3b 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -44,7 +44,7 @@ - {% assign assets_version = site.data.assets.assets_version | default: 'dev' %} + {% assign assets_version = site.data.assets.assets_version | default: site.github.build_revision | default: 'dev' %} diff --git a/script/asset_version.py b/script/asset_version.py index 98b6e23..7c79bfa 100644 --- a/script/asset_version.py +++ b/script/asset_version.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -"""Write _data/assets.yml with a content hash for CSS/JS cache busting.""" +"""Manage _data/assets.yml content hash for CSS/JS cache busting.""" from __future__ import annotations +import argparse import hashlib +import re import sys from pathlib import Path @@ -15,20 +17,60 @@ OUTPUT = Path("_data/assets.yml") -def main() -> int: +def compute_version() -> str: hasher = hashlib.sha256() for path in ASSET_FILES: if not path.is_file(): - print(f"Missing asset file: {path}", file=sys.stderr) - return 1 + raise FileNotFoundError(path) hasher.update(path.read_bytes()) hasher.update(b"\0") - version = hasher.hexdigest()[:8] + return hasher.hexdigest()[:8] + + +def read_version() -> str | None: + if not OUTPUT.is_file(): + return None + + match = re.search(r'^assets_version:\s*"([0-9a-f]+)"\s*$', OUTPUT.read_text(encoding="utf-8"), re.MULTILINE) + return match.group(1) if match else None + + +def write_version(version: str) -> None: OUTPUT.parent.mkdir(exist_ok=True) OUTPUT.write_text(f'assets_version: "{version}"\n', encoding="utf-8") - print(f"Wrote {OUTPUT} (assets_version: {version})") + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "--check", + action="store_true", + help="Fail if _data/assets.yml is missing or does not match current CSS/JS files", + ) + args = parser.parse_args() + + try: + expected = compute_version() + except FileNotFoundError as exc: + print(f"Missing asset file: {exc}", file=sys.stderr) + return 1 + + if args.check: + actual = read_version() + if actual != expected: + print( + f"_data/assets.yml is out of date (have {actual!r}, expected {expected!r}). " + "Run: python script/asset_version.py", + file=sys.stderr, + ) + return 1 + print(f"Asset version OK ({expected})") + return 0 + + write_version(expected) + print(f"Wrote {OUTPUT} (assets_version: {expected})") return 0 From 2cc24ed00d1d804755fad392831e98a128338a18 Mon Sep 17 00:00:00 2001 From: Rochet2 Date: Wed, 27 May 2026 04:47:51 +0300 Subject: [PATCH 2/3] Auto-commit asset version hash on pull requests. Add a CI job that regenerates _data/assets.yml and pushes it to the PR branch when CSS or JS changes, so merges already include the correct cache-busting hash. --- .github/workflows/jekyll.yml | 35 +++++++++++++++++++++++++++++++++++ README.md | 8 ++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/.github/workflows/jekyll.yml b/.github/workflows/jekyll.yml index 19bad16..a80943b 100644 --- a/.github/workflows/jekyll.yml +++ b/.github/workflows/jekyll.yml @@ -11,7 +11,41 @@ permissions: contents: read jobs: + update-asset-version: + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref }} + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Update asset version + run: python script/asset_version.py + + - name: Commit asset version if changed + run: | + if git diff --quiet -- _data/assets.yml; then + echo "Asset version already up to date" + exit 0 + fi + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add _data/assets.yml + git commit -m "Update asset version hash for CSS/JS changes." + git push + build: + needs: update-asset-version + if: always() && (needs.update-asset-version.result == 'success' || needs.update-asset-version.result == 'skipped') runs-on: ubuntu-latest steps: - name: Checkout @@ -31,6 +65,7 @@ jobs: run: python script/generate_webp.py --check - name: Check asset version + if: github.event_name != 'pull_request' run: python script/asset_version.py --check - name: Setup Pages diff --git a/README.md b/README.md index d179e28..ff5dd67 100644 --- a/README.md +++ b/README.md @@ -97,9 +97,13 @@ CI runs `python script/generate_webp.py --check` to ensure WebP copies are prese ### CSS/JS cache busting -Run `python script/asset_version.py` after changing `css/style.css`, `css/github_markdown.css`, or `js/gallery.js`. It updates `_data/assets.yml`, which is committed to the repo so GitHub Pages can read it during its own Jekyll build. +`_data/assets.yml` stores a content hash for `css/style.css`, `css/github_markdown.css`, and `js/gallery.js`. Layout templates append it as `?v=` on stylesheet and script URLs. The file must be in the repo because GitHub Pages runs its own Jekyll build. -CI runs `python script/asset_version.py --check` to ensure that file matches the current CSS/JS content (same idea as the WebP check). +On pull requests, CI runs `script/asset_version.py` and commits an updated `_data/assets.yml` to the PR branch when CSS or JS changed, so the hash is ready before you merge. + +Pushes to `master` run `script/asset_version.py --check` instead (the merged PR should already include the updated file). + +To update locally: ```bash python script/asset_version.py From deeb258d22dba6a6ae0b304cdce761b3f17fcf9a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 27 May 2026 01:48:07 +0000 Subject: [PATCH 3/3] Update asset version hash for CSS/JS changes. --- _data/assets.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_data/assets.yml b/_data/assets.yml index 5327bc1..62d4178 100644 --- a/_data/assets.yml +++ b/_data/assets.yml @@ -1 +1 @@ -assets_version: "e7eb82e9" +assets_version: "8a29461d"