1212 runs-on : ubuntu-latest
1313
1414 steps :
15- # 1️⃣ Checkout the repository
16- - name : Checkout code
15+ # 1️⃣ Checkout repository
16+ - name : Checkout repository
1717 uses : actions/checkout@v4
1818 with :
1919 fetch-depth : 0
@@ -23,53 +23,98 @@ jobs:
2323 id : changed-files
2424 run : |
2525 CHANGED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep '\.md$' || true)
26- CHANGED_FILES="${CHANGED_FILES//$'\n'/ }" # replace newlines with spaces
26+ CHANGED_FILES="${CHANGED_FILES//$'\n'/ }"
2727 echo "CHANGED_FILES=$CHANGED_FILES" >> $GITHUB_ENV
2828 echo "Changed Markdown files: $CHANGED_FILES"
2929
3030 # 3️⃣ Skip if no Markdown files changed
31- - name : Skip if no changed Markdown files
31+ - name : Skip if no Markdown files changed
3232 if : env.CHANGED_FILES == ''
3333 run : |
3434 echo "No Markdown files changed. Skipping link check."
3535 exit 0
3636
37- # 4️⃣ Run Lychee on changed files (compact output)
37+ # 4️⃣ Run Lychee on changed files
3838 - name : Run Lychee
3939 id : run-lychee
4040 uses : lycheeverse/lychee-action@v2
4141 with :
4242 args : |
4343 --no-progress
4444 --include-fragments
45- --format compact
45+ --format detailed
4646 ${{ env.CHANGED_FILES }}
4747 output : lychee/out_raw.md
48- fail : false # ✅ don't fail yet, let us capture output
48+ fail : false # ✅ don't fail yet, let us capture output
4949
50- # 5️⃣ Clean Lychee output (remove summary line + mark if has content )
51- - name : Clean Lychee output
52- id : clean-output
50+ # 5️⃣ Format Lychee output (user-friendly, relative paths )
51+ - name : Format Lychee report
52+ id : format-report
5353 if : always()
5454 run : |
55- grep -v '^🔍' lychee/out_raw.md > lychee/out.md || true
56- if [ -s lychee/out.md ]; then
55+ mkdir -p lychee
56+ : > lychee/comment.md # start with empty file
57+
58+ awk '
59+ /^Errors in / {
60+ file=$3
61+ gsub("^/home/runner/work/UmbracoDocs/UmbracoDocs/", "", file)
62+ print "\nFile : " file >> " lychee/comment.md"
63+ next
64+ }
65+
66+ /\[ERROR\]/ {
67+ msg = $0
68+ sub(/^- \[ \] /, "", msg)
69+ sub(/^\[ERROR\] /, "", msg)
70+ gsub("^file:///home/runner/work/UmbracoDocs/UmbracoDocs/", "", msg)
71+ print "⚓ Anchor not found → " msg >> "lychee/comment.md"
72+ next
73+ }
74+
75+ /\[404\]/ {
76+ msg = $0
77+ sub(/^- \[ \] /, "", msg)
78+ sub(/^\[404\] /, "", msg)
79+ print "❌ 404 Not Found → " msg >> "lychee/comment.md"
80+ next
81+ }
82+
83+ /\[301\]|\[302\]/ {
84+ msg = $0
85+ sub(/^- \[ \] /, "", msg)
86+ sub(/^\[(301|302)\] /, "", msg)
87+ print "🔀 Redirect → " msg >> "lychee/comment.md"
88+ next
89+ }
90+
91+ /Timeout/ && !/Timeouts/ {
92+ msg = $0
93+ sub(/^- \[ \] /, "", msg)
94+ print "⏳ Timeout → " msg >> "lychee/comment.md"
95+ next
96+ }
97+ ' lychee/out_raw.md
98+
99+ # Add header only if we found content
100+ if [ -s lychee/comment.md ]; then
101+ sed -i ' 1i 🚨 **Link Checker found broken links in this PR**\n' lychee/comment.md
57102 echo "has_content=true" >> $GITHUB_OUTPUT
58103 else
59104 echo "has_content=false" >> $GITHUB_OUTPUT
60105 fi
61106
62- # 6️⃣ Comment broken links on PR
107+ # 6️⃣ Comment broken links on PR (if present)
63108 - name : Comment broken links
64- if : always() && (env.CHANGED_FILES != '') && (steps.clean-output .outputs.has_content == 'true')
109+ if : always() && (env.CHANGED_FILES != '') && (steps.format-report .outputs.has_content == 'true')
65110 uses : marocchino/sticky-pull-request-comment@v2
66111 with :
67- path : lychee/out .md
112+ path : lychee/comment .md
68113 recreate : true
69114
70- # 7️⃣ Fail workflow if broken links are found
115+ # 7️⃣ Fail workflow if broken links exist
71116 - name : Fail workflow if broken links
72- if : steps.clean-output .outputs.has_content == 'true'
117+ if : steps.format-report .outputs.has_content == 'true'
73118 run : |
74119 echo "❌ Broken links detected. Please review the PR comment for details."
75120 exit 1
0 commit comments