Skip to content

Commit 950c1c7

Browse files
ci(indexnow): derive the full URL list from the checkout, handle multi-commit pushes
Review feedback: fetching the live sitemap puts the Cloudflare edge between a GitHub runner and the list; the checkout carries the same information (spec directories, metadata files, the static pages). A push with more than one commit falls back to the full list instead of a diff that fetch-depth 2 cannot resolve. Transport errors after the curl retries warn instead of failing the run; 4xx still fails. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SrKzcwZBnref1sWYtdXynu
1 parent a4ae1b6 commit 950c1c7

2 files changed

Lines changed: 33 additions & 5 deletions

File tree

.github/workflows/indexnow-submit.yml

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,33 @@ jobs:
5959

6060
- name: Collect URLs
6161
id: urls
62+
env:
63+
# Number of commits in the push; a squash merge is exactly one.
64+
PUSH_COMMITS: ${{ github.event_name == 'push' && toJSON(github.event.commits) || '[]' }}
6265
run: |
6366
set -euo pipefail
67+
# The full list comes from the checkout, not from the live sitemap:
68+
# every spec directory is a hub page and every metadata file an
69+
# implementation page (the same rule the sitemap follows), plus the
70+
# static pages. No fetch means no Cloudflare edge or bot management
71+
# between a GitHub runner and the list, and the shallow checkout
72+
# still carries the complete tree.
73+
full_list() {
74+
for p in / /plots /specs /libraries /map /palette /about /mcp /legal /stats; do
75+
echo "https://${HOST}${p}"
76+
done
77+
git ls-tree -d --name-only HEAD plots/ | awk -F/ '{ print "https://'"$HOST"'/" $2 }'
78+
git ls-tree -r --name-only HEAD plots/ | awk -F/ '
79+
$3 == "metadata" && NF == 5 { lib = $5; sub(/\.[^.]+$/, "", lib); print "https://'"$HOST"'/" $2 "/" $4 "/" lib }'
80+
}
81+
commits=$(jq 'length' <<<"$PUSH_COMMITS")
6482
if [ "$SCOPE" = "sitemap" ]; then
65-
curl -sfS "https://${HOST}/sitemap.xml" \
66-
| grep -oE '<loc>[^<]+</loc>' | sed -E 's#</?loc>##g' | sort -u > urls.txt
83+
full_list | sort -u > urls.txt
84+
elif [ "$commits" -gt 1 ]; then
85+
# A multi-commit push (rare on main) is not what fetch-depth 2 can
86+
# diff; submitting everything is cheap and always correct.
87+
echo "::notice::push carries ${commits} commits; submitting the full list instead of a diff"
88+
full_list | sort -u > urls.txt
6789
else
6890
git diff --name-only HEAD~1 HEAD -- plots/ | awk -F/ '
6991
$1 != "plots" || NF < 3 { next }
@@ -93,16 +115,21 @@ jobs:
93115
'{host: $host, key: $key, keyLocation: $loc,
94116
urlList: ($list | split("\n") | map(select(length > 0)))}')
95117
# Bounded: a slow or flaky api.indexnow.org must not burn the job
96-
# timeout; three retries cover a transient error.
118+
# timeout; three retries cover a transient error, and a transport
119+
# error after them yields code 000 for the branch below instead of
120+
# aborting under `set -e`.
97121
code=$(curl -sS -o response.txt -w '%{http_code}' \
98122
--max-time 30 --retry 3 --retry-delay 5 --retry-all-errors \
99123
-X POST "https://api.indexnow.org/indexnow" \
100124
-H "Content-Type: application/json; charset=utf-8" \
101-
--data "$body")
125+
--data "$body") || code="000"
102126
n=$(grep -c . "$f")
103127
case "$code" in
104128
200|202) echo "::notice::IndexNow accepted ${n} URL(s) (HTTP ${code})" ;;
105129
# 4xx is a protocol or key problem on our side; make it visible.
106-
*) echo "::error::IndexNow returned HTTP ${code} for ${n} URL(s): $(head -c 300 response.txt)"; exit 1 ;;
130+
4*) echo "::error::IndexNow rejected ${n} URL(s) (HTTP ${code}): $(head -c 300 response.txt 2>/dev/null)"; exit 1 ;;
131+
# 5xx / no response: their side. Every later push resubmits its
132+
# own URLs and `scope=sitemap` covers a longer gap, so warn.
133+
*) echo "::warning::IndexNow unavailable (HTTP ${code}) for ${n} URL(s); resubmit with scope=sitemap if it persists" ;;
107134
esac
108135
done

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ aggregate instead: an italic *Catalog* line at the end of the version section an
3737
`api.indexnow.org` (10,000 per request; a deleted implementation is submitted too).
3838
`workflow_dispatch` with `scope=sitemap` submits the whole live sitemap for the initial
3939
load. Google does not take part and keeps reading the sitemap. The protocol is free.
40+
(#11202)
4041

4142
### Fixed
4243

0 commit comments

Comments
 (0)