1+ name : Link Checker
2+
3+ on :
4+ schedule :
5+ # Run weekly on Sundays at 1 AM UTC
6+ - cron : ' 0 1 * * 0'
7+ workflow_dispatch :
8+ inputs :
9+ check_external :
10+ description : ' Check external links'
11+ required : false
12+ default : ' true'
13+ type : boolean
14+ fail_on_error :
15+ description : ' Fail workflow on broken links'
16+ required : false
17+ default : ' false'
18+ type : boolean
19+
20+ jobs :
21+ link-check :
22+ runs-on : ubuntu-latest
23+ steps :
24+ - name : Checkout
25+ uses : actions/checkout@v4
26+
27+ - name : Setup Ruby
28+ uses : ruby/setup-ruby@v1
29+ with :
30+ ruby-version : 3.2
31+ bundler-cache : true
32+
33+ - name : Build Jekyll site
34+ run : |
35+ bundle exec jekyll build
36+
37+ - name : Install lychee
38+ run : |
39+ wget -qO- https://github.com/lycheeverse/lychee/releases/latest/download/lychee-x86_64-unknown-linux-gnu.tar.gz | tar -xzv
40+ sudo mv lychee /usr/local/bin/
41+
42+ # Use shared lychee configuration file
43+
44+ - name : Check internal links
45+ run : |
46+ echo "🔍 Checking internal links..."
47+
48+ # Check internal links in built site
49+ lychee --config .lycherc.toml \
50+ --exclude-all-private \
51+ --no-progress \
52+ --offline \
53+ _site/ || {
54+ echo "❌ Internal link check failed"
55+ if [ "${{ github.event.inputs.fail_on_error }}" = "true" ]; then
56+ exit 1
57+ fi
58+ }
59+
60+ echo "✅ Internal link check completed"
61+
62+ - name : Check external links
63+ if : github.event.inputs.check_external != 'false'
64+ run : |
65+ echo "🌐 Checking external links..."
66+
67+ # Create results directory
68+ mkdir -p link-check-results
69+
70+ # Check external links with detailed reporting (excluding generated files)
71+ find manuals -name "*.md" -type f ! -name "1page.md" -exec lychee --config .lycherc.toml \
72+ --no-progress \
73+ --format json \
74+ --output link-check-results/external-links.json \
75+ {} + || {
76+ echo "❌ Some external links are broken"
77+
78+ # Generate human-readable report
79+ echo "## 🔗 Broken External Links Report" > link-check-results/report.md
80+ echo "" >> link-check-results/report.md
81+ echo "The following external links were found to be broken:" >> link-check-results/report.md
82+ echo "" >> link-check-results/report.md
83+
84+ # Parse JSON results for broken links using jq
85+ if [ -f "link-check-results/external-links.json" ]; then
86+ # Install jq for JSON parsing
87+ sudo apt-get update && sudo apt-get install -y jq
88+
89+ # Extract broken links from JSON using jq
90+ jq -r '.links[] | select(.status.status != "Ok") | .url' \
91+ link-check-results/external-links.json | sort -u \
92+ >> link-check-results/broken-links.txt || true
93+
94+ if [ -s "link-check-results/broken-links.txt" ]; then
95+ echo "### Broken Links:" >> link-check-results/report.md
96+ while read -r link; do
97+ echo "- $link" >> link-check-results/report.md
98+ done < link-check-results/broken-links.txt
99+ fi
100+ fi
101+
102+ # Show report
103+ if [ -f "link-check-results/report.md" ]; then
104+ cat link-check-results/report.md
105+ fi
106+
107+ if [ "${{ github.event.inputs.fail_on_error }}" = "true" ]; then
108+ exit 1
109+ fi
110+ }
111+
112+ echo "✅ External link check completed"
113+
114+ - name : Upload link check results
115+ uses : actions/upload-artifact@v3
116+ if : always()
117+ with :
118+ name : link-check-results
119+ path : link-check-results/
120+ retention-days : 30
121+
122+ - name : Create issue for broken links
123+ if : always() && github.event_name == 'schedule'
124+ uses : actions/github-script@v7
125+ with :
126+ script : |
127+ // Check if there's already an open issue for broken links
128+ const { data: issues } = await github.rest.issues.listForRepo({
129+ owner: context.repo.owner,
130+ repo: context.repo.repo,
131+ state: 'open',
132+ labels: ['documentation', 'broken-links']
133+ });
134+
135+ if (issues.length === 0) {
136+ // Create new issue
137+ await github.rest.issues.create({
138+ owner: context.repo.owner,
139+ repo: context.repo.repo,
140+ title: '🔗 Broken links detected in documentation',
141+ body: `
142+ ## Broken Links Detected
143+
144+ The scheduled link checker has detected broken links in the documentation.
145+
146+ **Workflow run**: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
147+ **Date**: ${new Date().toISOString()}
148+
149+ Please check the workflow logs and fix the broken links.
150+
151+ ### Actions Required
152+ - [ ] Review the link checker results
153+ - [ ] Fix or remove broken links
154+ - [ ] Update documentation if URLs have changed
155+ - [ ] Close this issue once fixed
156+
157+ This issue was created automatically by the link checker workflow.
158+ `,
159+ labels: ['documentation', 'broken-links', 'automated']
160+ });
161+ }
162+
163+ - name : Create summary
164+ if : always()
165+ run : |
166+ echo "## 🔗 Link Check Summary" >> $GITHUB_STEP_SUMMARY
167+ echo "" >> $GITHUB_STEP_SUMMARY
168+
169+ if [ "${{ job.status }}" = "success" ]; then
170+ echo "✅ All links are working correctly" >> $GITHUB_STEP_SUMMARY
171+ else
172+ echo "❌ Some links are broken" >> $GITHUB_STEP_SUMMARY
173+ echo "" >> $GITHUB_STEP_SUMMARY
174+ echo "Check the workflow logs and uploaded artifacts for details." >> $GITHUB_STEP_SUMMARY
175+ fi
176+
177+ echo "" >> $GITHUB_STEP_SUMMARY
178+ echo "### Configuration" >> $GITHUB_STEP_SUMMARY
179+ echo "- **Check external links**: ${{ github.event.inputs.check_external || 'true' }}" >> $GITHUB_STEP_SUMMARY
180+ echo "- **Fail on error**: ${{ github.event.inputs.fail_on_error || 'false' }}" >> $GITHUB_STEP_SUMMARY
181+ echo "- **Trigger**: ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
0 commit comments