From e0eeecd8e91c7efc040c8a1a2431c37881a3df7f Mon Sep 17 00:00:00 2001 From: ShivamJha2436 Date: Wed, 4 Feb 2026 21:40:52 +0530 Subject: [PATCH 1/2] Add automated broken link checking for documentation Signed-off-by: ShivamJha2436 --- .github/workflows/docs_link_check.yml | 66 +++++++++++++++++++++++++++ .lycheeignore | 28 ++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 .github/workflows/docs_link_check.yml create mode 100644 .lycheeignore diff --git a/.github/workflows/docs_link_check.yml b/.github/workflows/docs_link_check.yml new file mode 100644 index 00000000000..9fb100797c8 --- /dev/null +++ b/.github/workflows/docs_link_check.yml @@ -0,0 +1,66 @@ +name: Docs Broken Link Checker + +on: + pull_request: + paths: + - "site/content/docs/main/**/*.md" + # Run weekly + schedule: + - cron: "0 7 * * 1" + + # Allow manual runs + workflow_dispatch: + +jobs: + link-check: + runs-on: ubuntu-latest + + steps: + # Step 1: Checkout repository + - name: Checkout repository + uses: actions/checkout@v4 + + # Step 2: Run Lychee link checker on MAIN docs only + - name: Run Lychee link checker (main docs only) + uses: lycheeverse/lychee-action@v1 + with: + args: > + --verbose + --no-progress + --timeout 20 + --max-retries 3 + --retry-wait-time 5 + --exclude-mail + --accept 200,206,429 + --ignore-path .lycheeignore + --output lychee-report.md + --format markdown + "site/content/docs/main/**/*.md" + + # Step 3: Check if an open broken-link issue already exists + # This prevents weekly issue spam. + - name: Check if issue already exists + if: failure() && github.event_name == 'schedule' + id: issue-check + uses: actions/github-script@v7 + with: + script: | + const query = + 'repo:${{ github.repository }} ' + + 'is:issue is:open ' + + '"Broken links detected in Contour documentation"'; + + const result = await github.rest.search.issuesAndPullRequests({ + q: query + }); + + core.setOutput("exists", result.data.total_count > 0); + + # Step 4: Create issue ONLY if none exists already + - name: Create GitHub issue (scheduled run only) + if: failure() && github.event_name == 'schedule' && steps.issue-check.outputs.exists == 'false' + uses: peter-evans/create-issue-from-file@v5 + with: + title: "Broken links detected in Contour documentation" + content-filepath: lychee-report.md + labels: documentation, automated diff --git a/.lycheeignore b/.lycheeignore new file mode 100644 index 00000000000..f23cac25132 --- /dev/null +++ b/.lycheeignore @@ -0,0 +1,28 @@ +# Lychee Ignore File for Contour Documentation Link Checks + +# Purpose: +# - Avoid false positives from placeholder/dev links +# - Ignore dynamic GitHub URLs that cannot be validated reliably +# - Reduce CI noise while still catching real broken links + +# Local development links (not valid in CI) +localhost +127.0.0.1 + +# Placeholder/example domains used in docs +example.com +example.org + +# Mail links are not checkable as HTTP URLs +mailto:* + +# GitHub issue creation links are dynamic and often return redirects +https://github.com/projectcontour/contour/issues/new* +https://github.com/projectcontour/contour/issues?q=* + +# GitHub compare URLs are temporary/dynamic +https://github.com/projectcontour/contour/compare/* + +# Common documentation short-links that may rate-limit bots +https://twitter.com/* +https://x.com/* From 0ee4bfe3928abe014bf2e924f8ef51a742cf45a6 Mon Sep 17 00:00:00 2001 From: ShivamJha2436 Date: Thu, 5 Feb 2026 09:22:53 +0530 Subject: [PATCH 2/2] Fix: docs link checker workflow Signed-off-by: ShivamJha2436 --- .github/workflows/docs_link_check.yml | 64 ++++++++++++++++----------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/.github/workflows/docs_link_check.yml b/.github/workflows/docs_link_check.yml index 9fb100797c8..056efaeb2bc 100644 --- a/.github/workflows/docs_link_check.yml +++ b/.github/workflows/docs_link_check.yml @@ -4,11 +4,10 @@ on: pull_request: paths: - "site/content/docs/main/**/*.md" - # Run weekly + schedule: - cron: "0 7 * * 1" - - # Allow manual runs + workflow_dispatch: jobs: @@ -16,13 +15,13 @@ jobs: runs-on: ubuntu-latest steps: - # Step 1: Checkout repository - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - # Step 2: Run Lychee link checker on MAIN docs only + # Lychee parses Markdown files, extracts URLs, and checks them via HTTP requests. + # The job fails if any broken links are detected. - name: Run Lychee link checker (main docs only) - uses: lycheeverse/lychee-action@v1 + uses: lycheeverse/lychee-action@a8c4c7cb88f0c7386610c35eb25108e448569cb0 # v2.7.0 with: args: > --verbose @@ -37,30 +36,43 @@ jobs: --format markdown "site/content/docs/main/**/*.md" - # Step 3: Check if an open broken-link issue already exists - # This prevents weekly issue spam. - - name: Check if issue already exists + # Scheduled runs should create or update a tracking issue instead of opening duplicates. + - name: Create or update issue (scheduled runs only) if: failure() && github.event_name == 'schedule' - id: issue-check uses: actions/github-script@v7 with: script: | - const query = - 'repo:${{ github.repository }} ' + - 'is:issue is:open ' + - '"Broken links detected in Contour documentation"'; + const fs = require("fs"); + + const title = "Broken links found in documentation"; + const report = fs.readFileSync("lychee-report.md", "utf8"); - const result = await github.rest.search.issuesAndPullRequests({ - q: query + // Search for an existing open issue with the same title + const search = await github.rest.search.issuesAndPullRequests({ + q: `repo:${context.repo.owner}/${context.repo.repo} is:issue is:open "${title}"` }); - core.setOutput("exists", result.data.total_count > 0); + if (search.data.total_count > 0) { + const issue = search.data.items[0]; - # Step 4: Create issue ONLY if none exists already - - name: Create GitHub issue (scheduled run only) - if: failure() && github.event_name == 'schedule' && steps.issue-check.outputs.exists == 'false' - uses: peter-evans/create-issue-from-file@v5 - with: - title: "Broken links detected in Contour documentation" - content-filepath: lychee-report.md - labels: documentation, automated + // Add the latest report as a comment + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + body: report + }); + + console.log(`Updated existing issue #${issue.number}`); + } else { + // Create a new issue if none exists + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: title, + body: report, + labels: ["documentation", "automated"] + }); + + console.log("Created new broken-links issue"); + }