@@ -150,6 +150,63 @@ jobs:
150150 git commit -m "chore: update llms index [skip ci]"
151151 git push origin "HEAD:${BRANCH}"
152152
153+ - name : Validate llms.txt links
154+ if : env.NO_CHANGES != 'true'
155+ shell : bash
156+ run : |
157+ set -euo pipefail
158+ if [[ ! -f "llms.txt" ]]; then
159+ echo "llms.txt not found; skipping link check." >&2
160+ echo "LLMS_LINK_STATUS=llms.txt not found; link check skipped" >> "$GITHUB_ENV"
161+ exit 0
162+ fi
163+
164+ if ! command -v curl >/dev/null 2>&1; then
165+ echo "curl not available; skipping link check." >&2
166+ echo "LLMS_LINK_STATUS=curl missing; link check skipped" >> "$GITHUB_ENV"
167+ exit 0
168+ fi
169+
170+ PASSED=0
171+ FAILED=0
172+ FAIL_LINES=""
173+
174+ while IFS= read -r line; do
175+ case "$line" in
176+ -*\[*\]\(http*://*\)*)
177+ url="$(printf '%s\n' "$line" | sed -nE 's/.*\]\((https?:[^)]*)\).*/\1/p')"
178+ title="$(printf '%s\n' "$line" | sed -nE 's/^[[:space:]]*-[[:space:]]*\[([^]]+)\].*/\1/p')"
179+ if [[ -n "$url" ]]; then
180+ code="$(curl -o /dev/null -s -w "%{http_code}" --max-time 10 "$url" || echo "000")"
181+ if [[ "$code" =~ ^2[0-9][0-9]$ ]]; then
182+ PASSED=$((PASSED + 1))
183+ else
184+ FAILED=$((FAILED + 1))
185+ FAIL_LINES="${FAIL_LINES}"$'\n'" - ${title} -> ${url} (HTTP ${code})"
186+ fi
187+ fi
188+ ;;
189+ esac
190+ done < llms.txt
191+
192+ STATUS="Link check: ${PASSED} OK, ${FAILED} failed"
193+ echo "LLMS_LINK_STATUS=${STATUS}" >> "$GITHUB_ENV"
194+
195+ if (( FAILED > 0 )); then
196+ {
197+ echo "LLMS_LINK_DETAILS<<'EOF'"
198+ printf '%s\n' "${FAIL_LINES#"$'\n'"}"
199+ echo "EOF"
200+ } >> "$GITHUB_ENV"
201+ else
202+ echo "LLMS_LINK_DETAILS=" >> "$GITHUB_ENV"
203+ fi
204+
205+ echo "${STATUS}"
206+ if (( FAILED > 0 )); then
207+ echo "Some llms.txt links failed; see PR description for details." >&2
208+ fi
209+
153210 - name : Create pull request
154211 if : env.NO_CHANGES != 'true'
155212 uses : actions/github-script@v7
@@ -158,12 +215,21 @@ jobs:
158215 const defaultBranch = context.payload.repository.default_branch;
159216 const head = process.env.BRANCH;
160217 const title = 'chore: update Clix Flutter llms.txt index';
161- const body = [
218+ const linkStatus = process.env.LLMS_LINK_STATUS || 'not run';
219+ const linkDetails = process.env.LLMS_LINK_DETAILS || '';
220+ const bodyLines = [
162221 'This PR updates the generated Clix Flutter SDK llms.txt index.',
163222 '',
164223 `- Triggered by: ${context.eventName}`,
165- `- Range: ${process.env.COMPARE || '(none / full)'}`
166- ].join('\n');
224+ `- Range: ${process.env.COMPARE || '(none / full)'}`,
225+ `- Link check: ${linkStatus}`
226+ ];
227+ if (linkDetails.trim().length > 0) {
228+ bodyLines.push('');
229+ bodyLines.push('Link check details:');
230+ bodyLines.push(linkDetails);
231+ }
232+ const body = bodyLines.join('\n');
167233 try {
168234 const { data: pr } = await github.rest.pulls.create({
169235 owner: context.repo.owner,
0 commit comments