diff --git a/.env.example b/.env.example index e6e4d9cad..d251db87e 100644 --- a/.env.example +++ b/.env.example @@ -60,9 +60,8 @@ NEXT_PUBLIC_E2B_DOMAIN=e2b.dev # PLAIN_API_KEY= ### LaunchDarkly feature flags -### Use the SDK key for the LaunchDarkly environment selected below. +### Use the SDK key for the desired LaunchDarkly environment. # LAUNCHDARKLY_SDK_KEY= -# FEATURE_FLAG_ENVIRONMENT=staging ### OTEL Configuration # OTEL_SERVICE_NAME= diff --git a/README.md b/README.md index 701471d69..043a5fff6 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ Feature flags are evaluated server-side with LaunchDarkly via OpenFeature and hy 3. Use `featureFlags.isEnabled(...)` on the server or `useFeatureFlag(...)` inside dashboard client components. 4. Target users or teams in LaunchDarkly using the `user` and `team` contexts. -Set `LAUNCHDARKLY_SDK_KEY` and `FEATURE_FLAG_ENVIRONMENT=staging|production` for environments that should use LaunchDarkly. +Set `LAUNCHDARKLY_SDK_KEY` for environments that should use LaunchDarkly. The SDK key determines the LaunchDarkly environment. ## Production Deployment diff --git a/scripts/check-app-env.ts b/scripts/check-app-env.ts index 53cce9453..2f977369f 100644 --- a/scripts/check-app-env.ts +++ b/scripts/check-app-env.ts @@ -34,19 +34,5 @@ const schema = appEnvSchema path: ['PLAIN_API_KEY'], } ) - .refine( - (data) => { - if (data.LAUNCHDARKLY_SDK_KEY) { - return !!data.FEATURE_FLAG_ENVIRONMENT - } - - return true - }, - { - message: - 'LAUNCHDARKLY_SDK_KEY is set, but FEATURE_FLAG_ENVIRONMENT is missing', - path: ['FEATURE_FLAG_ENVIRONMENT'], - } - ) validateEnv(schema) diff --git a/src/core/modules/feature-flags/context.ts b/src/core/modules/feature-flags/context.ts index e7329d806..8881bb6dc 100644 --- a/src/core/modules/feature-flags/context.ts +++ b/src/core/modules/feature-flags/context.ts @@ -8,20 +8,4 @@ export type FeatureFlagContext = { slug?: string name?: string } - environment?: 'production' | 'staging' -} - -export function getFeatureFlagEnvironment(): FeatureFlagContext['environment'] { - switch (process.env.FEATURE_FLAG_ENVIRONMENT) { - case 'production': - case 'staging': - return process.env.FEATURE_FLAG_ENVIRONMENT - } - - switch (process.env.VERCEL_ENV) { - case 'production': - return 'production' - default: - return 'staging' - } } diff --git a/src/core/modules/feature-flags/launchdarkly-openfeature-provider.server.ts b/src/core/modules/feature-flags/launchdarkly-openfeature-provider.server.ts index 2387cfa25..57d40d648 100644 --- a/src/core/modules/feature-flags/launchdarkly-openfeature-provider.server.ts +++ b/src/core/modules/feature-flags/launchdarkly-openfeature-provider.server.ts @@ -5,10 +5,7 @@ import type { EvaluationDetails, JsonValue, } from '@openfeature/server-sdk' -import { - type FeatureFlagContext, - getFeatureFlagEnvironment, -} from '@/core/modules/feature-flags/context' +import type { FeatureFlagContext } from '@/core/modules/feature-flags/context' import type { FeatureFlagDefinition } from '@/core/modules/feature-flags/types' import { l, serializeErrorForLog } from '@/core/shared/clients/logger/logger' import { getOpenFeatureServerClient } from './openfeature-client.server' @@ -32,12 +29,10 @@ function definedStringAttributes( export function createOpenFeatureEvaluationContext( context: FeatureFlagContext ): EvaluationContext { - const environment = context.environment ?? getFeatureFlagEnvironment() const user = { targetingKey: context.user.id, ...definedStringAttributes({ email: context.user.email, - environment, }), } @@ -56,7 +51,6 @@ export function createOpenFeatureEvaluationContext( ...definedStringAttributes({ name: context.team.name, slug: context.team.slug, - environment, }), }, } diff --git a/src/lib/env.ts b/src/lib/env.ts index 963c0da3a..a9344787a 100644 --- a/src/lib/env.ts +++ b/src/lib/env.ts @@ -11,7 +11,6 @@ export const serverSchema = z.object({ POSTHOG_PROJECT_ID: z.string().min(1).optional(), LAUNCHDARKLY_SDK_KEY: z.string().min(1).optional(), - FEATURE_FLAG_ENVIRONMENT: z.enum(['production', 'staging']).optional(), AUTH_SECRET: z.string().min(1).optional(), AUTH_TRUST_HOST: z.string().optional(), diff --git a/tests/unit/feature-flags.test.ts b/tests/unit/feature-flags.test.ts index 5b3012325..160f7595f 100644 --- a/tests/unit/feature-flags.test.ts +++ b/tests/unit/feature-flags.test.ts @@ -1,8 +1,5 @@ -import { afterEach, describe, expect, it, vi } from 'vitest' -import { - type FeatureFlagContext, - getFeatureFlagEnvironment, -} from '@/core/modules/feature-flags/context' +import { describe, expect, it, vi } from 'vitest' +import type { FeatureFlagContext } from '@/core/modules/feature-flags/context' import { FEATURE_FLAGS } from '@/core/modules/feature-flags/definitions' import { createFeatureFlagService } from '@/core/modules/feature-flags/feature-flags.server' import { createOpenFeatureEvaluationContext } from '@/core/modules/feature-flags/launchdarkly-openfeature-provider.server' @@ -17,13 +14,8 @@ const context = { slug: 'team-slug', name: 'Team Name', }, - environment: 'staging', } satisfies FeatureFlagContext -afterEach(() => { - vi.unstubAllEnvs() -}) - describe('createFeatureFlagService', () => { it('evaluates boolean flags through the provider', async () => { const provider = { @@ -94,13 +86,11 @@ describe('createOpenFeatureEvaluationContext', () => { user: { targetingKey: 'user-id', email: 'user@example.com', - environment: 'staging', }, team: { targetingKey: 'team-id', name: 'Team Name', slug: 'team-slug', - environment: 'staging', }, }) }) @@ -117,29 +107,6 @@ describe('createOpenFeatureEvaluationContext', () => { kind: 'user', targetingKey: 'user-id', email: 'user@example.com', - environment: 'staging', }) }) }) - -describe('getFeatureFlagEnvironment', () => { - it('uses the explicit feature flag environment', () => { - vi.stubEnv('FEATURE_FLAG_ENVIRONMENT', 'production') - - expect(getFeatureFlagEnvironment()).toBe('production') - }) - - it('maps production Vercel deployments to production', () => { - vi.stubEnv('FEATURE_FLAG_ENVIRONMENT', '') - vi.stubEnv('VERCEL_ENV', 'production') - - expect(getFeatureFlagEnvironment()).toBe('production') - }) - - it('maps non-production deployments to staging', () => { - vi.stubEnv('FEATURE_FLAG_ENVIRONMENT', '') - vi.stubEnv('VERCEL_ENV', 'preview') - - expect(getFeatureFlagEnvironment()).toBe('staging') - }) -})