Skip to content

Preview: reuse backend PR's Convex preview instead of redeploying (fix dual-deploy race)#1859

Open
chelojimenez wants to merge 7 commits intomainfrom
claude/pr-preview-workflow-Tu645
Open

Preview: reuse backend PR's Convex preview instead of redeploying (fix dual-deploy race)#1859
chelojimenez wants to merge 7 commits intomainfrom
claude/pr-preview-workflow-Tu645

Conversation

@chelojimenez
Copy link
Copy Markdown
Contributor

@chelojimenez chelojimenez commented Apr 19, 2026

Summary

Pairs with MCPJam/mcpjam-backend#145. Fixes the silent-staging-fallback crash the author hits when cross-repo PRs open on the same branch.

The bug: when this flow detected a matching backend branch, it unconditionally dispatched inspector_preview_requested even if an open backend PR was already managing the Convex preview for that branch. Backend's deploy-preview ran a second convex deploy --preview-create <branch> concurrently with the first (they were in different concurrency groups). The loser's convex env set / smoke-test lost the race, fired backend_preview_failed, and this Railway env was wired to staging Convex → "Open preview" crashed on any PR-only schema.

The fix (this PR):

  1. New step Look up matching backend PR finds an open backend PR on the same branch.
  2. New step Reuse existing backend preview Convex URLs reads the backend-PR's pr-be-<BN> Railway env VITE_CONVEX_URL / CONVEX_HTTP_URL via railway run printenv. If both look like real preview URLs (distinct from staging), it overwrites this env's Convex URLs before railway up so the Vite build bakes in the shared preview URL.
  3. Dispatch backend preview request is skipped when reuse succeeded — no redundant deploy fires.
  4. Verify initial preview can reach Convex now targets the reused Convex URL when reuse succeeded.
  5. Preview comment says Backend target: shared with <backend_repo>#<N> on reuse.

Graceful fallback: if the backend env doesn't exist yet (PR opened seconds ago) or still has its staging-duplicated defaults (backend's sync-backend-preview hasn't run yet), the reuse step short-circuits fast and the original dispatch path runs. Paired with the backend's branch-keyed concurrency fix, that path is now race-safe on its own.

CORS: no change needed — DEFAULT_ALLOWED_ORIGINS in mcpjam-backend/convex/http.ts:29-40 already contains https://*.up.railway.app and matchesAllowedOrigin handles the wildcard, so both Railway preview URLs can talk to the shared Convex preview.

Test plan

  • Open this PR + MCPJam/mcpjam-backend#145 on the same branch.
  • Preview comment here shows Backend target: shared with MCPJam/mcpjam-backend#145, not staging fallback.
  • mcpjam-backend Actions shows at most one deploy-preview run (not two).
  • Open the preview URL — loads without CORS errors on Convex calls.
  • Regression: close mcpjam-backend#145, push a new commit here — inspector falls back to dispatching its own inspector_preview_requested and gets a working preview standalone.

https://claude.ai/code/session_01VoAzjkg2L5TuzNqyhnAyT5


Note

Medium Risk
Changes PR preview deployment logic in GitHub Actions to conditionally reuse backend PR Convex URLs and skip dispatching backend deploys; mistakes here could misconfigure preview environments or bake incorrect backend URLs into builds.

Overview
Prevents a dual-deploy race in the pr-preview.yml workflow by detecting an open backend PR on the same branch and, when present, reusing that backend PR’s Convex preview URLs (read from the backend PR’s pr-be-<N> Railway env) before running railway up.

When reuse succeeds, the workflow now skips dispatching inspector_preview_requested, updates the initial Convex health check to target the reused URL, and adjusts the PR comment to report that the backend target is shared with the matching backend PR. Also includes a no-op whitespace tweak in docs/README.md.

Reviewed by Cursor Bugbot for commit 18759cc. Bugbot is set up for automated code reviews on this repo. Configure here.

Opens an inspector PR on claude/pr-preview-workflow-Tu645 alongside
a backend PR on the same branch name to reproduce the race where
both upsert-backend-pr-preview (from the backend PR) and
upsert-preview (from this PR) dispatch concurrent
`convex deploy --preview-create` against the same Convex preview.

https://claude.ai/code/session_01VoAzjkg2L5TuzNqyhnAyT5
@mintlify
Copy link
Copy Markdown
Contributor

mintlify Bot commented Apr 19, 2026

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
mcpjam 🟢 Ready View Preview Apr 19, 2026, 1:21 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@chelojimenez
Copy link
Copy Markdown
Contributor Author

chelojimenez commented Apr 19, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 19, 2026

Internal preview

Preview URL will appear in Railway after the deploy finishes.
Deployed commit: 38ff88e
PR head commit: 18759cc
Backend target: preview requested.
Access is employee-only in non-production environments.

When an inspector PR opens on a branch that already has an open
backend PR, the inspector-PR flow used to unconditionally dispatch
`inspector_preview_requested` to the backend, triggering a second
`convex deploy --preview-create <branch>` that races the
backend-PR flow's deploy of the same Convex preview. The losing
deploy's `backend_preview_failed` callback wired this PR's Railway
env to staging Convex, crashing `Open preview` on any PR-only
schema.

Fix: before `railway up`, look up an open backend PR on the same
branch and read its `pr-be-<BN>` Railway env's VITE_CONVEX_URL /
CONVEX_HTTP_URL. If both look like real preview URLs (distinct
from staging), overwrite this env's Convex URLs with them so the
build bakes in the shared preview URL, and skip
"Dispatch backend preview request" so no redundant deploy fires.
If the backend env isn't populated yet (race with backend's
sync-backend-preview) the step short-circuits fast and falls
through to the original dispatch path — paired with the backend's
branch-keyed concurrency fix, that path is now race-safe.

https://claude.ai/code/session_01VoAzjkg2L5TuzNqyhnAyT5
@chelojimenez chelojimenez changed the title Test: reproduce dual convex-deploy race on shared preview branch Preview: reuse backend PR's Convex preview instead of redeploying (fix dual-deploy race) Apr 19, 2026
The previous Look up matching backend PR step ran
`jq -r '.[0].number // empty'` on whatever curl returned. If
BACKEND_PREVIEW_DISPATCH_TOKEN lacks pulls:read (it was originally
scoped only to branches + repository_dispatch), GitHub returns a
single JSON error object, jq errors "Cannot index object with
number", and `set -euo pipefail` kills the step. That took out the
whole upsert-preview job in ~17s on inspector#1859, leaving the
preview URL blank and the comment stuck on "Backend target:
preview requested".

Fix:
- Capture body + HTTP status separately; skip reuse gracefully on
  any non-200 (warning only, not an error).
- Type-guard the jq filter to `type == "array"` so an error-object
  response falls through instead of aborting.
- Allow jq itself to fail without killing the step (|| echo "").

Reuse is a nice-to-have; a missing token scope should never block
the preview from deploying at all.

https://claude.ai/code/session_01VoAzjkg2L5TuzNqyhnAyT5
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 19, 2026

Preview watchdog

The "preview requested" state has been stuck for ~6769 minutes.
The backend callback probably dropped (token expired, dispatch failed, or the backend job crashed).

Recover: re-run the upsert-preview workflow for this PR, or push an empty commit.

Watchdog runs every 15 minutes; this comment updates in place when conditions change.

@chelojimenez chelojimenez marked this pull request as ready for review April 19, 2026 21:03
@dosubot dosubot Bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Apr 19, 2026
@dosubot dosubot Bot added the bug Something isn't working label Apr 19, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 19, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 27f8ae87-8766-44f7-b934-b64de2488817

📥 Commits

Reviewing files that changed from the base of the PR and between 6fe2a66 and 51a7061.

📒 Files selected for processing (1)
  • .github/workflows/pr-preview.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/pr-preview.yml

Walkthrough

The preview workflow now looks up a matching backend PR via the GitHub API and records existence and number without failing on non-200 responses. If a backend PR exists, the workflow inspects its Railway environment and, when Convex URLs are present, valid, and differ from staging, it rewires the preview’s Convex endpoints and flags reuse. The Convex reachability check and backend dispatch respect the reused URL (skipping dispatch when reused). The preview comment’s BACKEND_MODE notes shared backend info when reuse occurs. A newline was appended to docs/README.md.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
docs/README.md (1)

47-47: Remove the test-only breadcrumb from docs.

This hidden comment reads like PR scaffolding, not lasting documentation. Keep the race context in the PR or workflow comments instead.

Proposed cleanup
-<!-- Test PR to reproduce dual-deploy race on shared Convex preview branch. -->
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/README.md` at line 47, Remove the test-only HTML comment "<!-- Test PR
to reproduce dual-deploy race on shared Convex preview branch. -->" from the
README by deleting that line (it's a transient PR scaffold, not documentation);
ensure no other PR-scaffold or test-only breadcrumbs remain in the docs and move
any necessary race/context explanations into the PR description or workflow
comments instead.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/pr-preview.yml:
- Around line 241-263: Normalize and validate the VITE_URL and HTTP_URL before
comparing or reusing them: trim trailing slashes and run a simple URL format
check (scheme + host) to avoid malformed strings passing; then compare the
normalized VITE_URL/HTTP_URL against STAGING_VITE_CONVEX_URL and
STAGING_CONVEX_HTTP_URL (also normalized) to decide early exit. Additionally, if
available in the Railway backend env, read CONVEX_DEPLOY_KEY and require it to
start with "preview:" before allowing reuse; only after
normalization+validation+deploy-key check should you call the railway variable
set step and write vite_convex_url/convex_http_url to GITHUB_OUTPUT using the
normalized values.

---

Nitpick comments:
In `@docs/README.md`:
- Line 47: Remove the test-only HTML comment "<!-- Test PR to reproduce
dual-deploy race on shared Convex preview branch. -->" from the README by
deleting that line (it's a transient PR scaffold, not documentation); ensure no
other PR-scaffold or test-only breadcrumbs remain in the docs and move any
necessary race/context explanations into the PR description or workflow comments
instead.
🪄 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: ae63d0cc-3929-4c3f-bd9c-461ab03302fd

📥 Commits

Reviewing files that changed from the base of the PR and between 123819b and f19fc90.

📒 Files selected for processing (2)
  • .github/workflows/pr-preview.yml
  • docs/README.md

Comment thread .github/workflows/pr-preview.yml Outdated
Comment on lines +241 to +263
# Only reuse real Convex preview URLs. If the backend Railway env
# is still on its staging-duplicated defaults (sync-backend-preview
# hasn't run yet), skip reuse so we don't mask a real race.
if [ -z "$VITE_URL" ] || [ -z "$HTTP_URL" ] \
|| [ "$VITE_URL" = "$STAGING_VITE_CONVEX_URL" ] \
|| [ "$HTTP_URL" = "$STAGING_CONVEX_HTTP_URL" ]; then
echo "::notice::Backend env $BE_ENV has no preview Convex URLs yet; falling through to dispatch."
echo "reused=false" >> "$GITHUB_OUTPUT"
exit 0
fi
.github/scripts/railway-retry.sh railway link \
--project "$RAILWAY_PROJECT_ID" \
--environment "${{ steps.meta.outputs.environment }}" \
--service "$RAILWAY_INSPECTOR_SERVICE" \
--json >/dev/null
.github/scripts/railway-retry.sh railway variable set \
-e "${{ steps.meta.outputs.environment }}" \
-s "$RAILWAY_INSPECTOR_SERVICE" \
VITE_CONVEX_URL="$VITE_URL" \
CONVEX_HTTP_URL="$HTTP_URL"
echo "reused=true" >> "$GITHUB_OUTPUT"
echo "vite_convex_url=$VITE_URL" >> "$GITHUB_OUTPUT"
echo "convex_http_url=$HTTP_URL" >> "$GITHUB_OUTPUT"
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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

What are the current Convex preview deployment URL formats and environment variables that distinguish preview deployments from production/development deployments?

💡 Result:

Convex preview deployment URL formats follow the standard Convex deployment pattern: https://[unique-adjective]-[unique-noun]-[number].convex.cloud, identical to production and development deployments. The unique identifier typically incorporates the preview name (e.g., Git branch name) to distinguish them. All deployment types share the same domain and format; distinction is based on the specific subdomain generated during deployment. To distinguish deployments in code: - Parse process.env.CONVEX_CLOUD_URL (always available in Convex functions, e.g., https://dusty-nightingale-847.convex.cloud). Preview deployments have unique subdomains tied to branch names. - Check process.env.CONVEX_DEPLOY_KEY during deployment (starts with 'preview:' for preview deploy keys vs 'prod:' for production). - No dedicated environment variable like 'DEPLOYMENT_TYPE' is documented for runtime distinction in functions; use URL parsing or deploy key prefix if needed. Development deployments are per-user and also use unique subdomains. Preview deployments are created using a preview deploy key set in CONVEX_DEPLOY_KEY (format: preview:team-slug:project-slug|ey...), triggered in CI like Vercel/Netlify previews.

Citations:


Harden URL validation, but note that format checks alone won't distinguish preview from production.

Line 244's check for empty/staging-exact values is insufficient—trailing slash mismatches or malformed URLs could pass through. URL normalization is needed to catch those edge cases.

However, the suggested regex validation against .convex.cloud won't actually prevent a production URL from reusing, since production and preview deployments share identical domain formats (https://[adjective]-[noun]-[number].convex.cloud). If the workflow must verify these are preview URLs specifically, the only documented distinguishing signal is the CONVEX_DEPLOY_KEY environment variable (prefix preview: vs prod:), not the runtime URL format.

Consider:

  • Normalize URLs to remove trailing slashes and validate format (prevents malformed URLs)
  • If available in the Railway backend env, check CONVEX_DEPLOY_KEY for preview: prefix to confirm deployment type
  • Otherwise, rely on the Railway environment itself being correctly configured as preview-only
Normalized URL validation shape
+          normalize_url() {
+            printf '%s' "$1" | sed 's#/*$##'
+          }
+          VITE_URL=$(normalize_url "$VITE_URL")
+          HTTP_URL=$(normalize_url "$HTTP_URL")
+          STAGING_VITE_URL=$(normalize_url "$STAGING_VITE_CONVEX_URL")
+          STAGING_HTTP_URL=$(normalize_url "$STAGING_CONVEX_HTTP_URL")
+
           # Only reuse real Convex preview URLs. If the backend Railway env
           # is still on its staging-duplicated defaults (sync-backend-preview
           # hasn't run yet), skip reuse so we don't mask a real race.
-          if [ -z "$VITE_URL" ] || [ -z "$HTTP_URL" ] \
-            || [ "$VITE_URL" = "$STAGING_VITE_CONVEX_URL" ] \
-            || [ "$HTTP_URL" = "$STAGING_CONVEX_HTTP_URL" ]; then
+          if [ -z "$VITE_URL" ] || [ -z "$HTTP_URL" ] \
+            || [ "$VITE_URL" = "$STAGING_VITE_URL" ] \
+            || [ "$HTTP_URL" = "$STAGING_HTTP_URL" ] \
+            || ! [[ "$VITE_URL" =~ ^https://[A-Za-z0-9-]+\.convex\.(cloud|site)$ ]] \
+            || ! [[ "$HTTP_URL" =~ ^https://[A-Za-z0-9-]+\.convex\.(cloud|site)$ ]]; then
             echo "::notice::Backend env $BE_ENV has no preview Convex URLs yet; falling through to dispatch."
             echo "reused=false" >> "$GITHUB_OUTPUT"
             exit 0
           fi
📝 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
# Only reuse real Convex preview URLs. If the backend Railway env
# is still on its staging-duplicated defaults (sync-backend-preview
# hasn't run yet), skip reuse so we don't mask a real race.
if [ -z "$VITE_URL" ] || [ -z "$HTTP_URL" ] \
|| [ "$VITE_URL" = "$STAGING_VITE_CONVEX_URL" ] \
|| [ "$HTTP_URL" = "$STAGING_CONVEX_HTTP_URL" ]; then
echo "::notice::Backend env $BE_ENV has no preview Convex URLs yet; falling through to dispatch."
echo "reused=false" >> "$GITHUB_OUTPUT"
exit 0
fi
.github/scripts/railway-retry.sh railway link \
--project "$RAILWAY_PROJECT_ID" \
--environment "${{ steps.meta.outputs.environment }}" \
--service "$RAILWAY_INSPECTOR_SERVICE" \
--json >/dev/null
.github/scripts/railway-retry.sh railway variable set \
-e "${{ steps.meta.outputs.environment }}" \
-s "$RAILWAY_INSPECTOR_SERVICE" \
VITE_CONVEX_URL="$VITE_URL" \
CONVEX_HTTP_URL="$HTTP_URL"
echo "reused=true" >> "$GITHUB_OUTPUT"
echo "vite_convex_url=$VITE_URL" >> "$GITHUB_OUTPUT"
echo "convex_http_url=$HTTP_URL" >> "$GITHUB_OUTPUT"
normalize_url() {
printf '%s' "$1" | sed 's#/*$##'
}
VITE_URL=$(normalize_url "$VITE_URL")
HTTP_URL=$(normalize_url "$HTTP_URL")
STAGING_VITE_URL=$(normalize_url "$STAGING_VITE_CONVEX_URL")
STAGING_HTTP_URL=$(normalize_url "$STAGING_CONVEX_HTTP_URL")
# Only reuse real Convex preview URLs. If the backend Railway env
# is still on its staging-duplicated defaults (sync-backend-preview
# hasn't run yet), skip reuse so we don't mask a real race.
if [ -z "$VITE_URL" ] || [ -z "$HTTP_URL" ] \
|| [ "$VITE_URL" = "$STAGING_VITE_URL" ] \
|| [ "$HTTP_URL" = "$STAGING_HTTP_URL" ] \
|| ! [[ "$VITE_URL" =~ ^https://[A-Za-z0-9-]+\.convex\.(cloud|site)$ ]] \
|| ! [[ "$HTTP_URL" =~ ^https://[A-Za-z0-9-]+\.convex\.(cloud|site)$ ]]; then
echo "::notice::Backend env $BE_ENV has no preview Convex URLs yet; falling through to dispatch."
echo "reused=false" >> "$GITHUB_OUTPUT"
exit 0
fi
.github/scripts/railway-retry.sh railway link \
--project "$RAILWAY_PROJECT_ID" \
--environment "${{ steps.meta.outputs.environment }}" \
--service "$RAILWAY_INSPECTOR_SERVICE" \
--json >/dev/null
.github/scripts/railway-retry.sh railway variable set \
-e "${{ steps.meta.outputs.environment }}" \
-s "$RAILWAY_INSPECTOR_SERVICE" \
VITE_CONVEX_URL="$VITE_URL" \
CONVEX_HTTP_URL="$HTTP_URL"
echo "reused=true" >> "$GITHUB_OUTPUT"
echo "vite_convex_url=$VITE_URL" >> "$GITHUB_OUTPUT"
echo "convex_http_url=$HTTP_URL" >> "$GITHUB_OUTPUT"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/pr-preview.yml around lines 241 - 263, Normalize and
validate the VITE_URL and HTTP_URL before comparing or reusing them: trim
trailing slashes and run a simple URL format check (scheme + host) to avoid
malformed strings passing; then compare the normalized VITE_URL/HTTP_URL against
STAGING_VITE_CONVEX_URL and STAGING_CONVEX_HTTP_URL (also normalized) to decide
early exit. Additionally, if available in the Railway backend env, read
CONVEX_DEPLOY_KEY and require it to start with "preview:" before allowing reuse;
only after normalization+validation+deploy-key check should you call the railway
variable set step and write vite_convex_url/convex_http_url to GITHUB_OUTPUT
using the normalized values.

- Drop the `<!-- Test PR to reproduce dual-deploy race ... -->` line
  from docs/README.md. It was scaffolding to open the test PR on this
  branch and doesn't belong in main.
- Normalize trailing slashes on both the discovered and staging
  Convex URLs before comparing, so `https://x.convex.cloud/` vs
  `https://x.convex.cloud` can't slip past the staging-equality check
  and let staging URLs reach the reuse path.
- Reject discovered URLs that don't match the
  `https://*.convex.{cloud,site}` shape — guards against a manually
  mis-set Railway var. Domain alone can't distinguish prod from
  preview Convex deployments (they share the format), but our
  scoping (only reading from `pr-be-<N>` envs) plus the
  MCPJAM_NONPROD_LOCKDOWN guard on every preview deployment make
  a prod-leak path infeasible without an attacker also writing to
  a backend-PR Railway env.

Skipped the CodeRabbit suggestion to check `CONVEX_DEPLOY_KEY` for
a `preview:` prefix — that secret lives only on the backend repo's
GitHub Actions, not on Railway envs, so it isn't readable here.

https://claude.ai/code/session_01VoAzjkg2L5TuzNqyhnAyT5
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/pr-preview.yml:
- Around line 216-280: The script leaves errexit disabled causing failures in
the final mutating Railway calls to be ignored; before invoking
.github/scripts/railway-retry.sh railway link and
.github/scripts/railway-retry.sh railway variable set (the two mutating calls
near the end of the step), re-enable errexit (e.g. restore set -e or set -euo
pipefail) so any non-zero exit from railway-retry.sh surfaces and the script
falls back to dispatch; after the mutating calls you can (optionally) restore
the previous -u behavior if needed.
🪄 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: da799b26-8cac-4846-9aba-6dc3e130222e

📥 Commits

Reviewing files that changed from the base of the PR and between f19fc90 and 6fe2a66.

📒 Files selected for processing (2)
  • .github/workflows/pr-preview.yml
  • docs/README.md
✅ Files skipped from review due to trivial changes (1)
  • docs/README.md

Comment thread .github/workflows/pr-preview.yml
The step opened with `set -uo pipefail` (no -e) deliberately, so the
early `railway link` probe to `pr-be-<N>` could soft-fail when the
backend env doesn't exist yet. But that left the FINAL two
`railway-retry.sh` calls — link + variable set on `pr-<N>` — with
errexit still off. If either failed, the script would happily write
`reused=true` to `$GITHUB_OUTPUT`, the dispatch step would be
skipped, and `railway up` would build with the STAGING Convex URLs
still on the env (set by "Configure staging-safe preview defaults")
baked into the Vite bundle. Initial health check would target the
backend's Convex from the step output, falsely report ✅, and the
preview comment would claim `shared with <backend>#N` while the
deployed inspector actually talks to staging — the exact crash mode
this PR is supposed to prevent.

Fix: re-enable errexit (`set -e`) right before the mutating calls,
after every soft-fall-through path has already exited 0.

https://claude.ai/code/session_01VoAzjkg2L5TuzNqyhnAyT5
Picks up `aceade9 "fix tests"` (and #1863 railway.json) so the
branch's `Run Tests` CI check goes green.
@chelojimenez chelojimenez deployed to preview-pr-1859 April 19, 2026 21:19 — with GitHub Actions Active
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working size:XS This PR changes 0-9 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants