Skip to content

feat(e2e): add E2E_STAGING flag for staging env auto-swap#8060

Open
jacekradko wants to merge 17 commits intomainfrom
jacek/staging-env-swap
Open

feat(e2e): add E2E_STAGING flag for staging env auto-swap#8060
jacekradko wants to merge 17 commits intomainfrom
jacek/staging-env-swap

Conversation

@jacekradko
Copy link
Member

@jacekradko jacekradko commented Mar 13, 2026

Summary

  • Adds withStagingSupport() wrapper in envs.ts that auto-swaps PK/SK to staging keys when E2E_STAGING=1 is set
  • Filters null env configs from long-running apps so missing staging keys gracefully skip tests
  • Adds :staging script variants and turbo tasks for all ~16 integration test suites
  • Expands e2e-staging workflow matrix with generic:staging

Adding a new staging instance requires only adding keys — no code changes needed.

How it works

withStagingSupport(envConfig, 'with-email-codes') checks for clerkstage-with-email-codes in instanceKeys. If found, swaps PK/SK and sets CLERK_API_URL=https://api.clerkstage.dev. If not found, returns null (config excluded from exports, long-running apps filtered out, tests run zero cases).

Test plan

  • Verify E2E_STAGING=1 swaps env configs correctly via inline script
  • Run generic:staging in CI via e2e-staging workflow dispatch
  • Confirm existing sessions:staging and handshake:staging still pass (no regression)
  • Verify non-staging tests are unaffected (E2E_STAGING unset → all configs present)

Summary by CodeRabbit

  • Chores
    • Added opt-in staging variants for integration tests across CI and local tooling, introduced staging instance key handling and a new staging keys artifact pattern, and wired staging keys into test/run environments.
  • Tests
    • Added Vitest configuration and a new test suite validating staging-aware selection, filtering, and error handling for long-running integration apps.

@vercel
Copy link

vercel bot commented Mar 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Mar 13, 2026 9:51pm

Request Review

@changeset-bot
Copy link

changeset-bot bot commented Mar 13, 2026

🦋 Changeset detected

Latest commit: ed9dc5f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 13, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds staging support across integration tests: CI workflow matrix includes generic:staging and passes INTEGRATION_STAGING_INSTANCE_KEYS; .gitignore adds .keys.staging.json; integration/constants.ts exports INTEGRATION_STAGING_INSTANCE_KEYS; integration/presets/envs.ts adds isStagingReady, withStagingSupport, staging URL/key constants, merges staging keys, and exposes staging-aware env presets; integration/presets/longRunningApps.ts is updated to filter by staging readiness and adjust pattern handling; package.json and turbo.json add many staging test variants; 1Password script handles optional .keys.staging.json; adds tests and a Vitest config for integration.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(e2e): add E2E_STAGING flag for staging env auto-swap' accurately and specifically describes the primary feature addition—introducing an E2E_STAGING flag that enables automatic environment variable swapping for staging tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

📝 Coding Plan
  • Generate coding plan for human review comments

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

Copy link
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: 3

🤖 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/e2e-staging.yml:
- Around line 89-90: The branch allowlist currently permits personal branches
via the regex check on REF (^(main|release/.*|jacek/.*)$); remove the
personal-branch entry by changing the regex to only allow main and release/*
(e.g. ^(main|release/.*)$) and update the error message that references allowed
refs so it matches the tightened allowlist.

In `@integration/presets/longRunningApps.ts`:
- Around line 22-23: The current logic around configs collapses invalid app
patterns and legitimately empty staging keys into the same empty-array return
when E2E_STAGING is set, hiding typos in E2E_APP_ID; change the flow so you
first build and keep an unfiltered configs list (the initial configs array) for
validation, then apply isStagingReady as a separate filter only for deciding
which configs to run, and return [] only when the requested pattern matches a
known app that was filtered out by isStagingReady; adjust the function that
currently returns [] (the block referencing E2E_STAGING/E2E_APP_ID around the
configs handling) to validate pattern existence against the unfiltered list and
only treat missing staging keys as a filtered-out case, and add a regression
test that distinguishes “missing staging key” from “invalid pattern” (i.e., test
both the stale/typo E2E_APP_ID case and the known-app-without-staging-keys case)
before merging.

In `@scripts/1password-keys.mjs`:
- Around line 62-67: The fallback branch that runs when stagingKeysItem is falsy
should remove any existing integration/.keys.staging.json so stale staging keys
aren't reused; update the else path that currently only logs to attempt to
delete the file (e.g., using fs.unlink or fs.rm wrapped in a try/catch or check
with fs.existsSync) for the target path produced by join(process.cwd(),
'integration', '.keys.staging.json'), and only suppress errors if the file
doesn't exist while still logging removal failures.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: fbce25c2-375f-4d13-88c2-75cbe289178a

📥 Commits

Reviewing files that changed from the base of the PR and between d32bf2c and 01337f9.

📒 Files selected for processing (8)
  • .github/workflows/e2e-staging.yml
  • .gitignore
  • integration/constants.ts
  • integration/presets/envs.ts
  • integration/presets/longRunningApps.ts
  • package.json
  • scripts/1password-keys.mjs
  • turbo.json

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 13, 2026

Open in StackBlitz

@clerk/agent-toolkit

npm i https://pkg.pr.new/@clerk/agent-toolkit@8060

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@8060

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@8060

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@8060

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@8060

@clerk/dev-cli

npm i https://pkg.pr.new/@clerk/dev-cli@8060

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@8060

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@8060

@clerk/express

npm i https://pkg.pr.new/@clerk/express@8060

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@8060

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@8060

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@8060

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@8060

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@8060

@clerk/react

npm i https://pkg.pr.new/@clerk/react@8060

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@8060

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@8060

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@8060

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@8060

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@8060

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@8060

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@8060

commit: ed9dc5f

jacekradko added a commit that referenced this pull request Mar 13, 2026
- Separate invalid pattern detection from staging-filtered apps in getByPattern
- Delete stale .keys.staging.json when 1Password staging keys are missing
- Add regression tests for getByPattern staging behavior
Copy link
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 `@integration/presets/longRunningApps.ts`:
- Around line 92-93: The filter call that builds stagingReadyConfigs calls
isStagingReady(c.env) without ensuring c.env exists, so guard the env before
calling it: change the predicate used on allConfigs (the arrow passed to filter
that calls isStagingReady) to first check c.env (or c.env != null) and only call
isStagingReady(c.env) when present; update the stagingReadyConfigs assignment
that currently uses allConfigs.filter(...) and ensure longRunningApplication
only receives configs with a valid env to prevent runtime crashes when
env.privateVariables is accessed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 30cb8655-4310-4ebe-aaaf-8d6e59a4a069

📥 Commits

Reviewing files that changed from the base of the PR and between 065da01 and 06fef2a.

📒 Files selected for processing (4)
  • integration/presets/__tests__/longRunningApps.test.ts
  • integration/presets/longRunningApps.ts
  • integration/vitest.config.mts
  • scripts/1password-keys.mjs

@jacekradko jacekradko changed the title feat(integration): add E2E_STAGING flag for staging env auto-swap feat(e2e): add E2E_STAGING flag for staging env auto-swap Mar 13, 2026
Copy link
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.

♻️ Duplicate comments (2)
integration/presets/longRunningApps.ts (1)

99-100: ⚠️ Potential issue | 🔴 Critical

Guard env before isStagingReady to avoid staging-mode runtime crashes.

At Line 99, isStagingReady(c.env) can receive a missing env config in staging mode, and isStagingReady dereferences env.privateVariables. This turns a “skip missing staging keys” case into a hard failure.

Suggested fix
-  const stagingReadyConfigs = allConfigs.filter(c => isStagingReady(c.env));
+  const stagingReadyConfigs = allConfigs.filter(c => c.env != null && isStagingReady(c.env));
   const apps = stagingReadyConfigs.map(longRunningApplication);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@integration/presets/longRunningApps.ts` around lines 99 - 100,
stagingReadyConfigs currently calls isStagingReady(c.env) without ensuring c.env
exists, which can cause crashes when env or env.privateVariables is missing;
update the filter to first guard that c.env (and/or c.env.privateVariables if
appropriate) is defined before calling isStagingReady, e.g. change the predicate
used when building stagingReadyConfigs (the usage of allConfigs.filter and
symbol isStagingReady) to check c.env presence, and ensure
longRunningApplication is only mapped over configs that passed that guard.
.github/workflows/e2e-staging.yml (1)

89-90: ⚠️ Potential issue | 🔴 Critical

Remove the personal-branch allowlist before merge.

Line 89 still permits jacek/* in a workflow that later injects INTEGRATION_*, certificate, Turbo, and Slack secrets. Git refs are not user-scoped, so any writer can create a matching branch and run unreviewed code with those secrets; tighten this back to main and release/*, and update Line 90 to match.

Suggested fix
-          if [[ ! "$REF" =~ ^(main|release/.*|jacek/.*)$ ]]; then
-            echo "::error::Ref '$REF' is not allowed. Only 'main', 'release/*', and 'jacek/*' branches are permitted."
+          if [[ ! "$REF" =~ ^(main|release/.*)$ ]]; then
+            echo "::error::Ref '$REF' is not allowed. Only 'main' and 'release/*' branches are permitted."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/e2e-staging.yml around lines 89 - 90, The workflow
currently allows branches matching jacek/* in the REF check; remove that pattern
from the conditional that evaluates REF (the if [[ ! "$REF" =~
^(main|release/.*|jacek/.*)$ ]] test) so it only permits main and release/*, and
update the accompanying echo message (the echo "::error::Ref '$REF' is not
allowed..." string) to reflect only 'main' and 'release/*' as allowed branches.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In @.github/workflows/e2e-staging.yml:
- Around line 89-90: The workflow currently allows branches matching jacek/* in
the REF check; remove that pattern from the conditional that evaluates REF (the
if [[ ! "$REF" =~ ^(main|release/.*|jacek/.*)$ ]] test) so it only permits main
and release/*, and update the accompanying echo message (the echo "::error::Ref
'$REF' is not allowed..." string) to reflect only 'main' and 'release/*' as
allowed branches.

In `@integration/presets/longRunningApps.ts`:
- Around line 99-100: stagingReadyConfigs currently calls isStagingReady(c.env)
without ensuring c.env exists, which can cause crashes when env or
env.privateVariables is missing; update the filter to first guard that c.env
(and/or c.env.privateVariables if appropriate) is defined before calling
isStagingReady, e.g. change the predicate used when building stagingReadyConfigs
(the usage of allConfigs.filter and symbol isStagingReady) to check c.env
presence, and ensure longRunningApplication is only mapped over configs that
passed that guard.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: e936aa13-0158-4d7a-84d5-e6146d1a0120

📥 Commits

Reviewing files that changed from the base of the PR and between bc11022 and c3c3943.

📒 Files selected for processing (3)
  • .github/workflows/e2e-staging.yml
  • integration/presets/longRunningApps.ts
  • package.json

When E2E_STAGING=1 is set, env configs transparently swap PK/SK to
staging keys and add CLERK_API_URL for clerkstage.dev. No new env
config objects, long-running app entries, or test file changes needed.

Adding a new staging instance only requires adding keys — the
withStagingSupport wrapper picks them up automatically.
Configs without staging keys are now marked with a private env var
instead of being null. This prevents crashes in test files that
directly access env configs (e.g. email-code.test.ts accesses
envs.withEmailCodes). Long-running apps filter by the marker.
The __STAGING_UNAVAILABLE__ env var marker was being written to the
app's .env file, causing side effects. Instead, use CLERK_API_URL
presence to determine staging readiness — configs with staging keys
have the staging API URL set, configs without don't.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants