Validate Links #22
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: Validate Links | |
on: | |
schedule: | |
# Run daily at 2:00 AM UTC | |
- cron: '0 2 * * *' | |
workflow_dispatch: # Allow manual triggering | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
permissions: | |
contents: read | |
issues: write | |
jobs: | |
validate-links: | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Set up Python | |
uses: actions/setup-python@v5 | |
with: | |
python-version: '3.11' | |
- name: Install dependencies | |
run: make install | |
- name: Run link validation | |
id: validate | |
run: | | |
make validate-github | |
echo "has_broken_links=$(python -c "import json; data=json.load(open('validation_results.json')); print('true' if data['newly_broken'] else 'false')")" >> "$GITHUB_OUTPUT" | |
- name: Upload validation results | |
if: always() | |
uses: actions/upload-artifact@v4 | |
with: | |
name: validation-results | |
path: | | |
validation_results.json | |
THE_RESOURCES_TABLE.csv | |
- name: Check for existing issue | |
if: steps.validate.outputs.has_broken_links == 'true' | |
id: check_issue | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const issues = await github.rest.issues.listForRepo({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
state: 'open', | |
labels: 'broken-links' | |
}); | |
const today = new Date().toISOString().split('T')[0]; | |
const existingIssue = issues.data.find(issue => | |
issue.title.includes('Broken Links Report') && | |
issue.title.includes(today) | |
); | |
core.setOutput('issue_number', existingIssue ? existingIssue.number : ''); | |
- name: Create or update issue | |
if: steps.validate.outputs.has_broken_links == 'true' | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const fs = require('fs'); | |
const results = JSON.parse(fs.readFileSync('validation_results.json', 'utf8')); | |
const today = new Date().toISOString().split('T')[0]; | |
let issueBody = `## 🔗 Broken Links Report\n\n`; | |
issueBody += `This automated scan found **${results.newly_broken_links.length}** new broken link(s) in the repository.\n\n`; | |
issueBody += `### Broken Links:\n\n`; | |
for (const link of results.newly_broken_links) { | |
issueBody += `- **${link.name}**\n`; | |
issueBody += ` - URL: ${link.url}\n`; | |
} | |
issueBody += `### Summary\n\n`; | |
issueBody += `- Broken links: ${results.newly_broken_links.length}\n`; | |
issueBody += `- Scan completed: ${results.timestamp}\n\n`; | |
issueBody += `---\n`; | |
issueBody += `*This issue was automatically created by the [link validation workflow](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/workflows/validate-links.yml).*`; | |
const existingIssueNumber = ${{ steps.check_issue.outputs.result }} || 0; | |
if (existingIssueNumber) { | |
await github.rest.issues.update({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
issue_number: existingIssueNumber, | |
body: issueBody | |
}); | |
console.log(`Updated existing issue #${existingIssueNumber}`); | |
} else { | |
const issue = await github.rest.issues.create({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
title: `🚨 Broken Links Report - ${today}`, | |
body: issueBody, | |
labels: ['broken-links', 'automated'] | |
}); | |
console.log(`Created new issue #${issue.data.number}`); | |
} | |
- name: Close old broken link issues | |
if: steps.validate.outputs.has_broken_links == 'false' | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const issues = await github.rest.issues.listForRepo({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
state: 'open', | |
labels: 'broken-links' | |
}); | |
for (const issue of issues.data) { | |
await github.rest.issues.update({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
issue_number: issue.number, | |
state: 'closed', | |
state_reason: 'completed' | |
}); | |
await github.rest.issues.createComment({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
issue_number: issue.number, | |
body: '✅ All links are now working! Closing this issue.' | |
}); | |
console.log(`Closed issue #${issue.number}`); | |
} |