Drop the unfalsifiable claim that put the fabrication ratchet at 10 (… #1359
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Broken Internal Links | |
| # On PRs, only crawl when a change could actually move an internal link: | |
| # content (blog/course/pages), templates, menu/baseURL config, the data | |
| # records rendered into links, or the checker config itself. A CSS/test/ | |
| # workflow-only PR does not trigger this workflow at all. The non-PR events | |
| # carry no paths filter, so they always run and keep master fully covered. | |
| on: | |
| pull_request: | |
| paths: | |
| - 'content/**' | |
| - 'themes/**/layouts/**' | |
| # root-level template overrides move links just like theme layouts | |
| - 'layouts/**' | |
| - 'config/**' | |
| - 'data/**' | |
| - 'lychee.toml' | |
| - 'Rakefile' | |
| # Build/runtime inputs: the crawl runs against a Hugo-built site using | |
| # bundled tooling, so a change here can move generated links too. | |
| - '.github/actions/setup-hugo/**' | |
| - 'Gemfile' | |
| - 'Gemfile.lock' | |
| push: | |
| branches: [ master ] | |
| schedule: | |
| - cron: '0 0 * * *' | |
| workflow_dispatch: | |
| workflow_run: | |
| workflows: ["Sync articles"] | |
| types: | |
| - completed | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: link-check-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: ${{ github.event.pull_request.number != '' }} | |
| defaults: | |
| run: | |
| shell: bash | |
| env: | |
| # Stalled-fetch guard (actions/checkout#2441): abort a fetch that has moved | |
| # <1 KB/s for 30s, so checkout's built-in 3x retry can recover instead of | |
| # the step hanging silently until the job cap kills it. Measurements and | |
| # full rationale live in .github/workflows/_hugo.yml. GIT_CONFIG_* env | |
| # rather than `git config --global`, because checkout overrides HOME before | |
| # it runs git - a global config from an earlier step never reaches it. | |
| GIT_CONFIG_COUNT: '2' | |
| GIT_CONFIG_KEY_0: http.lowSpeedLimit | |
| GIT_CONFIG_VALUE_0: '1000' | |
| GIT_CONFIG_KEY_1: http.lowSpeedTime | |
| GIT_CONFIG_VALUE_1: '30' | |
| jobs: | |
| link_check: | |
| name: Broken Internal Links | |
| # Sync fan-out gate: "Sync articles" completes every 10 min during the | |
| # day, but most runs commit nothing. For workflow_run events, only crawl | |
| # when the sync actually pushed (master head moved past the sha the sync | |
| # ran on). github.sha for workflow_run = current default-branch head. | |
| if: ${{ github.event_name != 'workflow_run' || (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_sha != github.sha) }} | |
| runs-on: ubuntu-latest | |
| # 15, not 10: html-proofer's image/fragment pass over the full page set | |
| # runs after lychee inside the same job. | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| persist-credentials: false | |
| - uses: ruby/setup-ruby@v1 | |
| with: | |
| ruby-version: '4.0' | |
| bundler-cache: true | |
| # setup only - rake test:links runs its own production build via | |
| # bin/hugo-build; the composite's default build made this job build | |
| # the whole site TWICE and blow its 10-minute timeout on cold caches. | |
| - uses: ./.github/actions/setup-hugo | |
| with: | |
| build: 'false' | |
| - uses: taiki-e/install-action@v2.86.3 | |
| with: | |
| tool: lychee | |
| # html-proofer catches what lychee does not: image src files that are | |
| # referenced but missing from the build, and malformed hash fragments. | |
| # The task existed in the Rakefile but was wired into no workflow, | |
| # hook, or script - dead code reading as coverage (2026-08-07 audit). | |
| # It is non-blocking by its own design; test:links stays blocking. | |
| # | |
| # ONE rake invocation, not two steps: build_for_linkcheck memoizes per | |
| # process, so the pair shares a single production build. Two steps | |
| # would build the whole site twice and blow the job timeout. | |
| - run: bundle exec rake test:links test:html_proofer | |
| # test:links_external existed in the Rakefile and was wired into no | |
| # workflow - the same dead-code-reading-as-coverage defect the comment | |
| # above describes for html_proofer. It is what would have caught the dead | |
| # LangChain cookbook link, the dead langchainai Twitter link and the 404 | |
| # blog.langchain.dev source, all of which shipped and were only found by | |
| # hand on 2026-08-28. | |
| # | |
| # Scheduled and manual runs only. External URLs rate-limit and flap, so | |
| # running this per-PR would train everyone to ignore a red check; the | |
| # daily cron catches rot without blocking anyone. Non-blocking by design. | |
| - name: External links (scheduled only, non-blocking) | |
| if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| continue-on-error: true | |
| run: bundle exec rake test:links_external |