1- # WHY: Automated link checking - behavior controlled by repo variable
2- # OBS: Set IS_ACTIVE_REPO=true in GitHub Repository Settings > Secrets and variables > Actions > Variables
3- # ALT: Default (no variable set) runs manual only - perfect for student repos
1+ # WHY-FILE : Automated link checking.
2+ # OBS: Behavior is configured in lychee.toml in this repository.
3+ # OBS: Runs on pull requests and monthly on schedule; manual trigger always available.
44
55name : Check Links
66
77on :
88 workflow_dispatch : # WHY: Manual trigger - always available
99
10- schedule :
11- - cron : " 0 6 1 * *" # WHY: Runs monthly (1st of month) if IS_ACTIVE_REPO=true
10+ pull_request : # WHY: Validates PR links before merge
1211
13- pull_request : # WHY: Validates PR links if IS_ACTIVE_REPO=true
12+ schedule :
13+ - cron : " 0 6 1 * *" # WHY: Runs monthly (1st of month)
1414
15- # WHY: Prevent multiple simultaneous link checks on same ref
1615concurrency :
16+ # WHY: Prevent multiple simultaneous link checks on same ref
1717 group : link-check-${{ github.ref }}
1818 cancel-in-progress : true
1919
2020jobs :
2121 lychee :
22- # WHY: Skip scheduled/PR runs unless IS_ACTIVE_REPO=true or manual trigger
23- # OBS: vars.IS_ACTIVE_REPO linted as error in VS Code but works on GitHub
24- if : github.event_name == 'workflow_dispatch' || vars.IS_ACTIVE_REPO == 'true'
25-
2622 runs-on : ubuntu-latest
2723
28- # WHY: Permissions needed for PR comments and issue creation
2924 permissions :
3025 contents : read
3126 issues : write
3227 pull-requests : write
3328
3429 steps :
35- - uses : actions/checkout@v6 # OBS: v6 current as of Dec 2025
30+ - name : 1) Checkout repository code
31+ uses : actions/checkout@v6 # OBS: v6 current as of Dec 2025
3632
37- # WHY: Check all documentation and config files for broken links
38- - name : Check links with Lychee
39- uses : lycheeverse/lychee-action@v2 # OBS: v2 current as of Dec 2025
33+ - name : 2) Check links with Lychee
34+ uses : lycheeverse/lychee-action@v2
4035 with :
4136 args : >
42- --verbose
43- --no-progress
37+ --config lychee.toml
4438 --user-agent "${{ github.repository }}/lychee"
4539 './**/*.bib'
4640 './**/*.md'
@@ -52,47 +46,49 @@ jobs:
5246 env :
5347 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
5448
55- # WHY: Provide helpful feedback on PRs with broken links
56- - name : Comment on PR if links broken
49+ - name : 3) Comment on PR if links broken
5750 if : failure() && github.event_name == 'pull_request'
58- uses : actions/github-script@v8 # OBS: v8 current as of Dec 2025
51+ uses : actions/github-script@v8
5952 with :
6053 script : |
61- const comment = `## Link Check Results
62-
63- Some links appear broken. Check the [workflow logs](${context.payload.repository.html_url}/actions/runs/${context.runId}) for details.`;
64-
65- github.rest.issues.createComment({
54+ const runUrl = `${context.payload.repository.html_url}/actions/runs/${context.runId}`;
55+ const comment = [
56+ "## Link Check Results",
57+ "",
58+ `Some links appear broken. Check the workflow logs: ${runUrl}`,
59+ ].join("\n");
60+
61+ await github.rest.issues.createComment({
6662 issue_number: context.issue.number,
6763 owner: context.repo.owner,
6864 repo: context.repo.repo,
69- body: comment
65+ body: comment,
7066 });
7167
72- # WHY: Track broken links found during scheduled checks
73- # OBS: Only creates issue if none already open with 'broken-links' label
74- - name : Create issue for scheduled failures
68+ - name : 4) Create issue for scheduled failures # WHY: Track broken links found during scheduled checks
69+ # OBS: Only creates issue if none already open with 'broken-links' label
7570 if : failure() && github.event_name == 'schedule'
76- uses : actions/github-script@v8 # OBS: v8 current as of Dec 2025
71+ uses : actions/github-script@v8
7772 with :
7873 script : |
79- const title = `Link Check Failed - ${new Date().toISOString().split('T')[0]}`;
80- const body = `Weekly link check found broken links. [Check logs](${context.payload.repository.html_url}/actions/runs/${context.runId})`;
74+ const date = new Date().toISOString().split("T")[0];
75+ const title = `Link Check Failed - ${date}`;
76+ const runUrl = `${context.payload.repository.html_url}/actions/runs/${context.runId}`;
77+ const body = `Monthly link check found broken links.\n\nWorkflow logs: ${runUrl}`;
8178
82- // WHY: Avoid duplicate issues
8379 const existing = await github.rest.issues.listForRepo({
8480 owner: context.repo.owner,
8581 repo: context.repo.repo,
86- labels: ' broken-links' ,
87- state: ' open'
82+ labels: " broken-links" ,
83+ state: " open",
8884 });
8985
9086 if (existing.data.length === 0) {
9187 await github.rest.issues.create({
9288 owner: context.repo.owner,
9389 repo: context.repo.repo,
94- title: title ,
95- body: body ,
96- labels: [' maintenance', ' broken-links']
90+ title,
91+ body,
92+ labels: [" maintenance", " broken-links"],
9793 });
9894 }
0 commit comments