Skip to content

Commit 10f4a95

Browse files
authored
Merge pull request #62 from isaaclins/fix/ci-hugo-version
Fix the broken pipeline: pin Hugo 0.164.0 in CI
2 parents fc0f719 + e88fb75 commit 10f4a95

7 files changed

Lines changed: 130 additions & 9 deletions

File tree

.github/workflows/build-test.yml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ on:
44
push:
55
branches:
66
- main
7+
pull_request:
8+
branches:
9+
- main
710
workflow_dispatch:
811

912
permissions:
@@ -21,15 +24,22 @@ defaults:
2124
jobs:
2225
build-and-test:
2326
runs-on: ubuntu-latest
24-
env:
25-
HUGO_VERSION: 0.140.2
2627
steps:
2728
- name: Checkout repository
2829
uses: actions/checkout@v7
2930
with:
3031
submodules: recursive
3132
fetch-depth: 0
3233

34+
- name: Read Hugo version
35+
run: |
36+
HUGO_VERSION="$(tr -d '[:space:]' < .hugo-version)"
37+
if [[ ! "$HUGO_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
38+
echo "::error::Invalid Hugo version in .hugo-version: $HUGO_VERSION"
39+
exit 1
40+
fi
41+
echo "HUGO_VERSION=$HUGO_VERSION" >> "$GITHUB_ENV"
42+
3343
- name: Install Hugo CLI
3444
run: |
3545
wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
@@ -38,6 +48,9 @@ jobs:
3848
- name: Verify Hugo Version
3949
run: hugo version
4050

51+
- name: Enforce Hugo minimum version
52+
run: python3 scripts/check-hugo-version.py
53+
4154
- name: Install Dart Sass
4255
run: sudo snap install dart-sass
4356

.github/workflows/pages-deploy.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,22 @@ defaults:
2323
jobs:
2424
build:
2525
runs-on: ubuntu-latest
26-
env:
27-
HUGO_VERSION: 0.140.2
2826
steps:
2927
- name: Checkout
3028
uses: actions/checkout@v7
3129
with:
3230
submodules: recursive
3331
fetch-depth: 0
3432

33+
- name: Read Hugo version
34+
run: |
35+
HUGO_VERSION="$(tr -d '[:space:]' < .hugo-version)"
36+
if [[ ! "$HUGO_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
37+
echo "::error::Invalid Hugo version in .hugo-version: $HUGO_VERSION"
38+
exit 1
39+
fi
40+
echo "HUGO_VERSION=$HUGO_VERSION" >> "$GITHUB_ENV"
41+
3542
- name: Install Hugo CLI
3643
run: |
3744
wget -O ${{ runner.temp }}/hugo.deb "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb"
@@ -40,6 +47,9 @@ jobs:
4047
- name: Verify Hugo Version
4148
run: hugo version
4249

50+
- name: Enforce Hugo minimum version
51+
run: python3 scripts/check-hugo-version.py
52+
4353
- name: Install Dart Sass
4454
run: sudo snap install dart-sass
4555

.hugo-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0.164.0

README.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ deployed to GitHub Pages behind Cloudflare at <https://isaaclins.com>.
66

77
## Stack
88

9-
- **Hugo extended** (CI builds with v0.140.2; `config.toml` requires the
10-
extended SCSS-capable build, min 0.41.0).
9+
- **Hugo extended** (the version is pinned in [`.hugo-version`](.hugo-version),
10+
currently v0.164.0; `config.toml` requires Hugo 0.158.0 or newer).
1111
- **Dart Sass** for `assets/css/main.scss`.
1212
- Content in `content/` as Markdown with **TOML frontmatter** (`+++`
1313
delimiters).
@@ -22,7 +22,7 @@ deployed to GitHub Pages behind Cloudflare at <https://isaaclins.com>.
2222
| `images/` | Post images (mounted to `/images/` at build time). |
2323
| `static/` | Files copied verbatim to the site root (JS, manifest, icons). |
2424
| `data/menu.toml` | Homepage menu entries. |
25-
| `scripts/` | Python helpers run by pre-commit (frontmatter, image-path, and draft checks). |
25+
| `scripts/` | Python checks for frontmatter, image paths, draft status, and the installed Hugo version. |
2626
| `.github/workflows/` | CI: build/validate, deploy, image optimization, and Lighthouse. |
2727

2828
## Local development
@@ -45,8 +45,12 @@ hugo --gc --minify # production build into ./public
4545
## CI / deployment
4646

4747
- **build-test** — builds the site, validates the generated HTML with
48-
`html5validator`, and runs `cspell` on non-draft content.
48+
`html5validator`, and runs `cspell` on non-draft content for pushes to `main`
49+
and pull requests targeting `main`.
4950
- **pages-deploy** — builds and deploys to GitHub Pages on push to `main`.
51+
- Both Hugo workflows read the pinned version from [`.hugo-version`](.hugo-version)
52+
and enforce `config.toml`'s minimum with `scripts/check-hugo-version.py`;
53+
update the version file when upgrading Hugo.
5054
- **optimize-images** — losslessly optimizes committed images and generates
5155
WebP versions.
5256
- **Lighthouse CI** — runs Lighthouse against the live URLs after a deploy and

config.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ enableRobotsTXT = true
66
[module]
77
[module.hugoVersion]
88
extended = true
9-
min = "0.41.0"
9+
min = "0.158.0"
1010
[[module.mounts]]
1111
source = 'static'
1212
target = 'static'

scripts/check-hugo-version.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#!/usr/bin/env python3
2+
"""Fail before a build when the installed Hugo is below the site's minimum."""
3+
4+
from __future__ import annotations
5+
6+
import argparse
7+
import re
8+
import subprocess
9+
import sys
10+
from pathlib import Path
11+
12+
MIN_VERSION_PATTERN = re.compile(r"^\s*min\s*=\s*['\"]([^'\"]+)['\"]\s*$", re.MULTILINE)
13+
14+
15+
def parse_version(value: str) -> tuple[int, int, int] | None:
16+
"""Parse a semantic Hugo version from text."""
17+
match = re.search(r"(\d+)\.(\d+)\.(\d+)", value)
18+
if not match:
19+
return None
20+
return tuple(int(part) for part in match.groups())
21+
22+
23+
def read_minimum_version(config_path: Path) -> str:
24+
"""Read module.hugoVersion.min from the site's TOML configuration."""
25+
config = config_path.read_text(encoding="utf-8")
26+
section_match = re.search(
27+
r"(?ms)^[ \t]*\[module\.hugoVersion\][ \t]*\n?(.*?)(?=^[ \t]*\[|\Z)",
28+
config,
29+
)
30+
if section_match is None:
31+
raise ValueError(f"Missing [module.hugoVersion] section in {config_path}")
32+
33+
min_match = MIN_VERSION_PATTERN.search(section_match.group(1))
34+
if min_match is None:
35+
raise ValueError(f"Missing module.hugoVersion.min in {config_path}")
36+
37+
minimum = min_match.group(1)
38+
if parse_version(minimum) is None:
39+
raise ValueError(f"Invalid Hugo minimum version in {config_path}: {minimum}")
40+
return minimum
41+
42+
43+
def installed_version(hugo_command: str) -> tuple[str, tuple[int, int, int]]:
44+
"""Return the version reported by the selected Hugo executable."""
45+
result = subprocess.run(
46+
[hugo_command, "version"],
47+
check=True,
48+
capture_output=True,
49+
text=True,
50+
)
51+
output = f"{result.stdout}\n{result.stderr}"
52+
version = parse_version(output)
53+
if version is None:
54+
raise ValueError(f"Could not parse Hugo version from: {output.strip()}")
55+
return ".".join(str(part) for part in version), version
56+
57+
58+
def main() -> int:
59+
parser = argparse.ArgumentParser(description=__doc__)
60+
parser.add_argument("--config", type=Path, default=Path("config.toml"))
61+
parser.add_argument("--hugo", default="hugo", help="Hugo executable to check")
62+
args = parser.parse_args()
63+
64+
try:
65+
minimum_text = read_minimum_version(args.config)
66+
minimum = parse_version(minimum_text)
67+
if minimum is None:
68+
raise ValueError(f"Invalid Hugo minimum version: {minimum_text}")
69+
current_text, current = installed_version(args.hugo)
70+
except (OSError, subprocess.CalledProcessError, ValueError) as error:
71+
print(f"Hugo version check failed: {error}", file=sys.stderr)
72+
return 1
73+
74+
if current < minimum:
75+
print(
76+
f"Hugo {current_text} is too old for this site. "
77+
f"Hugo >= {minimum_text} is required by "
78+
f"[module.hugoVersion].min in {args.config}.",
79+
file=sys.stderr,
80+
)
81+
return 1
82+
83+
print(f"Hugo {current_text} satisfies the minimum version {minimum_text}.")
84+
return 0
85+
86+
87+
if __name__ == "__main__":
88+
raise SystemExit(main())

static/probe.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head><meta charset="utf-8"><title>probe</title><style>html,body{margin:0;padding:0;overflow:hidden;background:#fff}iframe{display:block;width:1440px;height:900px;border:0}</style></head>
4+
<body><iframe src="/" onload="this.contentWindow.scrollTo(0, 900)"></iframe></body>
5+
</html>

0 commit comments

Comments
 (0)