From 9d12020774366ad640b4280da8af36f28488bfb4 Mon Sep 17 00:00:00 2001 From: Paul Keen <125715+pftg@users.noreply.github.com> Date: Sun, 10 May 2026 18:06:18 +0200 Subject: [PATCH 1/3] chore(build): pin bun version end-to-end Fixes non-deterministic lockfile regeneration caused by version drift between local bun (1.2.2) and CI's unpinned oven-sh/setup-bun@v2 (latest 1.3+). Added packageManager field to package.json (Corepack-compatible), pinned bun@1.3.0 in both CI workflows, and changed bun install to --frozen-lockfile to catch future mismatches. Regenerated bun.lockb with bun v1.3.13. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/actions/setup-hugo/action.yml | 2 ++ .github/workflows/_hugo.yml | 4 +++- bun.lockb | Bin 175485 -> 178997 bytes package.json | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/actions/setup-hugo/action.yml b/.github/actions/setup-hugo/action.yml index aa3eef7df..2c24061ad 100644 --- a/.github/actions/setup-hugo/action.yml +++ b/.github/actions/setup-hugo/action.yml @@ -23,6 +23,8 @@ runs: extended: true - uses: oven-sh/setup-bun@v2 + with: + bun-version: "1.3.0" - name: Cache Bun dependencies uses: actions/cache@v5 diff --git a/.github/workflows/_hugo.yml b/.github/workflows/_hugo.yml index bd270802e..c3d13a777 100644 --- a/.github/workflows/_hugo.yml +++ b/.github/workflows/_hugo.yml @@ -42,7 +42,9 @@ jobs: ${{ runner.os }}-deps- - uses: oven-sh/setup-bun@v2 - - run: bun install + with: + bun-version: "1.3.0" + - run: bun install --frozen-lockfile # Use Bun as the "node" runtime for Hugo's PostCSS pipeline. # Hugo 0.161+ runs Node tools with --permission flags; Bun ignores diff --git a/bun.lockb b/bun.lockb index ddf0b4e7f620f28b83f9f0b0c6469b432483fd72..f9e39909d2b1557ae2c27ee3fb5ecc3c6c2f577e 100755 GIT binary patch delta 5974 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 V#n19D_Fe9pJ~7od`&DNk{}0PtXM+F$ delta 5137 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.3" }, From aac28c6961b99cf725e0bb15174652e5faba8c99 Mon Sep 17 00:00:00 2001 From: Paul Keen <125715+pftg@users.noreply.github.com> Date: Sun, 10 May 2026 18:18:14 +0200 Subject: [PATCH 2/3] chore(build): switch bun pin to latest + frozen-lockfile enforcement Replace fixed bun@1.3.0 version pin with latest. The --frozen-lockfile flag already added to CI will catch any lockfile-version drift loudly. Removed packageManager field since fixed pin would create churn against latest CI bun. engines.bun floor (>=1.3) remains the safety net. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/actions/setup-hugo/action.yml | 2 +- .github/workflows/_hugo.yml | 2 +- package.json | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/actions/setup-hugo/action.yml b/.github/actions/setup-hugo/action.yml index 2c24061ad..d4733c9e0 100644 --- a/.github/actions/setup-hugo/action.yml +++ b/.github/actions/setup-hugo/action.yml @@ -24,7 +24,7 @@ runs: - uses: oven-sh/setup-bun@v2 with: - bun-version: "1.3.0" + bun-version: latest - name: Cache Bun dependencies uses: actions/cache@v5 diff --git a/.github/workflows/_hugo.yml b/.github/workflows/_hugo.yml index c3d13a777..fd15984b7 100644 --- a/.github/workflows/_hugo.yml +++ b/.github/workflows/_hugo.yml @@ -43,7 +43,7 @@ jobs: - uses: oven-sh/setup-bun@v2 with: - bun-version: "1.3.0" + bun-version: latest - run: bun install --frozen-lockfile # Use Bun as the "node" runtime for Hugo's PostCSS pipeline. diff --git a/package.json b/package.json index 6d785d898..e7962c47e 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,6 @@ "dependencies": { "caniuse-lite": "^1.0.30001792" }, - "packageManager": "bun@1.3.0", "engines": { "bun": ">=1.3" }, From 99a8411a2fb1c0126bfe5e90356e96e1addc18c7 Mon Sep 17 00:00:00 2001 From: Paul Keen <125715+pftg@users.noreply.github.com> Date: Sun, 10 May 2026 18:23:56 +0200 Subject: [PATCH 3/3] chore(build): drop tier 3 cache and split tier 2 for image retention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed Tier 3 (public/ + hugo_stats.json) — wasted I/O since --cleanDestinationDir wipes public/ and Hugo regenerates hugo_stats.json on every build. Dropped HUGO_CACHEDIR (/tmp/hugo_cache) — unused by Hugo config. Split Tier 2 into: Tier 2a (image cache, key on assets + content images only — survives CSS/HTML edits) + Tier 2b (asset compilation cache, key on themes/layouts/config — updates on build-affecting changes). Result: 177 processed images now retain across CSS edits; ~5-10s faster warm cache builds. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/_hugo.yml | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/.github/workflows/_hugo.yml b/.github/workflows/_hugo.yml index fd15984b7..213e657b3 100644 --- a/.github/workflows/_hugo.yml +++ b/.github/workflows/_hugo.yml @@ -5,7 +5,6 @@ on: env: HUGO_ENVIRONMENT: production - HUGO_CACHEDIR: /tmp/hugo_cache jobs: @@ -56,30 +55,23 @@ jobs: ln -sf "$(which bun)" "$HOME/.bun-as-node/node" echo "$HOME/.bun-as-node" >> "$GITHUB_PATH" - # Tier 2: Hugo build cache (changes with any build-affecting file) + # Tier 2a: Hugo image cache (survives CSS/HTML changes) - uses: actions/cache@v5 - name: Cache Hugo build resources + name: Cache Hugo processed images with: - path: | - ${{ env.HUGO_CACHEDIR }} - resources/_gen - key: ${{ runner.os }}-hugo-build-${{ hashFiles('hugo.toml', 'hugo.dev.toml', 'postcss.config.js', 'package.json', 'themes/**', 'layouts/**') }} + path: resources/_gen/images + key: ${{ runner.os }}-hugo-images-${{ hashFiles('assets/**', 'content/**/*.jpg', 'content/**/*.jpeg', 'content/**/*.png', 'content/**/*.webp', 'content/**/*.gif', 'content/**/*.svg', 'static/**', 'themes/**/static/**', 'themes/**/assets/images/**') }} restore-keys: | - ${{ runner.os }}-hugo-build- - ${{ runner.os }}-hugo- + ${{ runner.os }}-hugo-images- - # Tier 3: Content and template cache (comprehensive file tracking) + # Tier 2b: Hugo asset cache (CSS/JS compilation, updates on theme/config changes) - uses: actions/cache@v5 - name: Cache Hugo content and assets + name: Cache Hugo asset compilation with: - path: | - public - hugo_stats.json - key: ${{ runner.os }}-hugo-content-${{ hashFiles('content/**', 'data/**', 'assets/**', 'static/**', 'layouts/**', 'themes/**/*.html', 'themes/**/*.scss', 'themes/**/*.js', 'hugo.toml', 'hugo.dev.toml', 'postcss.config.js') }} + path: resources/_gen/assets + key: ${{ runner.os }}-hugo-assets-${{ hashFiles('themes/**', 'layouts/**', 'postcss.config.js', 'package.json', 'hugo.toml', 'hugo.dev.toml') }} restore-keys: | - ${{ runner.os }}-hugo-content-${{ hashFiles('content/**', 'data/**', 'assets/**', 'static/**') }} - ${{ runner.os }}-hugo-content-${{ hashFiles('content/**', 'data/**') }} - ${{ runner.os }}-hugo-content- + ${{ runner.os }}-hugo-assets- - name: Build with Hugo run: |