Implement comprehensive link checker with image focus and CI/CD integration #5
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: PR Link Check | |
| on: | |
| pull_request: | |
| types: [labeled, synchronize, reopened] | |
| jobs: | |
| check-label: | |
| name: Check for link-check label | |
| runs-on: ubuntu-latest | |
| outputs: | |
| should-run: ${{ steps.check.outputs.should-run }} | |
| steps: | |
| - name: Check for link-check label | |
| id: check | |
| run: | | |
| if [[ "${{ contains(github.event.pull_request.labels.*.name, 'link-check') }}" == "true" ]]; then | |
| echo "should-run=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "should-run=false" >> $GITHUB_OUTPUT | |
| fi | |
| build-and-linkcheck: | |
| name: Build Site and Run Link Check | |
| runs-on: ubuntu-latest | |
| needs: check-label | |
| if: needs.check-label.outputs.should-run == 'true' | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Build site with Docker Compose | |
| run: | | |
| docker compose --profile manual run --rm dist | |
| docker compose --profile manual run --rm build | |
| - name: Start HTTP server and run link checker | |
| run: | | |
| # Start HTTP server in background | |
| docker compose up -d http_serve | |
| # Wait for server to be ready | |
| echo "⏳ Waiting for server to be ready..." | |
| timeout 60 bash -c 'until curl -s http://localhost:8082 > /dev/null; do sleep 2; done' || { | |
| echo "❌ Server not ready" | |
| docker compose logs http_serve | |
| exit 1 | |
| } | |
| # Run quick link checker (2min max) | |
| docker compose --profile manual run --rm broken_links_quick | |
| # Stop services | |
| docker compose down | |
| - name: Upload Link Check Report | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: pr-link-check-report-${{ github.event.number }} | |
| path: linkchecker_reports/ | |
| retention-days: 14 | |
| - name: Comment on PR with results | |
| uses: actions/github-script@v7 | |
| if: always() | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const path = './.github/linkchecker/output.csv'; | |
| let message = '## 🔗 Link Check Results\n\n'; | |
| if (fs.existsSync(path)) { | |
| const lines = fs.readFileSync(path, 'utf8') | |
| .split('\n') | |
| .filter(line => line.trim()); | |
| if (lines.length > 1) { | |
| const brokenCount = lines.length - 1; // Subtract header | |
| message += `❌ **Found ${brokenCount} broken links**\n\n`; | |
| message += `📊 [View detailed report](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})\n\n`; | |
| if (brokenCount <= 10) { | |
| message += '### Broken Links:\n'; | |
| const csvContent = fs.readFileSync(path, 'utf8'); | |
| const rows = csvContent.split('\n').slice(1, 11); | |
| for (const row of rows) { | |
| if (row.trim()) { | |
| const cols = row.split(';'); | |
| if (cols.length >= 3) { | |
| message += `- **${cols[1]}** in ${cols[0]} - ${cols[2]}\n`; | |
| } | |
| } | |
| } | |
| if (brokenCount > 10) { | |
| message += `\n... and ${brokenCount - 10} more. See full report above.\n`; | |
| } | |
| } | |
| } else { | |
| message += '✅ **No broken links found!**\n\n'; | |
| } | |
| } else { | |
| message += '⚠️ **Link check could not be completed**\n\n'; | |
| message += 'Please check the workflow logs for more information.\n'; | |
| } | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: message | |
| }); |