From 4709f6ba27b270ff08883794000ad2cd534840dc Mon Sep 17 00:00:00 2001 From: Vijit Singh Date: Thu, 18 Jun 2026 02:25:04 -0500 Subject: [PATCH] ci: scheduled external-link monitor with lychee (closes #12) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI's htmltest runs with CheckExternal: false (deterministic, never flakes on a third-party outage), so nothing ever checks outbound links — rot to getmonero.org / GitHub / Tari goes unnoticed. - links.yml: weekly (+ workflow_dispatch) job that builds the site and runs lychee over ./public, excluding our own domain (internal links stay htmltest's job). fail: false — it never blocks a PR. On breakage it opens, or updates, a single "Broken external links (lychee)" tracking issue via gh. - .lycheeignore: documented placeholder for flaky/auth-walled hosts (none needed yet — the site only links to stable hosts). - Hugo install reads .hugoversion when present (falls back to 0.162.1), so it picks up the single-source pin from #15 once that merges. Verified locally: lychee --dump over a production build lists exactly the outbound links (own domain excluded); prettier/YAML/zizmor clean. The job is scheduled, so it doesn't run on this PR. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/links.yml | 60 +++++++++++++++++++++++++++++++++++++ .lycheeignore | 9 ++++++ 2 files changed, 69 insertions(+) create mode 100644 .github/workflows/links.yml create mode 100644 .lycheeignore diff --git a/.github/workflows/links.yml b/.github/workflows/links.yml new file mode 100644 index 0000000..bf19028 --- /dev/null +++ b/.github/workflows/links.yml @@ -0,0 +1,60 @@ +name: Link monitor + +# Scheduled external-link check (link rot to getmonero.org, GitHub, Tari, …). Kept OUT of the PR +# gate on purpose: CI's htmltest checks internal links deterministically, while outbound checks are +# flaky by nature (third-party outages). On breakage this opens or updates a single tracking issue — +# it never blocks a PR. + +on: + schedule: + - cron: "0 6 * * 1" # Mondays 06:00 UTC + workflow_dispatch: + +permissions: + contents: read + +jobs: + link-check: + runs-on: ubuntu-latest + permissions: + contents: read + issues: write # open / update the tracking issue + steps: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false # zizmor: artipacked + - name: Install Hugo (extended) + run: | + HUGO_VERSION="$(cat .hugoversion 2>/dev/null || echo 0.162.1)" # tracks .hugoversion once #15 lands + wget -O "${{ runner.temp }}/hugo.deb" \ + "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb" + sudo dpkg -i "${{ runner.temp }}/hugo.deb" + - name: Build site + env: + HUGO_ENVIRONMENT: production + TZ: UTC + run: hugo --gc --minify --baseURL "https://p2pool-starter-stack.github.io/" + - name: Check external links (lychee) + id: lychee + uses: lycheeverse/lychee-action@8646ba30535128ac92d33dfc9133794bfdd9b411 # v2.8.0 + with: + # Internal links are htmltest's job — exclude our own domain so this only audits outbound. + args: "--no-progress --exclude p2pool-starter-stack.github.io ./public" + output: ./lychee/out.md + fail: false # never fail the workflow; report via the tracking issue instead + - name: Open or update tracking issue + if: steps.lychee.outputs.exit_code != 0 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TITLE: "Broken external links (lychee)" + run: | + set -euo pipefail + existing="$(gh issue list --state open --search "in:title Broken external links" \ + --json number,title --jq "[.[] | select(.title==\"$TITLE\")][0].number // empty")" + if [ -n "$existing" ]; then + gh issue edit "$existing" --body-file ./lychee/out.md + gh issue comment "$existing" --body "Re-checked by the scheduled run — still failing. Report above was updated." + else + gh issue create --title "$TITLE" --body-file ./lychee/out.md --label infra + fi diff --git a/.lycheeignore b/.lycheeignore new file mode 100644 index 0000000..a768c5e --- /dev/null +++ b/.lycheeignore @@ -0,0 +1,9 @@ +# lychee ignore list — one regex per line. For links an automated checker can't reliably verify +# (rate-limits, auth walls, bot blocks), NOT real link rot. Keep this list small and justified. +# +# The site currently links only to stable hosts (github.com, getmonero.org, tari.com, +# opensource.org, schema.org), so nothing needs ignoring yet. Add entries here when a flaky or +# auth-walled link appears — e.g. social links that 403 automated requests: +# +# https://x\.com/.* +# https://(www\.)?linkedin\.com/.*