forked from practical-tutorials/project-based-learning
-
Notifications
You must be signed in to change notification settings - Fork 0
114 lines (102 loc) · 5.18 KB
/
Copy pathlink-rot.yml
File metadata and controls
114 lines (102 loc) · 5.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
name: Link rot sweep
on:
schedule:
- cron: "17 6 * * 1"
workflow_dispatch:
permissions:
contents: write
issues: write
pull-requests: write
concurrency:
group: link-rot-sweep
cancel-in-progress: false
jobs:
sweep:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
- name: Check every link in README.md
run: |
# check-links exits 1 as soon as any URL is dead/suspect -- that's the
# expected, reportable outcome of a link-rot sweep, not a script
# failure, so `|| true` here (state commit + issue upsert below are
# what actually need to keep running either way).
python3 scripts/check_readme.py check-links --all --state .github/link-rot-state.json --json > /tmp/results.json || true
python3 -c "import json; print('stats:', json.load(open('/tmp/results.json'))['stats'])" >> "$GITHUB_STEP_SUMMARY"
- name: Commit updated sweep state
continue-on-error: true
run: |
if git diff --quiet -- .github/link-rot-state.json; then
echo "No state changes to commit."
else
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add .github/link-rot-state.json
git commit -m "chore(link-rot): update sweep state [skip ci]"
git pull --rebase origin "${{ github.ref_name }}"
git push origin "HEAD:${{ github.ref_name }}"
fi
- name: Apply safe auto-fixes (remove confirmed-dead entries, update moved URLs)
id: prune
if: always()
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
# Only two categories are safe enough to fix without a human decision:
# entries confirmed dead for 2+ consecutive weeks (with no known redirect),
# and URLs that now redirect to a different working page. Everything else
# (SUSPECT, secondary/prose links, ambiguous matches) is left in the
# report for a human to judge -- see scripts/check_readme.py's cmd_prune
# docstring for the exact rules.
python3 scripts/check_readme.py prune \
--results /tmp/results.json --state .github/link-rot-state.json \
--readme README.md --pr-body-out /tmp/pr-body.md > /tmp/prune-summary.json
changed=$(python3 -c "import json; print(json.load(open('/tmp/prune-summary.json'))['changed'])")
if [ "$changed" != "True" ]; then
echo "Nothing to auto-fix this run."
exit 0
fi
removed=$(python3 -c "import json; print(len(json.load(open('/tmp/prune-summary.json'))['removals']))")
updated=$(python3 -c "import json; print(len(json.load(open('/tmp/prune-summary.json'))['updates']))")
branch="automated/link-rot-fixes"
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git checkout -B "$branch"
git add README.md
git commit -m "chore(link-rot): remove $removed confirmed-dead link(s), update $updated moved URL(s)"
git push --force-with-lease origin "HEAD:$branch"
if [ -z "$(gh pr list --repo "${{ github.repository }}" --head "$branch" --state open --json number --jq '.[0].number // empty')" ]; then
gh pr create --repo "${{ github.repository }}" --base "${{ github.ref_name }}" --head "$branch" \
--title "chore(link-rot): remove $removed confirmed-dead link(s), update $updated moved URL(s)" \
--body-file /tmp/pr-body.md --label link-rot
else
gh pr edit "$branch" --repo "${{ github.repository }}" --body-file /tmp/pr-body.md
fi
pr_url=$(gh pr view "$branch" --repo "${{ github.repository }}" --json url --jq '.url')
echo "pr_url=$pr_url" >> "$GITHUB_OUTPUT"
- name: Render report body
if: always()
env:
FIX_PR_URL: ${{ steps.prune.outputs.pr_url }}
run: |
if [ -n "$FIX_PR_URL" ]; then
python3 scripts/check_readme.py report --results /tmp/results.json --state .github/link-rot-state.json --fix-pr-url "$FIX_PR_URL" > /tmp/report-body.md
else
python3 scripts/check_readme.py report --results /tmp/results.json --state .github/link-rot-state.json > /tmp/report-body.md
fi
- name: Upsert consolidated link-rot report issue
if: always()
env:
GH_TOKEN: ${{ github.token }}
run: |
existing=$(gh issue list --repo "${{ github.repository }}" --search "🔗 Link rot report in:title" --label link-rot --state open --json number --jq '.[0].number // empty')
if [ -n "$existing" ]; then
gh issue edit "$existing" --repo "${{ github.repository }}" --body-file /tmp/report-body.md
else
gh issue create --repo "${{ github.repository }}" --title "🔗 Link rot report" --label link-rot --body-file /tmp/report-body.md
fi