Skip to content

Conversation

heatlikeheatwave
Copy link
Contributor

@heatlikeheatwave heatlikeheatwave commented Sep 24, 2025

Description

To help us debug why keyless applications are failing to make certain API requests, this PR forwards a new header, clerk-is-ci) with requests to accountless_applications.
Adds a new function, detectCIEnvironment(), that checks for 25+ common CI environment variables (GitHub Actions, GitLab CI, CircleCI, Jenkins, Vercel, Netlify, etc.)

Linear task

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Summary by CodeRabbit

  • New Features

    • Adds CI environment detection and includes a CI indicator header on requests during Next.js keyless app creation.
  • Behavior Changes

    • Requests will include a CI header when running in CI; existing flows remain compatible and require no action.
  • Tests

    • Updated and added tests to cover CI detection and header behavior across environments.
  • Chores

    • Published a patch release announcing the CI detection capability.

Copy link

changeset-bot bot commented Sep 24, 2025

🦋 Changeset detected

Latest commit: 7b1060b

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

This PR includes changesets to release 1 package
Name Type
@clerk/nextjs Patch

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

Copy link

vercel bot commented Sep 24, 2025

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

Project Deployment Preview Comments Updated (UTC)
clerk-js-sandbox Ready Ready Preview Comment Sep 25, 2025 7:39pm

Copy link
Contributor

coderabbitai bot commented Sep 24, 2025

Walkthrough

Adds CI environment detection to Next.js keyless metadata: introduces CI_ENV_VARS and detectCIEnvironment() in keyless-custom-headers.ts, extends MetadataHeaders with isCI, sets isCI in collectKeylessMetadata(), and conditionally emits a Clerk-Is-CI: 'true' header in formatMetadataHeaders(). Tests and a patch changeset were added.

Changes

Cohort / File(s) Summary
Next.js keyless headers
packages/nextjs/src/server/keyless-custom-headers.ts
Add CI_ENV_VARS: string[]; add detectCIEnvironment(); extend MetadataHeaders with isCI: boolean; set isCI in collectKeylessMetadata(); have formatMetadataHeaders() include Clerk-Is-CI: 'true' when isCI is true.
Tests updated
packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
Add CI_ENV_VARS constant and clearAllCIEnvironmentVariables helper; stub CI-related env vars and other envs in setup/teardown; update tests to include isCI: false in metadata/expected objects and adjust env handling.
Release note (changeset)
.changeset/wild-shoes-divide.md
Add patch changeset: "feat(nextjs): Add CI environment detection header for Next.js keyless app creation".

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant App as Next.js App
  participant Env as Process Env
  participant Module as keyless-custom-headers.ts
  participant API as Clerk Backend

  App->>Module: collectKeylessMetadata()
  Module->>Env: read CI env vars (CI_ENV_VARS)
  Env-->>Module: boolean isCI
  Module-->>App: MetadataHeaders { ..., isCI }

  App->>Module: formatMetadataHeaders(metadata)
  alt metadata.isCI == true
    Module-->>App: Headers (incl. "Clerk-Is-CI: true")
  else metadata.isCI == false
    Module-->>App: Headers (no Clerk-Is-CI)
  end

  App->>API: POST accountless_applications with Headers
  API-->>App: Response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

I nibble logs where builders roam,
I sniff the env and find a home.
A tiny header takes a leap,
"Clerk-Is-CI" — a secret we keep.
Hops, tests, and patch notes — soft and sweet. 🥕

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title concisely and specifically summarizes the primary change by indicating that a CI environment detection header is being added for Next.js keyless app creation, and it matches the scope of the implemented changes in the PR.
Linked Issues Check ✅ Passed The PR implements CI environment detection by checking a comprehensive set of environment variables including Vercel’s CI, assigns the isCI flag in metadata, and forwards it as the clerk-is-ci header on accountless application requests, fully satisfying the objectives of GROW-777.
Out of Scope Changes Check ✅ Passed All modifications—including the new CI detection logic, header formatting, changeset file, and corresponding test updates—are directly related to adding CI environment detection and do not introduce any unrelated or extraneous functionality.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch heat/grow-777-detect-ci-environment

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

Copy link

pkg-pr-new bot commented Sep 24, 2025

Open in StackBlitz

@clerk/agent-toolkit

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

@clerk/astro

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

@clerk/backend

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

@clerk/chrome-extension

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

@clerk/clerk-js

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

@clerk/dev-cli

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

@clerk/elements

npm i https://pkg.pr.new/@clerk/elements@6852

@clerk/clerk-expo

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

@clerk/expo-passkeys

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

@clerk/express

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

@clerk/fastify

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

@clerk/localizations

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

@clerk/nextjs

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

@clerk/nuxt

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

@clerk/clerk-react

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

@clerk/react-router

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

@clerk/remix

npm i https://pkg.pr.new/@clerk/remix@6852

@clerk/shared

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

@clerk/tanstack-react-start

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

@clerk/testing

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

@clerk/themes

npm i https://pkg.pr.new/@clerk/themes@6852

@clerk/types

npm i https://pkg.pr.new/@clerk/types@6852

@clerk/upgrade

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

@clerk/vue

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

commit: 7b1060b

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

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a39f2fc and b99277d.

📒 Files selected for processing (1)
  • packages/nextjs/src/server/keyless-custom-headers.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

TypeScript is required for all packages

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
packages/**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Packages should export TypeScript types alongside runtime code

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use proper TypeScript error types

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: semgrep/ci
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: Analyze (javascript-typescript)

Copy link
Member

@tmilewski tmilewski left a comment

Choose a reason for hiding this comment

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

🚢

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: 2

🧹 Nitpick comments (2)
packages/nextjs/src/__tests__/keyless-custom-headers.test.ts (2)

477-506: Consider extracting duplicated metadata scaffolding

metadataWithCI and metadataWithoutCI only differ by isCI. Extracting a helper (e.g. createMinimalMetadata({ isCI })) keeps future changes to the common fields in one place and trims noise in the assertions.


566-621: Prefer table-driven tests for CI detection scenarios

The two CI detection tests above already loop through value/provider matrices. You can collapse this final integration check into a parameterized test that reuses that data, further reducing duplication while keeping coverage intact.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 62c4697 and d9be68e.

📒 Files selected for processing (1)
  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts (11 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

TypeScript is required for all packages

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
packages/**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Packages should export TypeScript types alongside runtime code

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use proper TypeScript error types

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
packages/**/*.{test,spec}.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Unit tests should use Jest or Vitest as the test runner.

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

**/__tests__/**/*.{ts,tsx}: Create type-safe test builders/factories
Use branded types for test isolation
Implement proper mock types that match interfaces

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
🧬 Code graph analysis (1)
packages/nextjs/src/__tests__/keyless-custom-headers.test.ts (1)
packages/nextjs/src/server/keyless-custom-headers.ts (2)
  • collectKeylessMetadata (22-38)
  • formatMetadataHeaders (100-148)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: semgrep/ci
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan

@heatlikeheatwave heatlikeheatwave force-pushed the heat/grow-777-detect-ci-environment branch from d9be68e to 99e142b Compare September 25, 2025 15:17
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: 2

🧹 Nitpick comments (1)
packages/nextjs/src/__tests__/keyless-custom-headers.test.ts (1)

579-638: Minor: isolate CI state explicitly for clarity

This test will pass regardless due to CI=1, but adding clearAllCIEnvironmentVariables() at the start improves isolation and intent.

Apply this small tweak:

   it('should format metadata with CI environment detected correctly', async () => {
-    // Reset mock to ensure clean state from previous test
+    // Reset mock to ensure clean state from previous test
     mockHeaders.mockReset();
+    clearAllCIEnvironmentVariables();
 
     // Setup environment with CI detection
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 99e142b and 4120c21.

📒 Files selected for processing (2)
  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts (14 hunks)
  • packages/nextjs/src/server/keyless-custom-headers.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/nextjs/src/server/keyless-custom-headers.ts
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

TypeScript is required for all packages

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
packages/**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Packages should export TypeScript types alongside runtime code

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use proper TypeScript error types

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
packages/**/*.{test,spec}.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Unit tests should use Jest or Vitest as the test runner.

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

**/__tests__/**/*.{ts,tsx}: Create type-safe test builders/factories
Use branded types for test isolation
Implement proper mock types that match interfaces

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
🧬 Code graph analysis (1)
packages/nextjs/src/__tests__/keyless-custom-headers.test.ts (1)
packages/nextjs/src/server/keyless-custom-headers.ts (3)
  • CI_ENV_VARS (41-67)
  • collectKeylessMetadata (22-38)
  • formatMetadataHeaders (102-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: semgrep/ci
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (11)
packages/nextjs/src/__tests__/keyless-custom-headers.test.ts (11)

5-5: Importing CI_ENV_VARS keeps tests in sync with implementation

Good call importing the allowlist from the source to avoid drift.


67-73: Centralized CI env clearing helper

Solid helper; this reduces flakiness across tests and reflects the actual allowlist.


144-161: Verifies Clerk-Is-CI emission

Asserting exact casing and value for the CI header looks good.


163-191: Asserts absence of Clerk-Is-CI when isCI=false

Correct expectation; header is not set.


193-224: Undefined optional fields and isCI=false behavior

Covers the “undefined” path and ensures the CI header is omitted.


226-255: Empty string behavior is correct

Empty strings are treated as absent; CI header omitted as expected.


291-294: Pre-test CI cleanup

Good use of clearAllCIEnvironmentVariables() to ensure a clean slate.


342-356: Explicitly expecting isCI=false in full metadata path

Expectation matches the cleared CI state.


478-486: No-indicator path covered

Good: uses the centralized helper to guarantee no CI signals are present.


487-516: Header emission toggling

Clear, focused test ensures Clerk-Is-CI is only present when intended.


520-577: End-to-end formatting without CI

Great integration-style coverage; includes CI cleanup to prevent leakage.

@heatlikeheatwave heatlikeheatwave force-pushed the heat/grow-777-detect-ci-environment branch from 4120c21 to da348e4 Compare September 25, 2025 15:44
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

🧹 Nitpick comments (3)
packages/nextjs/src/__tests__/keyless-custom-headers.test.ts (1)

464-484: Broaden falsy-value coverage in CI detection tests

Add 'no', 'off', and case/whitespace permutations to validate normalization.

Apply this diff to expand the falsy set:

-      const falsyValues = ['0', 'false', ''];
+      const falsyValues = ['0', 'false', '', 'no', 'off', 'False', 'OFF', ' No ', ' Off '];
packages/nextjs/src/server/keyless-custom-headers.ts (2)

40-67: Make CI_ENV_VARS readonly and expand provider coverage

  • Mark the list as readonly with as const.
  • Consider adding other common indicators (Render, Cloudflare Pages, AWS CodeBuild, Screwdriver, generic CI_* markers) to improve detection.

Apply this diff to the list and make it readonly:

-export const CI_ENV_VARS = [
+export const CI_ENV_VARS = [
   'CI',
   'CONTINUOUS_INTEGRATION',
   'BUILD_NUMBER',
   'BUILD_ID',
   'BUILDKITE',
   'CIRCLECI',
   'GITHUB_ACTIONS',
   'GITLAB_CI',
   'JENKINS_URL',
   'TRAVIS',
   'APPVEYOR',
   'WERCKER',
   'DRONE',
   'CODESHIP',
   'SEMAPHORE',
   'SHIPPABLE',
   'TEAMCITY_VERSION',
   'BAMBOO_BUILDKEY',
   'GO_PIPELINE_NAME',
   'TF_BUILD',
   'SYSTEM_TEAMFOUNDATIONCOLLECTIONURI',
   'BITBUCKET_BUILD_NUMBER',
   'HEROKU_TEST_RUN_ID',
   'VERCEL',
   'NETLIFY',
-];
+  // Additional common indicators
+  'RENDER',
+  'CF_PAGES',
+  'SCREWDRIVER',
+  'CODEBUILD_BUILD_ARN',
+  'CODEBUILD_BUILD_ID',
+  'CI_NAME',
+  'CI_SERVER',
+  'CI_VENDOR',
+] as const;

Also export the narrow string union type for ergonomic use downstream:

export type CIEnvVar = (typeof CI_ENV_VARS)[number];

69-86: Hoist falsy set and include additional false-like values ('off', 'disabled')

Avoid re-allocating Set on every call and handle more negations.

Apply this diff:

-function detectCIEnvironment(): boolean {
-  const ciIndicators = CI_ENV_VARS;
-
-  const falsyValues = new Set<string>(['', 'false', '0', 'no']);
-
-  return ciIndicators.some(indicator => {
-    const value = process.env[indicator];
-    if (value === undefined) {
-      return false;
-    }
-
-    const normalizedValue = value.trim().toLowerCase();
-    return !falsyValues.has(normalizedValue);
-  });
-}
+const FALSY_CI_VALUES = new Set<string>(['', 'false', '0', 'no', 'off', 'disabled']);
+
+function detectCIEnvironment(): boolean {
+  return CI_ENV_VARS.some(indicator => {
+    const value = process.env[indicator];
+    if (value == null) {
+      return false;
+    }
+    const normalized = value.trim().toLowerCase();
+    return !FALSY_CI_VALUES.has(normalized);
+  });
+}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4120c21 and da348e4.

📒 Files selected for processing (2)
  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts (14 hunks)
  • packages/nextjs/src/server/keyless-custom-headers.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

TypeScript is required for all packages

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
packages/**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Packages should export TypeScript types alongside runtime code

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use proper TypeScript error types

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
packages/**/*.{test,spec}.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Unit tests should use Jest or Vitest as the test runner.

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

**/__tests__/**/*.{ts,tsx}: Create type-safe test builders/factories
Use branded types for test isolation
Implement proper mock types that match interfaces

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
🧬 Code graph analysis (1)
packages/nextjs/src/__tests__/keyless-custom-headers.test.ts (1)
packages/nextjs/src/server/keyless-custom-headers.ts (3)
  • CI_ENV_VARS (41-67)
  • collectKeylessMetadata (22-38)
  • formatMetadataHeaders (102-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: semgrep/ci
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (10)
packages/nextjs/src/__tests__/keyless-custom-headers.test.ts (9)

5-5: Good call: import CI_ENV_VARS to avoid drift with implementation

Keeps tests aligned with the production allowlist.


67-73: Helper to clear CI envs looks good

Iterating CI_ENV_VARS and stubbing to undefined prevents runner leakage when combined with vi.unstubAllEnvs() in tests.


144-161: Header behavior assertions are correct

Clerk-Is-CI is only set when isCI is true; omitted otherwise. This matches formatMetadataHeaders.

Also applies to: 171-191, 205-224, 238-255


292-294: Nice: clear CI envs before the “all fields present” metadata test

Prevents flakiness from the runner and keeps isCI deterministic.


442-462: Fix for previously noted flakiness looks solid

Per‑iteration env clearing and fresh header mocks address the stale state concerns raised earlier.


486-493: LGTM: baseline non-CI scenario

Using clearAllCIEnvironmentVariables() ensures no indicators slip through.


495-524: LGTM: header emitted only when isCI is true

Asserts both presence and absence cases clearly.


528-585: End-to-end without CI: good coverage

Pipeline validates collection and formatting, and confirms Clerk-Is-CI is omitted.


587-646: Good isolation between sequential integration tests

Resetting mockHeaders avoids leaked state from the previous test.

packages/nextjs/src/server/keyless-custom-headers.ts (1)

145-147: Header emission only when true is correct

Only sets Clerk-Is-CI when metadata.isCI is true, as discussed in review.

@heatlikeheatwave heatlikeheatwave force-pushed the heat/grow-777-detect-ci-environment branch from da348e4 to 43b46d7 Compare September 25, 2025 16:00
@heatlikeheatwave heatlikeheatwave force-pushed the heat/grow-777-detect-ci-environment branch from 43b46d7 to 6e87cb9 Compare September 25, 2025 16:36
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: 0

🧹 Nitpick comments (3)
packages/nextjs/src/server/keyless-custom-headers.ts (3)

5-17: Document the new public API surface (MetadataHeaders and isCI).

Add JSDoc for the exported interface and the new field to meet the project's “All public APIs must be documented” guideline.

-export interface MetadataHeaders {
+/**
+ * Keyless metadata forwarded as HTTP headers to Clerk.
+ * @public
+ */
+export interface MetadataHeaders {
@@
-  isCI: boolean;
+  /**
+   * True when running in a CI/build/test environment. Controls the `Clerk-Is-CI` header emission.
+   */
+  isCI: boolean;

40-67: Make CI_ENV_VARS readonly and document it.

Prevent unintended mutation and improve type safety by using a const assertion, and add brief docs since this is exported.

-// Common CI environment variables
-export const CI_ENV_VARS = [
+// Common CI environment variables used to detect CI environments.
+// Exported for transparency and testing.
+export const CI_ENV_VARS = [
@@
-  'NETLIFY',
-];
+  'NETLIFY',
+] as const;

69-86: Optional: rely on ci-info to avoid maintaining provider lists.

Consider using the well‑maintained ci-info package (isCI flag) to reduce maintenance and edge cases; keep your list as a fallback if adding a dep is undesirable.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 43b46d7 and 6e87cb9.

📒 Files selected for processing (1)
  • packages/nextjs/src/server/keyless-custom-headers.ts (4 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

TypeScript is required for all packages

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
packages/**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Packages should export TypeScript types alongside runtime code

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use proper TypeScript error types

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
🧬 Code graph analysis (1)
packages/nextjs/src/server/keyless-custom-headers.ts (1)
scripts/notify.mjs (1)
  • process (6-6)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (26)
  • GitHub Check: Integration Tests (custom, chrome)
  • GitHub Check: Integration Tests (localhost, chrome)
  • GitHub Check: Integration Tests (machine, chrome)
  • GitHub Check: Integration Tests (vue, chrome)
  • GitHub Check: Integration Tests (billing, chrome)
  • GitHub Check: Integration Tests (react-router, chrome)
  • GitHub Check: Integration Tests (nuxt, chrome)
  • GitHub Check: Integration Tests (sessions, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 15)
  • GitHub Check: Integration Tests (nextjs, chrome, 14)
  • GitHub Check: Integration Tests (tanstack-react-start, chrome)
  • GitHub Check: Integration Tests (quickstart, chrome)
  • GitHub Check: Integration Tests (astro, chrome)
  • GitHub Check: Integration Tests (tanstack-react-router, chrome)
  • GitHub Check: Integration Tests (elements, chrome)
  • GitHub Check: Integration Tests (ap-flows, chrome)
  • GitHub Check: Integration Tests (expo-web, chrome)
  • GitHub Check: Integration Tests (express, chrome)
  • GitHub Check: Integration Tests (generic, chrome)
  • GitHub Check: Publish with pkg-pr-new
  • GitHub Check: Unit Tests (22, **)
  • GitHub Check: Unit Tests (18, --filter=@clerk/astro --filter=@clerk/backend --filter=@clerk/express --filter=@c...
  • GitHub Check: Static analysis
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (3)
packages/nextjs/src/server/keyless-custom-headers.ts (3)

36-37: LGTM: isCI is correctly included in collected metadata.


69-86: Treat 'off' as falsy too (minor correctness).

Some CI toggles use 'off'; currently it’s treated as truthy. Include it in the falsy set.

-  const falsyValues = new Set<string>(['', 'false', '0', 'no']);
+  const falsyValues = new Set<string>(['', 'false', '0', 'no', 'off']);

145-147: Approved: Clerk-Is-CI header is correctly forwarded to the accountless applications API.

@heatlikeheatwave heatlikeheatwave force-pushed the heat/grow-777-detect-ci-environment branch from 6e87cb9 to 1adb4fd Compare September 25, 2025 18:45
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

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6e87cb9 and 1adb4fd.

📒 Files selected for processing (1)
  • packages/nextjs/src/server/keyless-custom-headers.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

TypeScript is required for all packages

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
packages/**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Packages should export TypeScript types alongside runtime code

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use proper TypeScript error types

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (28)
  • GitHub Check: Integration Tests (localhost, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 15)
  • GitHub Check: Integration Tests (custom, chrome)
  • GitHub Check: Integration Tests (machine, chrome)
  • GitHub Check: Integration Tests (react-router, chrome)
  • GitHub Check: Integration Tests (express, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 14)
  • GitHub Check: Integration Tests (billing, chrome)
  • GitHub Check: Integration Tests (nuxt, chrome)
  • GitHub Check: Integration Tests (vue, chrome)
  • GitHub Check: Integration Tests (tanstack-react-router, chrome)
  • GitHub Check: Integration Tests (astro, chrome)
  • GitHub Check: Integration Tests (sessions, chrome)
  • GitHub Check: Integration Tests (tanstack-react-start, chrome)
  • GitHub Check: Integration Tests (expo-web, chrome)
  • GitHub Check: Integration Tests (generic, chrome)
  • GitHub Check: Integration Tests (elements, chrome)
  • GitHub Check: Integration Tests (quickstart, chrome)
  • GitHub Check: Integration Tests (ap-flows, chrome)
  • GitHub Check: Publish with pkg-pr-new
  • GitHub Check: Unit Tests (22, **)
  • GitHub Check: Unit Tests (18, --filter=@clerk/astro --filter=@clerk/backend --filter=@clerk/express --filter=@c...
  • GitHub Check: Static analysis
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: semgrep/ci
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan

@heatlikeheatwave heatlikeheatwave force-pushed the heat/grow-777-detect-ci-environment branch from 1adb4fd to ea7298a Compare September 25, 2025 18:58
@heatlikeheatwave heatlikeheatwave force-pushed the heat/grow-777-detect-ci-environment branch from ea7298a to 3830563 Compare September 25, 2025 19:27
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: 0

🧹 Nitpick comments (1)
packages/nextjs/src/server/keyless-custom-headers.ts (1)

40-67: Make CI_ENV_VARS readonly and document it

Prevent accidental mutation and aid type inference with as const; add a short JSDoc since this is exported.

As per coding guidelines

-// Common CI environment variables
-export const CI_ENV_VARS = [
+// Common CI environment variables
+export const CI_ENV_VARS = [
   'CI',
   'CONTINUOUS_INTEGRATION',
   'BUILD_NUMBER',
   'BUILD_ID',
   'BUILDKITE',
   'CIRCLECI',
   'GITHUB_ACTIONS',
   'GITLAB_CI',
   'JENKINS_URL',
   'TRAVIS',
   'APPVEYOR',
   'WERCKER',
   'DRONE',
   'CODESHIP',
   'SEMAPHORE',
   'SHIPPABLE',
   'TEAMCITY_VERSION',
   'BAMBOO_BUILDKEY',
   'GO_PIPELINE_NAME',
   'TF_BUILD',
   'SYSTEM_TEAMFOUNDATIONCOLLECTIONURI',
   'BITBUCKET_BUILD_NUMBER',
   'HEROKU_TEST_RUN_ID',
   'VERCEL',
   'NETLIFY',
-];
+ ] as const;
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ea7298a and 3830563.

📒 Files selected for processing (2)
  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts (7 hunks)
  • packages/nextjs/src/server/keyless-custom-headers.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/nextjs/src/tests/keyless-custom-headers.test.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

TypeScript is required for all packages

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
packages/**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Packages should export TypeScript types alongside runtime code

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use proper TypeScript error types

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/nextjs/src/server/keyless-custom-headers.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (27)
  • GitHub Check: Integration Tests (nextjs, chrome, 14)
  • GitHub Check: Integration Tests (nextjs, chrome, 15)
  • GitHub Check: Integration Tests (machine, chrome)
  • GitHub Check: Integration Tests (custom, chrome)
  • GitHub Check: Integration Tests (vue, chrome)
  • GitHub Check: Integration Tests (billing, chrome)
  • GitHub Check: Integration Tests (react-router, chrome)
  • GitHub Check: Integration Tests (tanstack-react-start, chrome)
  • GitHub Check: Integration Tests (nuxt, chrome)
  • GitHub Check: Integration Tests (expo-web, chrome)
  • GitHub Check: Integration Tests (tanstack-react-router, chrome)
  • GitHub Check: Integration Tests (sessions, chrome)
  • GitHub Check: Integration Tests (astro, chrome)
  • GitHub Check: Integration Tests (localhost, chrome)
  • GitHub Check: Integration Tests (quickstart, chrome)
  • GitHub Check: Integration Tests (elements, chrome)
  • GitHub Check: Integration Tests (generic, chrome)
  • GitHub Check: Integration Tests (express, chrome)
  • GitHub Check: Integration Tests (ap-flows, chrome)
  • GitHub Check: Unit Tests (18, --filter=@clerk/astro --filter=@clerk/backend --filter=@clerk/express --filter=@c...
  • GitHub Check: Publish with pkg-pr-new
  • GitHub Check: Unit Tests (22, **)
  • GitHub Check: Static analysis
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (4)
packages/nextjs/src/server/keyless-custom-headers.ts (4)

5-17: Export MetadataHeaders (public API) and add JSDoc

This type is part of the exported surface via collectKeylessMetadata(). Export it so downstreams can reference it; also add brief JSDoc.

As per coding guidelines

-interface MetadataHeaders {
+/**
+ * Public type describing metadata forwarded to Clerk for diagnostics/debugging.
+ */
+export interface MetadataHeaders {
   nodeVersion?: string;
   nextVersion?: string;
   npmConfigUserAgent?: string;
   userAgent: string;
   port?: string;
   host: string;
   xHost: string;
   xPort: string;
   xProtocol: string;
   xClerkAuthStatus: string;
   isCI: boolean;
 }
#!/bin/bash
# Verify if consumers expect to import MetadataHeaders (will fail if not exported).
rg -nP -C2 '\bMetadataHeaders\b'

36-37: LGTM: isCI is correctly plumbed into metadata


145-147: LGTM: Header added only when the signal is true

Matches the behavior agreed in the review thread and aligns with other Clerk headers.

Please confirm tests assert that the header is omitted when isCI is false and present when true.


72-86: Treat 'off' as falsy to avoid misreporting CI

Values like CI=OFF or VERCEL=off are currently treated as true. Include 'off' in the falsy set.

-  const falsyValues = new Set<string>(['', 'false', '0', 'no']);
+  const falsyValues = new Set<string>(['', 'false', '0', 'no', 'off']);

Optional: hoist the set to module scope to avoid re-allocations.

// outside the function
const CI_FALSY_VALUES = new Set(['', 'false', '0', 'no', 'off']);

// inside detectCIEnvironment()
const normalizedValue = value.trim().toLowerCase();
return !CI_FALSY_VALUES.has(normalizedValue);
#!/bin/bash
# Ensure test coverage for the OFF case exists or add one.
rg -nP -C2 "Clerk-Is-CI|isCI|detectCIEnvironment|CI_ENV_VARS|CI=OFF|VERCEL=off|NETLIFY=off" --type=ts --type=tsx --type=js --type=jsx

@heatlikeheatwave heatlikeheatwave force-pushed the heat/grow-777-detect-ci-environment branch from 3830563 to 321c9b7 Compare September 25, 2025 19:37
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: 0

🧹 Nitpick comments (1)
packages/nextjs/src/__tests__/keyless-custom-headers.test.ts (1)

1-39: Import the CI allowlist from the source

We now define the CI variable allowlist twice (here and in keyless-custom-headers.ts). That duplication will drift the moment we tweak the source list, reintroducing the flakes we just cleaned up. Export the array from the implementation module and import it here so the tests always exercise the real allowlist.

-import { collectKeylessMetadata, formatMetadataHeaders } from '../server/keyless-custom-headers';
-
-const CI_ENV_VARS = [
-  'CI',
-  'CONTINUOUS_INTEGRATION',
-  'BUILD_NUMBER',
-  'BUILD_ID',
-  'BUILDKITE',
-  'CIRCLECI',
-  'GITHUB_ACTIONS',
-  'GITLAB_CI',
-  'JENKINS_URL',
-  'TRAVIS',
-  'APPVEYOR',
-  'WERCKER',
-  'DRONE',
-  'CODESHIP',
-  'SEMAPHORE',
-  'SHIPPABLE',
-  'TEAMCITY_VERSION',
-  'BAMBOO_BUILDKEY',
-  'GO_PIPELINE_NAME',
-  'TF_BUILD',
-  'SYSTEM_TEAMFOUNDATIONCOLLECTIONURI',
-  'BITBUCKET_BUILD_NUMBER',
-  'HEROKU_TEST_RUN_ID',
-  'VERCEL',
-  'NETLIFY',
-];
+import { CI_ENV_VARS, collectKeylessMetadata, formatMetadataHeaders } from '../server/keyless-custom-headers';
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3830563 and 7b1060b.

📒 Files selected for processing (3)
  • .changeset/wild-shoes-divide.md (1 hunks)
  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts (7 hunks)
  • packages/nextjs/src/server/keyless-custom-headers.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .changeset/wild-shoes-divide.md
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
  • packages/nextjs/src/server/keyless-custom-headers.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
  • packages/nextjs/src/server/keyless-custom-headers.ts
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

TypeScript is required for all packages

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
  • packages/nextjs/src/server/keyless-custom-headers.ts
packages/**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Packages should export TypeScript types alongside runtime code

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
  • packages/nextjs/src/server/keyless-custom-headers.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use proper TypeScript error types

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
  • packages/nextjs/src/server/keyless-custom-headers.ts
packages/**/*.{test,spec}.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Unit tests should use Jest or Vitest as the test runner.

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
  • packages/nextjs/src/server/keyless-custom-headers.ts
**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

**/__tests__/**/*.{ts,tsx}: Create type-safe test builders/factories
Use branded types for test isolation
Implement proper mock types that match interfaces

Files:

  • packages/nextjs/src/__tests__/keyless-custom-headers.test.ts
🧬 Code graph analysis (1)
packages/nextjs/src/server/keyless-custom-headers.ts (1)
scripts/notify.mjs (1)
  • process (6-6)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (24)
  • GitHub Check: Integration Tests (machine, chrome)
  • GitHub Check: Integration Tests (billing, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 14)
  • GitHub Check: Integration Tests (nextjs, chrome, 15)
  • GitHub Check: Integration Tests (nuxt, chrome)
  • GitHub Check: Integration Tests (react-router, chrome)
  • GitHub Check: Integration Tests (vue, chrome)
  • GitHub Check: Integration Tests (express, chrome)
  • GitHub Check: Integration Tests (tanstack-react-router, chrome)
  • GitHub Check: Integration Tests (tanstack-react-start, chrome)
  • GitHub Check: Integration Tests (custom, chrome)
  • GitHub Check: Integration Tests (expo-web, chrome)
  • GitHub Check: Integration Tests (quickstart, chrome)
  • GitHub Check: Integration Tests (elements, chrome)
  • GitHub Check: Integration Tests (localhost, chrome)
  • GitHub Check: Integration Tests (ap-flows, chrome)
  • GitHub Check: Integration Tests (sessions, chrome)
  • GitHub Check: Integration Tests (astro, chrome)
  • GitHub Check: Integration Tests (generic, chrome)
  • GitHub Check: Unit Tests (22, **)
  • GitHub Check: Publish with pkg-pr-new
  • GitHub Check: Unit Tests (18, --filter=@clerk/astro --filter=@clerk/backend --filter=@clerk/express --filter=@c...
  • GitHub Check: Static analysis
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (1)
packages/nextjs/src/server/keyless-custom-headers.ts (1)

75-85: Treat 'off' values as CI false

We regress on the earlier fix: CI=OFF (or any * = off) now reports as CI because 'off' isn’t in the falsy set. That will emit the Clerk-Is-CI header in environments explicitly opting out, undermining the signal we’re adding. Please bring 'off' back into the falsy allowlist (and update the tests accordingly).

-  const falsyValues = new Set<string>(['', 'false', '0', 'no']);
+  const falsyValues = new Set<string>(['', 'false', '0', 'no', 'off']);

@heatlikeheatwave heatlikeheatwave merged commit cf2f284 into main Sep 25, 2025
40 checks passed
@heatlikeheatwave heatlikeheatwave deleted the heat/grow-777-detect-ci-environment branch September 25, 2025 19:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants