Skip to content
This repository has been archived by the owner on May 16, 2024. It is now read-only.

Commit

Permalink
Merge pull request #24 from zerodays/feat/env-validation
Browse files Browse the repository at this point in the history
feat: added t3-oss validation of environment variables
  • Loading branch information
zigapk authored Nov 15, 2023
2 parents 9ef4501 + 6a9bb05 commit 2923086
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 52 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ jobs:
- uses: pnpm/action-setup@v2
with:
run_install: true
- uses: zerodays/action-infisical@v1
with:
infisical_token: ${{ secrets.INFISICAL_TOKEN }}
environment: "staging"
- name: Lint
run: |
pnpm lint
source .env && pnpm tsc
typecheck:
runs-on: ubuntu-latest
steps:
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ jobs:
- uses: pnpm/action-setup@v2
with:
run_install: true
- uses: ArtiomTr/jest-coverage-report-action@v2
- uses: zerodays/action-infisical@v1
with:
package-manager: pnpm
infisical_token: ${{ secrets.INFISICAL_TOKEN }}
environment: 'staging'
- name: Run tests
run: source .env && pnpm jest --reporters="summary" --reporters="github-actions"
5 changes: 5 additions & 0 deletions .infisical.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"workspaceId": "65521d699e945b505e4731d8",
"defaultEnvironment": "",
"gitBranchToEnvironmentMapping": null
}
46 changes: 0 additions & 46 deletions next.config.js

This file was deleted.

33 changes: 33 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
await import('./src/env.mjs');
import { withSentryConfig } from '@sentry/nextjs';
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import { withAxiom } from 'next-axiom';

/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
sentry: {
// Upload a larger set of source maps for prettier stack traces (increases build time)
widenClientFileUpload: true,

// Transpiles SDK to be compatible with IE11 (increases bundle size)
transpileClientSDK: true,

// Routes browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers (increases server load)
tunnelRoute: '/monitoring',

// Hides source maps from generated client bundles
hideSourceMaps: true,

// Automatically tree-shake Sentry logger statements to reduce bundle size
disableLogger: true,
},
};

export default withAxiom(
withSentryConfig(nextConfig, {
silent: true,
org: 'zerodays',
project: 'next-template',
}),
);
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"packageManager": "[email protected]",
"scripts": {
"dev": "next dev",
"dev": "infisical run -- next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
Expand All @@ -18,6 +18,7 @@
"@hookform/resolvers": "^3.1.0",
"@next/bundle-analyzer": "^14.0.0",
"@sentry/nextjs": "7.77.0",
"@t3-oss/env-nextjs": "^0.7.1",
"autoprefixer": "10.4.14",
"next": "^14.0.0",
"next-axiom": "^1.1.0",
Expand All @@ -28,7 +29,7 @@
"react-hook-form": "^7.44.3",
"tailwindcss": "3.3.2",
"typescript": "^5.2.2",
"zod": "^3.22.3"
"zod": "^3.22.4"
},
"devDependencies": {
"@commitlint/cli": "^18.2.0",
Expand Down
32 changes: 31 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

90 changes: 90 additions & 0 deletions src/env.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { createEnv } from '@t3-oss/env-nextjs';
import { z } from 'zod';

// Base schema for common variables
const baseSchema = {
server: {
NODE_ENV: z
.enum(['development', 'test', 'production'])
.default('development'),
SENTRY_AUTH_TOKEN: z.string(),
},
client: {
NEXT_PUBLIC_NODE_ENV: z
.enum(['development', 'test', 'production'])
.default('development'),
},
// ... other shared properties
};

// Development environment-specific schema
const devSchema = {
client: {
NEXT_PUBLIC_SENTRY_DNS: z.string().optional(),
NEXT_PUBLIC_SENTRY_TRACE_SAMPLE_RATE: z.coerce.number().optional(),
},
// ... other dev/test-specific properties
};

// Staging environment-specific schema
const stagingSchema = {
client: {
NEXT_PUBLIC_SENTRY_DNS: z.string().optional(),
NEXT_PUBLIC_SENTRY_TRACE_SAMPLE_RATE: z.coerce.number().optional(),
},
// ... other staging-specific properties
};

// Production environment-specific schema
const productionSchema = {
client: {
NEXT_PUBLIC_SENTRY_DNS: z
.string()
.min(1, { message: 'Sentry DNS is required in production' }),
NEXT_PUBLIC_SENTRY_TRACE_SAMPLE_RATE: z.coerce.number(),
},
// ... other production-specific properties
};

// Determine the current environment and merge schemas accordingly
const currentEnv = process.env.NODE_ENV || 'development'; // Default to 'development' if NODE_ENV is not set

let envSchema;
switch (currentEnv) {
case 'development':
envSchema = { ...baseSchema, ...devSchema };
break;
case 'test':
case 'staging':
envSchema = { ...baseSchema, ...stagingSchema };
break;
case 'production':
envSchema = { ...baseSchema, ...productionSchema };
break;
default:
throw new Error(`Unknown environment: ${currentEnv}`);
}

// Runtime environment variables (for Next.js edge runtimes or client-side)
const runtimeEnv = {
NODE_ENV: process.env.NODE_ENV,
NEXT_PUBLIC_NODE_ENV: process.env.NEXT_PUBLIC_NODE_ENV,
SENTRY_AUTH_TOKEN: process.env.SENTRY_AUTH_TOKEN,
NEXT_PUBLIC_SENTRY_DNS: process.env.NEXT_PUBLIC_SENTRY_DNS,
NEXT_PUBLIC_SENTRY_TRACE_SAMPLE_RATE:
process.env.NEXT_PUBLIC_SENTRY_TRACE_SAMPLE_RATE,
};

// Skip env validation flag (useful for Docker builds)
const skipValidation = !!process.env.SKIP_ENV_VALIDATION;

// Treat empty strings as undefined
const emptyStringAsUndefined = true;

// Create and export the environment object
export const env = createEnv({
...envSchema,
runtimeEnv,
skipValidation,
emptyStringAsUndefined,
});

1 comment on commit 2923086

@vercel
Copy link

@vercel vercel bot commented on 2923086 Nov 15, 2023

Choose a reason for hiding this comment

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

Please sign in to comment.