From a34baafcc87ddc0a0f5aca7f9fa845bc32582525 Mon Sep 17 00:00:00 2001 From: tannevaled Date: Sun, 8 Nov 2026 15:00:32 +0100 Subject: [PATCH] ci: check landing links with landingkit links Replace the hand-written curl loop over the built site with `landingkit links public` (landingkit v0.20.0, pinned through go.mod). Co-Authored-By: Claude Sonnet 5.5 --- .github/workflows/links.yml | 60 ++++++++----------------------------- 1 file changed, 12 insertions(+), 48 deletions(-) diff --git a/.github/workflows/links.yml b/.github/workflows/links.yml index bdcbcb6..8d6fbaa 100644 --- a/.github/workflows/links.yml +++ b/.github/workflows/links.yml @@ -1,17 +1,14 @@ name: links -# The landing had a link to https://github.com/go-fileshare/authnd, which is a -# 404: authnd lives in go-authn. The organisation profile carries the SAME link -# and has it right, because .github/ has a link check and this repository did -# not. A dead link on a landing page breaks nothing that complains. +# A dead link on a landing page breaks nothing that complains (the landing once +# linked https://github.com/go-fileshare/authnd, a 404), so every link of the +# page is checked. # -# ⛔ THE CHECK READS THE BUILT SITE, NOT THE LAYOUTS. The first version of this -# file grepped layouts/ and failed on its own first run against -# `https://github.com/go-fileshare/{{ .name }}` -- a Hugo template expression, -# not a URL. Skipping anything with a brace in it would have "fixed" that and -# left the per-repository card links unchecked, which is most of the page's -# links. Building first expands them into the URLs a reader actually gets, -# which is the only set worth checking. +# ⛔ THE CHECK READS THE BUILT SITE, NOT THE LAYOUTS: templated links such as +# the per-repository cards only become real URLs once Hugo has expanded them. +# +# The checker is `landingkit links` (go-fleettools/landingkit), run at the +# version go.mod pins: it replaces a hand-written curl loop. on: pull_request: @@ -37,43 +34,10 @@ jobs: cache: false - uses: peaceiris/actions-hugo@v3 with: - hugo-version: "0.169.0" + hugo-version: "0.168.0" extended: true - run: hugo --minify --destination ./public - name: Check - run: | - set -uo pipefail - # The character class matters: an extractor that stops only at ) and " - # carries a closing > or < into the request. - urls=$(grep -rhoE 'https?://[^)">< [:space:]]+' public/ | sed 's/[.,]$//' | sort -u) - test -n "$urls" || { echo "::error::no links found; did the site build?"; exit 1; } - echo "checking $(printf '%s\n' "$urls" | wc -l) distinct URLs" - fail=0 - while read -r u; do - # img.shields.io renders anything asked of it and proves nothing. - case "$u" in *img.shields.io*) continue ;; esac - # github.com answers curl's blob pages with 503 most of the time - # (7 of 8 on 2026-10-10, all 3 attempts on every run), while the - # raw host answers 200 for a file and 404 for a missing one. A blob - # link claims "this file exists at this ref", so ask the raw host. - # (go-ndarray/docs#30; `landingkit links` does the same, tested.) - probe=$u - case "$u" in - https://github.com/*/*/blob/*) - probe=https://raw.githubusercontent.com/$(printf '%s' "${u#https://github.com/}" | sed -E 's#^([^/]+/[^/]+)/blob/#\1/#; s/[?#].*$//') ;; - esac - # Three attempts: one is a flake detector rather than a link - # checker, and a lane that fails at random is a lane people learn - # to ignore. - code=000 - for attempt in 1 2 3; do - code=$(curl -sS -o /dev/null -w '%{http_code}' -L --max-time 25 "$probe" || echo 000) - case "$code" in 2*|3*) break ;; esac - sleep 3 - done - case "$code" in - 2*|3*) printf ' ok %s %s\n' "$code" "$u" ;; - *) printf ' FAIL %s %s\n' "$code" "$u"; fail=1 ;; - esac - done <<< "$urls" - test "$fail" -eq 0 || { echo "::error::at least one link or image does not resolve"; exit 1; } + env: + GOWORK: "off" + run: go run github.com/go-fleettools/landingkit/cmd/landingkit links public