fix(website): read the crawler config back from the right endpoint - #5394
Conversation
The sync succeeded but logged "Could not read the config back (404); skipping verification" — there is no GET on /config, so the check that exists to catch a bad sync had quietly done nothing. Read the crawler with ?withConfig=true instead, unwrapping the response and its config string. A 404 now fails the job: it means this URL is wrong rather than the service being unwell, and a verification step that silently no-ops is worse than not having one.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Warning Review limit reached
Next review available in: 32 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe crawler synchronization script reads configuration from the crawler endpoint with ChangesCrawler verification
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
This PR fixes the crawler-config verification step in the website’s Algolia crawler sync script by reading the configuration back from the correct API shape (crawler read with withConfig=true) and making a bad read-back endpoint (404) fail the job instead of silently skipping verification.
Changes:
- Switches verification read-back from
GET /configtoGET /crawlers/{id}?withConfig=true. - Unwraps the read-back payload (
data) and supportsconfigarriving as a JSON string. - Treats a 404 on read-back as a hard failure to prevent silent no-op verification.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@website/scripts/sync-algolia-crawler.mjs`:
- Around line 137-140: Update the read-back fetch in the sync flow around
readBack to catch transport errors such as timeouts or network failures, warn,
and continue processing; preserve the existing hard-failure behavior for HTTP
404 responses. Add coverage that mocks fetch rejection and verifies the warning
and continued execution.
- Around line 153-154: Update the read-back handling around readBack.ok to throw
an error for non-retryable 4xx responses instead of warning and continuing.
Preserve the existing verification flow for successful responses and retry
behavior for retryable failures, ensuring the sync job cannot complete
successfully when verification receives a non-retryable response.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: ac829fa9-b9b9-40a6-9ede-281a5d698cbb
📒 Files selected for processing (1)
website/scripts/sync-algolia-crawler.mjs
Review of the previous commit found the same weakness it was fixing, in the paths it did not cover: - A transport failure (timeout, reset) rejected `fetch` and fell through to the outer catch, failing the deploy over a blip that says nothing about the config the API had already accepted. It now warns and continues, matching how a 5xx is treated. - 401/403 only warned, so credentials that can PATCH but not read would have skipped verification silently — exactly how the wrong endpoint survived three runs. Non-retryable 4xx now fails; 429 still warns. - A non-JSON body threw a bare SyntaxError with no indication of what was being parsed. It now names the URL and attaches the cause. Each branch was exercised against a stubbed API: match verifies, drift fails, transport/timeout/503 warn and continue, 403/404/bad JSON fail.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@website/scripts/sync-algolia-crawler.mjs`:
- Around line 170-184: Move the readBack.json() call into the existing try block
that handles configuration parsing in the read-back flow. Ensure JSON body parse
failures use the same error handling as crawler.config parsing, preserving
readBackUrl in the message and the original error as cause.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 10044d3e-d59c-45ea-b412-0a97784bd76d
📒 Files selected for processing (1)
website/scripts/sync-algolia-crawler.mjs
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (3)
website/scripts/sync-algolia-crawler.mjs:158
- This comment says 429 is "worth retrying", but the code does not retry; it just warns and skips verification. Either add a retry loop or adjust the comment so behavior and documentation match.
* A 4xx means this request is wrong — bad URL, or credentials that PATCH but
* cannot read — rather than the service being unwell. Warning through it is
* how the previous endpoint stayed broken for three runs, so fail instead.
* 429 is the exception: that one is worth retrying, not diagnosing.
*/
website/scripts/sync-algolia-crawler.mjs:180
- If the read-back endpoint returns 200 but omits
config(e.g.withConfignot honored), we currently fall back to diffing against the crawler object, which tends to produce a misleading "stored something different" error. Fail explicitly when no config is returned so the failure points to the real problem.
const payload = await readBack.json();
// The crawler may arrive wrapped, and its config as a JSON string.
const crawler = payload.data ?? payload;
let stored;
try {
website/scripts/sync-algolia-crawler.mjs:168
- The 4xx failure path drops the response body, which makes diagnosing 401/403/404 errors harder (especially when the API includes a useful message). Include the response text in the thrown error before failing.
if (
readBack &&
readBack.status >= 400 &&
readBack.status < 500 &&
readBack.status !== 429
) {
throw new Error(
`Read-back failed (${readBack.status}) for ${readBackUrl}; verification cannot run.`,
);
}
`readBack.json()` sat outside the try, so a response body that is not JSON at all — a proxy error page, say — still threw a bare SyntaxError naming nothing. The previous stub run missed it because it returned a valid envelope wrapping an invalid config string, exercising only the inner parse. Both parses now share one boundary, and the stub suite covers a non-JSON body as well as a config returned unwrapped, so verification holds whichever shape the API responds with.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (3)
website/scripts/sync-algolia-crawler.mjs:179
storedfalls back to the entire crawler object whencrawler.configis missing. If the API returns a crawler payload withoutconfig(e.g., due to permissions orwithConfigbeing ignored), the diff will compare against the wrong shape and fail with a misleading “stored something different” message. It’s better to explicitly detect a crawler payload missingconfigand fail with a clear error that verification cannot run.
const crawler = payload.data ?? payload;
stored =
typeof crawler.config === 'string'
? JSON.parse(crawler.config)
: (crawler.config ?? crawler);
website/scripts/sync-algolia-crawler.mjs:158
- The comment says 429 “is worth retrying”, but the code doesn’t retry; it only skips verification. Either implement a retry/backoff, or update the comment to match the current behavior to avoid confusion during incident/debugging.
* A 4xx means this request is wrong — bad URL, or credentials that PATCH but
* cannot read — rather than the service being unwell. Warning through it is
* how the previous endpoint stayed broken for three runs, so fail instead.
* 429 is the exception: that one is worth retrying, not diagnosing.
*/
website/scripts/sync-algolia-crawler.mjs:149
- In the
fetchcatch handler,errorisn’t guaranteed to be anErrorinstance. Accessingerror.messagecan produceundefined(or throw if something non-object is thrown), which makes logs less useful. Converting to a safe string avoids that.
console.warn(`Could not reach ${readBackUrl} (${error.message}).`);
Two independent reviews found the verification could still pass while the
stored config differed, including in the one way it exists to catch.
- `unwrapFunctions` collapsed `{__type:'function', source}` to the bare
source string on both sides, so an extractor stored as a plain string —
which never executes, and whose only symptom is an empty index — compared
equal. It was added to avoid a false failure that cannot happen: the API
rejects bare strings outright. Removed; envelopes now compare structurally,
which also stops sibling keys such as a disabling flag being discarded.
- The diff ran over `Object.keys(sent)`, so anything present only in the
stored config was invisible: a setting hand-added in the dashboard, or a
key deleted from this file, which a partial update leaves in place. It now
diffs the union, ignoring the server-owned `apiKey`.
- Transport failures, 429 and 5xx warned and exited 0. A permanent mistake —
wrong host, a key that can write but not read — is indistinguishable from a
blip, so that path could stay green forever; the same shape as the 404 that
went unnoticed for three runs. Now retried twice, then failed. Nothing
reaches the end without either verifying or failing.
- A response without `config` was compared against the crawler object and
reported as drift in every field. It now says so plainly.
- The `cause` chain was attached but never printed, so failures lost their
reason. Print the error itself; no error here carries credentials.
Ten scenarios exercised against a stubbed API: match, wrapped envelope and
transient 5xx pass; stale stored key, bare extractor, envelope flag, missing
config, 403, persistent 429 and DNS failure all fail. Credential scan across
those paths finds nothing.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (2)
website/scripts/sync-algolia-crawler.mjs:127
- When retrying after a non-OK response, the response body should be cancelled before sleeping/retrying to avoid keeping the underlying connection open unnecessarily.
await sleep(retryDelaysMs[attempt]);
website/scripts/sync-algolia-crawler.mjs:90
- The PR description says transient read-back failures should warn without failing, but
readWithRetriescurrently throws on network errors (after retries) and on 429/5xx once retries are exhausted, which will fail the job instead of skipping verification. Please align either the implementation (warn + skip verification for transient failures) or the PR description / doc comment here so CI behavior matches the intended policy.
*
* Nothing here warns and carries on: a permanent mistake — a wrong host, a key
* that can write but not read — would otherwise look exactly like a blip and
* leave the job green with no verification, which is how the previous endpoint
* stayed broken for three runs.
The sync now works — but its verification step never ran:
There is no
GET /1/crawlers/{id}/config. The check built to catch a bad syncwas quietly doing nothing, which is how it went unnoticed for three runs.
?withConfig=trueand unwrap the response (data) andits
config, which may arrive as a JSON string.being unwell, and a verification step that silently no-ops is worse than not
having one. Transient failures still warn without failing.
Not yet verified end to end
The PATCH path is confirmed working in CI. The read-back path is not — it needs
the crawler API key, which I do not have. Before merging, this settles it in one
command:
Expected:
Verified: the stored configuration matches this repo.It is idempotent — it pushes the same config that is already live.
🤖 created by Claude Opus 5