Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/link-rot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# External-link rot check.
#
# Scheduled (not per-PR) on purpose: external checks are network-flaky and a
# third-party outage must never block merges. The internal link graph is
# already guarded per-PR by check_link_graph.py; this covers the external
# citations (DOJ, IC3, vendor docs, papers) that rot silently.
#
# Failures open/update a single tracking issue rather than emailing a red run
# nobody reads. Exclusions live in .lycheeignore (placeholders from code
# examples, bot-hostile hosts).
name: Link rot check

on:
schedule:
- cron: '0 14 * * 1' # Mondays 14:00 UTC
workflow_dispatch:

permissions:
contents: read
issues: write

jobs:
lychee:
name: External link check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

- name: Check external links in content
id: lychee
uses: lycheeverse/lychee-action@v2
with:
# Source markdown only; {filename} internal links are non-http and
# skipped via --scheme, and the built site's internal graph has its
# own per-PR guard.
args: >-
--scheme https --scheme http
--base-url 'https://rivassec.com'
--accept '200..=206,429'
--timeout 20
--max-retries 2
--max-concurrency 8
--no-progress
'content/**/*.md' 'README.md'
output: lychee-report.md
fail: false

- name: Open or update tracking issue on failures
if: steps.lychee.outputs.exit_code != 0
uses: peter-evans/create-issue-from-file@v5
with:
title: 'Link rot: broken external links detected'
content-filepath: lychee-report.md
labels: link-rot

- name: Fail the run if links are broken
if: steps.lychee.outputs.exit_code != 0
run: |
echo "::error::lychee found broken external links (see lychee-report.md / tracking issue)"
exit 1
13 changes: 13 additions & 0 deletions .lycheeignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Pelican source-link syntax ({filename}/{static}); resolves at build time and
# the internal link graph has its own per-PR guard (check_link_graph.py).
%7B(filename|static)%7D
\{(filename|static)\}
# Placeholders and local addresses from code examples - never real links.
^https?://localhost
^https?://host(:|$|/)
^https?://127\.0\.0\.1
# Hosts that block automated checkers while working fine in browsers
# (LinkedIn returns 999 to bots; X/Twitter gates aggressively).
^https?://(www\.)?linkedin\.com
^https?://(www\.)?x\.com
^https?://(www\.)?twitter\.com
Loading