Skip to content

Commit 62032ce

Browse files
committed
Merge remote-tracking branch 'origin/master' into rois
# Conflicts: # content/en/docs/Data/templates.md
2 parents 1907849 + 42697aa commit 62032ce

293 files changed

Lines changed: 12152 additions & 1140 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# NOT ACTIVE where it sits. Move it into place to enable:
2+
# git mv themes/vfb-nova/ci/builder-image.yml .github/workflows/builder-image.yml
3+
# Parked here because the token used to push this branch has no `workflow`
4+
# scope, and GitHub rejects any push touching .github/workflows/ without it.
5+
# Pushing from a checkout with normal credentials has no such problem.
6+
#
7+
# Until it is moved, virtualflybrain/vfb-static-builder DOES NOT EXIST and the
8+
# Rancher service has nothing to pull. This has to happen before the switchover.
9+
#
10+
# Publishes the image the Rancher build service runs. It lives here, next to
11+
# deploy.sh, because deploy.sh is what dictates the image's contents — bash,
12+
# rsync and findutils are in the Dockerfile for its sake. Splitting the two
13+
# across repos is how rcourt/docsy-builder:Feb2023 ended up frozen on a floating
14+
# base tag for two years.
15+
#
16+
# Uses the org-level Docker Hub secrets (DOCKER_HUB_USER / DOCKER_HUB_PASSWORD),
17+
# which vfb-status and vfbquery already use to publish into the virtualflybrain
18+
# namespace. Docker Hub creates the repository on first push.
19+
name: builder image
20+
21+
on:
22+
push:
23+
branches: ["master"]
24+
paths:
25+
- "Dockerfile"
26+
- "deploy.sh"
27+
- ".github/workflows/builder-image.yml"
28+
release:
29+
types: [published]
30+
workflow_dispatch:
31+
32+
permissions:
33+
contents: read
34+
35+
jobs:
36+
publish:
37+
runs-on: ubuntu-latest
38+
steps:
39+
- uses: actions/checkout@v4
40+
41+
- uses: docker/setup-buildx-action@v3
42+
43+
- name: Log in to Docker Hub
44+
uses: docker/login-action@v3
45+
with:
46+
username: ${{ secrets.DOCKER_HUB_USER }}
47+
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
48+
49+
- name: Metadata
50+
id: meta
51+
uses: docker/metadata-action@v5
52+
with:
53+
images: virtualflybrain/vfb-static-builder
54+
tags: |
55+
type=raw,value=latest,enable={{is_default_branch}}
56+
type=ref,event=tag
57+
type=sha,format=short
58+
59+
- name: Build and push
60+
uses: docker/build-push-action@v6
61+
with:
62+
context: .
63+
push: true
64+
tags: ${{ steps.meta.outputs.tags }}
65+
labels: ${{ steps.meta.outputs.labels }}
66+
67+
# Tests the first tag this run actually pushed. The previous version
68+
# tested :latest, which metadata-action only emits on the default branch,
69+
# so a tag-triggered run would have failed on an image that did not exist.
70+
#
71+
# Pin the Rancher service to the sha- tag printed at the end, not :latest.
72+
- name: Smoke test the published image
73+
env:
74+
TAGS: ${{ steps.meta.outputs.tags }}
75+
run: |
76+
set -euo pipefail
77+
image=$(printf '%s\n' "$TAGS" | head -n1)
78+
echo "testing $image"
79+
docker run --rm --entrypoint hugo "$image" version
80+
docker run --rm --entrypoint /bin/sh "$image" -c '
81+
set -e
82+
command -v bash
83+
command -v rsync
84+
command -v find
85+
test "$HUGO_CACHEDIR" = /tmp/hugo_cache
86+
test "$(pwd)" = /src
87+
test "$(id -u)" = 0
88+
'
89+
echo "pushed tags:"
90+
printf '%s\n' "$TAGS"

‎.gitmodules‎

Lines changed: 0 additions & 6 deletions
This file was deleted.

‎Dockerfile‎

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,78 @@
1-
FROM klakegg/hugo:ext-alpine
1+
# Build image for the static site.
2+
#
3+
# docker build -t vfb-static-builder .
4+
# docker run --rm -v "$PWD:/src" -v vfb_cache:/tmp vfb-static-builder
5+
#
6+
# Pinned to Hugo 0.122.0 rather than the newest release. That is a deliberate
7+
# step backwards and the reason is measured, not suspected.
8+
#
9+
# The content tree is ~763k generated term pages, ~650k of them in a single
10+
# directory (content/en/blog/ontologies/vfb), reached over NFSv3 from a Synology
11+
# volume whose btrfs metadata sits on RAID5 spinning disks. Measured on that
12+
# volume: plain readdir runs at 5-29k entries/s, but readdir+stat runs at
13+
# 253/s — ~4ms per inode, a disk seek, nothing cached. NFSv3 uses READDIRPLUS,
14+
# so the server stats every entry it enumerates. Per-page filesystem cost is
15+
# therefore the dominant term in this build, far above template or render cost.
16+
#
17+
# Hugo's per-page filesystem cost rose at v0.123.0, which rewrote page assembly.
18+
# Counted with strace over an identical 25k-page corpus on local disk:
19+
#
20+
# 0.122.0 75,658 openat 76,997 newfstatat 3.06 stat/page
21+
# 0.128.0 100,788 openat 101,527 newfstatat 4.04 stat/page
22+
# 0.140.2 100,813 openat 101,485 newfstatat 4.03 stat/page
23+
# 0.164.0 100,844 openat 101,488 newfstatat 4.03 stat/page
24+
#
25+
# Flat from 0.128 onward, so this is one regression at 0.123, not a drift. At
26+
# 763k pages and 253 stat/s that extra stat per page is ~49 min on top of a
27+
# build already costing ~2.6h of pure metadata I/O.
28+
#
29+
# 0.122.0 is the last version known to complete this build: the live term pages
30+
# carry `generator: Hugo 0.122.0` and were written 2026-08-05 17:59. No 0.16x
31+
# build has ever finished — each ran 17h+ with one thread in uninterruptible
32+
# sleep on the vfb/ directory and not a single page written.
33+
#
34+
# This pin is a workaround. The fix is to stop holding 650k files in one
35+
# directory (shard vfbterms.py's output) and to pin the volume's btrfs metadata
36+
# to its SSD cache. When either lands, raise HUGO_VERSION — it is an ARG so that
37+
# is a one-line change.
38+
#
39+
# Debian rather than Alpine, and the tarball rather than ghcr.io/gohugoio/hugo:
40+
# that registry has no v0.122.0 tag (it begins around v0.140), and the extended
41+
# release binary is glibc-linked — `ldd` gives /lib64/ld-linux-x86-64.so.2 plus
42+
# libstdc++.so.6 — so musl with gcompat is not a safe host for it.
43+
#
44+
# Extended edition, matching the rcourt/docsy-builder:Feb2023 that produced the
45+
# last good site. The theme ships plain CSS and needs no Sass, so the standard
46+
# edition would also serve and is statically linked; keeping extended here
47+
# changes one variable at a time relative to the last build known to work.
48+
#
49+
# The theme declares min_version 0.128.0 for `[pagination] pagerSize`, so 0.122
50+
# emits one WARN and falls back to 10 items per page. Nothing on the site
51+
# paginates today, so that is latent rather than active.
52+
FROM debian:bookworm-slim
253

3-
RUN apk add git && \
4-
git config --global --add safe.directory /src
54+
ARG HUGO_VERSION=0.122.0
55+
56+
# bash and find are already in the base image. rsync is for deploy.sh, which
57+
# stages the build and syncs it into the served directory rather than writing
58+
# there directly. libstdc++6 is what the extended Hugo binary links against.
59+
RUN apt-get update \
60+
&& apt-get install -y --no-install-recommends rsync ca-certificates libstdc++6 \
61+
&& rm -rf /var/lib/apt/lists/*
62+
63+
ADD https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz /tmp/hugo.tgz
64+
RUN tar xzf /tmp/hugo.tgz -C /usr/local/bin hugo \
65+
&& rm -f /tmp/hugo.tgz \
66+
&& hugo version
67+
68+
# Deliberately root. The published tree on the NFS volume is owned by root from
69+
# the klakegg-era builds, so an unprivileged rsync could not overwrite it.
70+
USER root
71+
72+
# deploy.sh uses ${HUGO_CACHEDIR:-/tmp/hugo_cache}, so this must be set
73+
# explicitly: Rancher mounts the workspace at /src and the cache volume at /tmp.
74+
ENV HUGO_CACHEDIR=/tmp/hugo_cache
75+
WORKDIR /src
76+
77+
ENTRYPOINT []
78+
CMD ["/bin/bash", "/src/deploy.sh"]

‎assets/scss/_styles_project.scss‎

Lines changed: 0 additions & 20 deletions
This file was deleted.

‎assets/scss/_variables_project.scss‎

Lines changed: 0 additions & 8 deletions
This file was deleted.

‎check_images.py‎

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,24 @@
1515
DEFAULT_EXTENSIONS = ['.md', '.html', '.yml', '.yaml', '.toml', '.json', '.js', '.ts', '.scss', '.css']
1616

1717

18+
def is_templated(url: str) -> bool:
19+
"""True for URLs that are template strings, not real links.
20+
21+
Hugo/Go templates build image URLs with a placeholder filled in at render
22+
time, e.g. `printf "https://i.ytimg.com/vi/%s/hqdefault.jpg" $id` or a
23+
`{{ ... }}` expression. Fetching the literal template string 404s, so skip
24+
it. A printf verb is a `%` followed by a letter that cannot begin a valid
25+
`%HH` percent-encoding (i.e. not a-f), which distinguishes `%s`/`%v` from
26+
genuinely encoded characters like `%2F` or `%FF`.
27+
"""
28+
if '{{' in url or '}}' in url:
29+
return True
30+
return any(
31+
m.group(1).isalpha() and m.group(1).lower() not in 'abcdef'
32+
for m in re.finditer(r'%(.)', url)
33+
)
34+
35+
1836
def collect_image_urls(base_dir: pathlib.Path, ext_filter=None):
1937
ext_filter = ext_filter or DEFAULT_EXTENSIONS
2038
matches = []
@@ -23,7 +41,10 @@ def collect_image_urls(base_dir: pathlib.Path, ext_filter=None):
2341
continue
2442
text = path.read_text(encoding='utf-8', errors='ignore')
2543
for m in IMAGE_PATTERN.finditer(text):
26-
matches.append((str(path), m.group(0)))
44+
url = m.group(0)
45+
if is_templated(url):
46+
continue
47+
matches.append((str(path), url))
2748
return matches
2849

2950

0 commit comments

Comments
 (0)