Skip to content

Add Bump.sh proxy to preview API docs links in cloud-docs PRs#638

Open
kbatuigas wants to merge 1 commit into
mainfrom
add-bump-proxy-api-preview
Open

Add Bump.sh proxy to preview API docs links in cloud-docs PRs#638
kbatuigas wants to merge 1 commit into
mainfrom
add-bump-proxy-api-preview

Conversation

@kbatuigas

Copy link
Copy Markdown
Contributor

Description

link:/api/doc/... API reference links 404 in rp-cloud deploy previews. The /api/doc/... reference is the Bump.sh-hosted API docs, served by a Netlify edge function that proxies /api/* → Bump.sh. That proxy lives in the docs and docs-site repos but not in cloud-docs (which had no netlify.toml), so the links only resolve on production (built by docs-site), not in cloud-docs previews. The link syntax itself is already correct.

This mirrors redpanda-data/docs#1552 ("Add the Bump proxy for previewing API docs in PRs"):

  • netlify.toml — registers the /api/* edge function (identical to docs main).
  • netlify/edge-functions/proxy-api-docs.js — copied verbatim from docs main (includes the docs-site#182 cache-poisoning fix).

Validated on docs PR #1786's preview (branch that includes the same proxy): /api/doc/cloud-controlplane/authentication and /api/doc/admin/operation/operation-get_cluster_health_overview both return 200.

⚠️ Required infra step

BUMP_PROXY_SECRET must be set on the rp-cloud Netlify site (same value as the docs/docs-site sites). Without it the edge function returns 503. This is a Netlify dashboard step, not a repo change.

How to verify

Once the deploy preview builds and the secret is set, these should return 200 (not 404/503):

  • https://deploy-preview-<PR>--rp-cloud.netlify.app/api/doc/cloud-controlplane/authentication
  • https://deploy-preview-<PR>--rp-cloud.netlify.app/api/doc/cloud-controlplane/operation/operation-clusterservice_createcluster

No production impact: docs.redpanda.com is built by docs-site, which has its own proxy; this netlify.toml only affects the rp-cloud site.

Checks

  • Small fix (infra / preview tooling)

🤖 Generated with Claude Code

The API reference is served at /api/doc/... by a Netlify edge function
that proxies to Bump.sh. That proxy exists in the docs and docs-site
repos but not in cloud-docs, so link:/api/doc/... links 404 in rp-cloud
deploy previews (they resolve fine on production, which is built by
docs-site).

Mirror redpanda-data/docs#1552: add netlify.toml registering the
/api/* edge function and the proxy-api-docs.js function (copied verbatim
from docs main, includes the docs-site#182 cache-poisoning fix).

Requires BUMP_PROXY_SECRET to be set on the rp-cloud Netlify site.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kbatuigas
kbatuigas requested a review from a team as a code owner July 17, 2026 22:24
@netlify

netlify Bot commented Jul 17, 2026

Copy link
Copy Markdown

Deploy Preview for rp-cloud ready!

Name Link
🔨 Latest commit 9c010f2
🔍 Latest deploy log https://app.netlify.com/projects/rp-cloud/deploys/6a5aab84994482000822d28f
😎 Deploy Preview https://deploy-preview-638--rp-cloud.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds Netlify configuration for Node.js 22, local documentation publishing, and /api/* Edge Function routing. The new proxy normalizes routes, redirects legacy and markdown requests, validates BUMP_PROXY_SECRET, and fetches Bump.sh content with retries and timeouts. HTML responses are parsed and augmented with navigation, widget fragments, llms.txt discovery markup, and CSS. Non-HTML responses and upstream failures receive specialized responses.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant NetlifyEdgeFunction
  participant Bump.sh
  participant WidgetEndpoints
  Client->>NetlifyEdgeFunction: Request API documentation
  NetlifyEdgeFunction->>Bump.sh: Fetch rewritten documentation URL
  Bump.sh-->>NetlifyEdgeFunction: Return documentation response
  NetlifyEdgeFunction->>WidgetEndpoints: Fetch HTML widget fragments
  WidgetEndpoints-->>NetlifyEdgeFunction: Return widget HTML
  NetlifyEdgeFunction-->>Client: Return transformed or non-HTML response
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding a Bump.sh proxy for API docs previews in cloud-docs PRs.
Description check ✅ Passed The description covers the purpose, implementation, verification, and infra requirement, but omits the issue link, review deadline, and page previews.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-bump-proxy-api-preview

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 `@netlify.toml`:
- Around line 9-11: Update the [[edge_functions]] configuration for the
proxy-api-docs function to include cache = "manual", enabling its response
caching behavior and allowing the configured Cache-Control and Netlify-Vary
headers to take effect.

In `@netlify/edge-functions/proxy-api-docs.js`:
- Around line 84-88: Update fetchWithRetry to retry HTTP 429 and 5xx responses,
applying the existing retry limits and delay behavior while continuing to retry
network exceptions. In the caller’s non-successful response handling, preserve
non-retryable upstream statuses such as 404 instead of throwing an error path
that maps them to 503; return or propagate the original response status and body
as appropriate.
🪄 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: CHILL

Plan: Pro

Run ID: 5597b832-9de0-4742-88f3-ee1929729fb8

📥 Commits

Reviewing files that changed from the base of the PR and between 4824c0b and 9c010f2.

📒 Files selected for processing (2)
  • netlify.toml
  • netlify/edge-functions/proxy-api-docs.js

Comment thread netlify.toml
Comment on lines +9 to +11
[[edge_functions]]
path = "/api/*"
function = "proxy-api-docs"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does Netlify Edge Function response caching require cache = "manual" when Cache-Control and Netlify-Vary headers are returned?

💡 Result:

Yes, configuring an Edge Function for caching requires explicitly opting in by setting the cache property to manual [1][2]. Netlify Edge Function responses are not cached by default because they are dynamic [3][4]. Simply returning Cache-Control or Netlify-Vary headers in your function response is insufficient on its own; if the cache property is not set to manual (either inline in the function code or via netlify.toml), the function will continue to execute on every request, and the cache headers will not be honored for edge caching [1][2]. To enable caching for your Edge Function, you must complete both of these steps [2]: 1. Opt in to caching by setting cache = "manual" in your function declaration [1][5]. 2. Customize the caching behavior by including appropriate HTTP headers (such as Cache-Control or Netlify-Vary) in your response [1][3]. If you perform only one of these actions, the responses will not be cached by the edge [2]. Once cache = "manual" is configured, Netlify will respect the Cache-Control and Netlify-Vary headers you return to manage how the response is cached and how cache keys are generated [1][3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Repo root: '; pwd

echo '--- netlify.toml ---'
nl -ba netlify.toml | sed -n '1,80p'

echo '--- edge function files ---'
fd -a 'proxy-api-docs' .

echo '--- search for caching headers/config ---'
rg -n --hidden --glob '!**/.git/**' 'cache\s*=\s*"manual"|Cache-Control|Netlify-Vary|edge_functions|proxy-api-docs' .

Repository: redpanda-data/cloud-docs

Length of output: 253


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- locate netlify.toml ---'
fd -a '^netlify\.toml$' .

echo '--- netlify.toml with line numbers ---'
sed -n '1,80p' netlify.toml | cat -n

echo '--- locate proxy-api-docs implementation ---'
fd -a 'proxy-api-docs' .

echo '--- search for caching-related headers and edge function config ---'
rg -n --hidden --glob '!**/.git/**' 'cache\s*=\s*"manual"|Cache-Control|Netlify-Vary|edge_functions|proxy-api-docs' .

Repository: redpanda-data/cloud-docs

Length of output: 914


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- proxy-api-docs.js outline ---'
ast-grep outline netlify/edge-functions/proxy-api-docs.js --view expanded

echo '--- proxy-api-docs.js relevant lines ---'
sed -n '1,220p' netlify/edge-functions/proxy-api-docs.js | cat -n

Repository: redpanda-data/cloud-docs

Length of output: 10050


Opt this Edge Function into response caching. Add cache = "manual" to netlify.toml:9-11; otherwise the proxy still runs on every request and the Cache-Control / Netlify-Vary headers won’t take effect.

Proposed fix
 [[edge_functions]]
 path = "/api/*"
 function = "proxy-api-docs"
+cache = "manual"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[[edge_functions]]
path = "/api/*"
function = "proxy-api-docs"
[[edge_functions]]
path = "/api/*"
function = "proxy-api-docs"
cache = "manual"
🤖 Prompt for 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.

In `@netlify.toml` around lines 9 - 11, Update the [[edge_functions]]
configuration for the proxy-api-docs function to include cache = "manual",
enabling its response caching behavior and allowing the configured Cache-Control
and Netlify-Vary headers to take effect.

Comment on lines +84 to +88
// Handle non-successful responses
if (!bumpRes.ok) {
console.error(`❌ Bump.sh returned ${bumpRes.status}: ${bumpRes.statusText}`);
throw new Error(`Bump.sh API error: ${bumpRes.status}`);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Retry transient HTTP failures without converting every upstream error to 503.

fetchWithRetry retries only network exceptions, so HTTP 429/5xx responses return immediately. The caller then throws for every non-2xx response, causing permanent statuses such as 404 to be reported as 503. Retry 429/5xx inside the helper and preserve non-retryable upstream statuses.

Proposed approach
-    if (!bumpRes.ok) {
+    if (!bumpRes.ok && bumpRes.status >= 400 && bumpRes.status < 500) {
       console.error(`❌ Bump.sh returned ${bumpRes.status}: ${bumpRes.statusText}`);
-      throw new Error(`Bump.sh API error: ${bumpRes.status}`);
+      return bumpRes;
     }
       const response = await fetch(url, {
         ...options,
         signal: AbortSignal.timeout(10000),
       });
-      return response;
+
+      const retryable = response.status === 429 || response.status >= 500;
+      if (!retryable || attempt === maxRetries) {
+        return response;
+      }
+
+      await response.body?.cancel();

Also applies to: 275-294

🤖 Prompt for 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.

In `@netlify/edge-functions/proxy-api-docs.js` around lines 84 - 88, Update
fetchWithRetry to retry HTTP 429 and 5xx responses, applying the existing retry
limits and delay behavior while continuing to retry network exceptions. In the
caller’s non-successful response handling, preserve non-retryable upstream
statuses such as 404 instead of throwing an error path that maps them to 503;
return or propagate the original response status and body as appropriate.

@kbatuigas
kbatuigas requested a review from JakeSCahill July 17, 2026 22:32

@JakeSCahill JakeSCahill left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants