1+ name : Check Broken Links in MDX Files
2+
3+ on :
4+ pull_request :
5+ paths :
6+ - ' mintlify/**/*.mdx'
7+
8+ permissions :
9+ contents : read
10+ pull-requests : write
11+
12+ jobs :
13+ check-broken-links :
14+ runs-on : ubuntu-latest
15+
16+ steps :
17+ - name : Checkout repository
18+ uses : actions/checkout@v4
19+
20+ - name : Setup Node.js
21+ uses : actions/setup-node@v4
22+ with :
23+ node-version : ' 18'
24+
25+ - name : Install Mintlify CLI
26+ run : npm install -g mintlify
27+
28+ - name : Run broken links check
29+ id : broken-links
30+ working-directory : mintlify
31+ run : |
32+ echo "Running mint broken-links in mintlify directory..."
33+
34+ # Run broken links check and capture both stdout and stderr
35+ set +e # Don't exit on error
36+ mint broken-links &> broken-links-output.txt
37+ mint_exit_code=$?
38+ set -e # Re-enable exit on error
39+
40+ echo "mint_exit_code=$mint_exit_code" >> $GITHUB_OUTPUT
41+
42+ # Show original output for debugging
43+ echo "Original mint output:"
44+ cat broken-links-output.txt
45+
46+ # Filter out /api-reference/ false positives with smarter grouping
47+ # This awk script processes the mint output and only keeps file sections that have non-/api-reference/ links
48+ awk '
49+ /^[^ ]/ {
50+ # This is a filename line
51+ current_file = $0
52+ has_real_links = 0
53+ links = ""
54+ }
55+ /^ / {
56+ # This is a link line (starts with 2 spaces)
57+ if ($0 !~ /\/api-reference\//) {
58+ has_real_links = 1
59+ }
60+ links = links $0 "\n"
61+ }
62+ /^$/ || /^[^ ]/ {
63+ # Empty line or new file - output previous section if it has real links
64+ if (current_file && has_real_links) {
65+ print current_file
66+ printf "%s", links
67+ if (NF == 0) print "" # preserve empty lines
68+ }
69+ if (/^[^ ]/) {
70+ current_file = $0
71+ has_real_links = 0
72+ links = ""
73+ }
74+ }
75+ END {
76+ # Handle the last file section
77+ if (current_file && has_real_links) {
78+ print current_file
79+ printf "%s", links
80+ }
81+ }
82+ ' broken-links-output.txt > filtered-output.txt
83+
84+ # Count the number of files with actual broken links (non-empty, non-header lines that don't start with space)
85+ broken_files_count=$(grep -c "^[^[:space:]].*\.mdx$" filtered-output.txt || echo "0")
86+
87+ # Check if there are any remaining broken links
88+ if [ "$broken_files_count" -gt 0 ]; then
89+ echo "has_broken_links=true" >> $GITHUB_OUTPUT
90+ echo "FILTERED_OUTPUT<<EOF" >> $GITHUB_OUTPUT
91+ cat filtered-output.txt >> $GITHUB_OUTPUT
92+ echo "EOF" >> $GITHUB_OUTPUT
93+ else
94+ echo "has_broken_links=false" >> $GITHUB_OUTPUT
95+ echo "FILTERED_OUTPUT=✅ No broken links found (after filtering out /api-reference/ paths)" >> $GITHUB_OUTPUT
96+ fi
97+
98+ - name : Comment on PR
99+ uses : actions/github-script@v7
100+ with :
101+ script : |
102+ const hasBrokenLinks = '${{ steps.broken-links.outputs.has_broken_links }}' === 'true';
103+ const filteredOutput = `${{ steps.broken-links.outputs.FILTERED_OUTPUT }}`;
104+
105+ let body;
106+ if (hasBrokenLinks) {
107+ body = `## 🔗 Broken Links Check Failed
108+
109+ The following broken links were found in the MDX files (after filtering out \`/api-reference/\` paths):
110+
111+ \`\`\`
112+ ${filteredOutput}
113+ \`\`\`
114+
115+ Please fix these broken links before merging.
116+
117+ > **Note**: Links under \`/api-reference/\` are automatically filtered out as they may be false positives.`;
118+ } else {
119+ body = `## ✅ Broken Links Check Passed
120+
121+ ${filteredOutput}
122+
123+ All MDX files in the \`mintlify/\` directory have been checked for broken links.
124+
125+ > **Note**: Links under \`/api-reference/\` are automatically filtered out as they may be false positives.`;
126+ }
127+
128+ // Find existing comment
129+ const comments = await github.rest.issues.listComments({
130+ owner: context.repo.owner,
131+ repo: context.repo.repo,
132+ issue_number: context.issue.number,
133+ });
134+
135+ const existingComment = comments.data.find(comment =>
136+ comment.user.login === 'github-actions[bot]' &&
137+ comment.body.includes('Broken Links Check')
138+ );
139+
140+ if (existingComment) {
141+ // Update existing comment
142+ await github.rest.issues.updateComment({
143+ owner: context.repo.owner,
144+ repo: context.repo.repo,
145+ comment_id: existingComment.id,
146+ body: body
147+ });
148+ } else {
149+ // Create new comment
150+ await github.rest.issues.createComment({
151+ owner: context.repo.owner,
152+ repo: context.repo.repo,
153+ issue_number: context.issue.number,
154+ body: body
155+ });
156+ }
157+
158+ - name : Fail if broken links found
159+ if : steps.broken-links.outputs.has_broken_links == 'true'
160+ run : |
161+ echo "Broken links found after filtering out /api-reference/ paths!"
162+ exit 1
0 commit comments