gamma-multi-env-setup

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Gamma Multi-Environment Setup

Gamma 多环境配置

Overview

概述

Configure Gamma across development, staging, and production environments with proper isolation and secrets management.
在开发、预发布(staging)和生产环境中配置Gamma,实现环境隔离与密钥管理。

Prerequisites

前提条件

  • Separate Gamma API keys per environment
  • Secret management solution (Vault, AWS Secrets Manager, etc.)
  • CI/CD pipeline with environment variables
  • Environment detection in application
  • 每个环境拥有独立的Gamma API密钥
  • 密钥管理方案(如Vault、AWS Secrets Manager等)
  • 支持环境变量的CI/CD流水线
  • 应用中具备环境检测能力

Instructions

操作步骤

Step 1: Environment Configuration Structure

步骤1:环境配置结构

typescript
// config/gamma.config.ts
interface GammaConfig {
  apiKey: string;
  baseUrl: string;
  timeout: number;
  retries: number;
  debug: boolean;
}

type Environment = 'development' | 'staging' | 'production';

const configs: Record<Environment, Partial<GammaConfig>> = {
  development: {
    baseUrl: 'https://api.gamma.app/v1',
    timeout: 60000,
    retries: 1,
    debug: true,
  },
  staging: {
    baseUrl: 'https://api.gamma.app/v1',
    timeout: 45000,
    retries: 2,
    debug: true,
  },
  production: {
    baseUrl: 'https://api.gamma.app/v1',
    timeout: 30000,
    retries: 3,
    debug: false,
  },
};

export function getConfig(): GammaConfig {
  const env = (process.env.NODE_ENV || 'development') as Environment;
  const envConfig = configs[env];

  return {
    apiKey: process.env.GAMMA_API_KEY!,
    ...envConfig,
  } as GammaConfig;
}
typescript
// config/gamma.config.ts
interface GammaConfig {
  apiKey: string;
  baseUrl: string;
  timeout: number;
  retries: number;
  debug: boolean;
}

type Environment = 'development' | 'staging' | 'production';

const configs: Record<Environment, Partial<GammaConfig>> = {
  development: {
    baseUrl: 'https://api.gamma.app/v1',
    timeout: 60000,
    retries: 1,
    debug: true,
  },
  staging: {
    baseUrl: 'https://api.gamma.app/v1',
    timeout: 45000,
    retries: 2,
    debug: true,
  },
  production: {
    baseUrl: 'https://api.gamma.app/v1',
    timeout: 30000,
    retries: 3,
    debug: false,
  },
};

export function getConfig(): GammaConfig {
  const env = (process.env.NODE_ENV || 'development') as Environment;
  const envConfig = configs[env];

  return {
    apiKey: process.env.GAMMA_API_KEY!,
    ...envConfig,
  } as GammaConfig;
}

Step 2: Environment-Specific API Keys

步骤2:环境专属API密钥

bash
undefined
bash
undefined

.env.development

.env.development

GAMMA_API_KEY=gamma_dev_xxx... GAMMA_MOCK=false NODE_ENV=development
GAMMA_API_KEY=gamma_dev_xxx... GAMMA_MOCK=false NODE_ENV=development

.env.staging

.env.staging

GAMMA_API_KEY=gamma_staging_xxx... GAMMA_MOCK=false NODE_ENV=staging
GAMMA_API_KEY=gamma_staging_xxx... GAMMA_MOCK=false NODE_ENV=staging

.env.production

.env.production

GAMMA_API_KEY=gamma_prod_xxx... GAMMA_MOCK=false NODE_ENV=production
undefined
GAMMA_API_KEY=gamma_prod_xxx... GAMMA_MOCK=false NODE_ENV=production
undefined

Step 3: Secret Management Integration

步骤3:集成密钥管理

typescript
// lib/secrets.ts
import { SecretsManager } from '@aws-sdk/client-secrets-manager';

const secretsManager = new SecretsManager({ region: 'us-east-1' });

interface SecretCache {
  value: string;
  expiresAt: number;
}

const cache: Map<string, SecretCache> = new Map();
const CACHE_TTL = 300000; // 5 minutes

export async function getSecret(name: string): Promise<string> {
  const cached = cache.get(name);
  if (cached && cached.expiresAt > Date.now()) {
    return cached.value;
  }

  const env = process.env.NODE_ENV || 'development';
  const secretName = `gamma/${env}/${name}`;

  const response = await secretsManager.getSecretValue({
    SecretId: secretName,
  });

  const value = response.SecretString!;
  cache.set(name, { value, expiresAt: Date.now() + CACHE_TTL });

  return value;
}

// Usage
const apiKey = await getSecret('api-key');
typescript
// lib/secrets.ts
import { SecretsManager } from '@aws-sdk/client-secrets-manager';

const secretsManager = new SecretsManager({ region: 'us-east-1' });

interface SecretCache {
  value: string;
  expiresAt: number;
}

const cache: Map<string, SecretCache> = new Map();
const CACHE_TTL = 300000; // 5 minutes

export async function getSecret(name: string): Promise<string> {
  const cached = cache.get(name);
  if (cached && cached.expiresAt > Date.now()) {
    return cached.value;
  }

  const env = process.env.NODE_ENV || 'development';
  const secretName = `gamma/${env}/${name}`;

  const response = await secretsManager.getSecretValue({
    SecretId: secretName,
  });

  const value = response.SecretString!;
  cache.set(name, { value, expiresAt: Date.now() + CACHE_TTL });

  return value;
}

// Usage
const apiKey = await getSecret('api-key');

Step 4: Client Factory

步骤4:客户端工厂

typescript
// lib/gamma-factory.ts
import { GammaClient } from '@gamma/sdk';
import { getConfig } from '../config/gamma.config';
import { getSecret } from './secrets';

let clients: Map<string, GammaClient> = new Map();

export async function getGammaClient(): Promise<GammaClient> {
  const env = process.env.NODE_ENV || 'development';

  if (clients.has(env)) {
    return clients.get(env)!;
  }

  const config = getConfig();

  // In production, fetch from secret manager
  const apiKey = env === 'production'
    ? await getSecret('api-key')
    : config.apiKey;

  const client = new GammaClient({
    apiKey,
    baseUrl: config.baseUrl,
    timeout: config.timeout,
    retries: config.retries,
    debug: config.debug,
  });

  clients.set(env, client);
  return client;
}
typescript
// lib/gamma-factory.ts
import { GammaClient } from '@gamma/sdk';
import { getConfig } from '../config/gamma.config';
import { getSecret } from './secrets';

let clients: Map<string, GammaClient> = new Map();

export async function getGammaClient(): Promise<GammaClient> {
  const env = process.env.NODE_ENV || 'development';

  if (clients.has(env)) {
    return clients.get(env)!;
  }

  const config = getConfig();

  // In production, fetch from secret manager
  const apiKey = env === 'production'
    ? await getSecret('api-key')
    : config.apiKey;

  const client = new GammaClient({
    apiKey,
    baseUrl: config.baseUrl,
    timeout: config.timeout,
    retries: config.retries,
    debug: config.debug,
  });

  clients.set(env, client);
  return client;
}

Step 5: Environment Guards

步骤5:环境防护

typescript
// lib/env-guards.ts
export function requireProduction(): void {
  if (process.env.NODE_ENV !== 'production') {
    throw new Error('This operation requires production environment');
  }
}

export function blockProduction(): void {
  if (process.env.NODE_ENV === 'production') {
    throw new Error('This operation is blocked in production');
  }
}

// Usage
async function deleteAllPresentations() {
  blockProduction(); // Safety guard

  const gamma = await getGammaClient();
  const presentations = await gamma.presentations.list();

  for (const p of presentations) {
    await gamma.presentations.delete(p.id);
  }
}

async function runMigration() {
  requireProduction(); // Ensure correct environment

  // Migration logic
}
typescript
// lib/env-guards.ts
export function requireProduction(): void {
  if (process.env.NODE_ENV !== 'production') {
    throw new Error('This operation requires production environment');
  }
}

export function blockProduction(): void {
  if (process.env.NODE_ENV === 'production') {
    throw new Error('This operation is blocked in production');
  }
}

// Usage
async function deleteAllPresentations() {
  blockProduction(); // Safety guard

  const gamma = await getGammaClient();
  const presentations = await gamma.presentations.list();

  for (const p of presentations) {
    await gamma.presentations.delete(p.id);
  }
}

async function runMigration() {
  requireProduction(); // Ensure correct environment

  // Migration logic
}

Step 6: CI/CD Environment Configuration

步骤6:CI/CD环境配置

yaml
undefined
yaml
undefined

.github/workflows/deploy.yml

.github/workflows/deploy.yml

name: Deploy
on: push: branches: - develop # → staging - main # → production
jobs: deploy-staging: if: github.ref == 'refs/heads/develop' runs-on: ubuntu-latest environment: staging steps: - uses: actions/checkout@v4 - name: Deploy to Staging env: GAMMA_API_KEY: ${{ secrets.GAMMA_API_KEY_STAGING }} NODE_ENV: staging run: | npm ci npm run build npm run deploy:staging
deploy-production: if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest environment: production steps: - uses: actions/checkout@v4 - name: Deploy to Production env: GAMMA_API_KEY: ${{ secrets.GAMMA_API_KEY_PRODUCTION }} NODE_ENV: production run: | npm ci npm run build npm run deploy:production
undefined
name: Deploy
on: push: branches: - develop # → staging - main # → production
jobs: deploy-staging: if: github.ref == 'refs/heads/develop' runs-on: ubuntu-latest environment: staging steps: - uses: actions/checkout@v4 - name: Deploy to Staging env: GAMMA_API_KEY: ${{ secrets.GAMMA_API_KEY_STAGING }} NODE_ENV: staging run: | npm ci npm run build npm run deploy:staging
deploy-production: if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest environment: production steps: - uses: actions/checkout@v4 - name: Deploy to Production env: GAMMA_API_KEY: ${{ secrets.GAMMA_API_KEY_PRODUCTION }} NODE_ENV: production run: | npm ci npm run build npm run deploy:production
undefined

Environment Checklist

环境检查清单

CheckDevStagingProd
Separate API keyYesYesYes
Debug loggingOnOnOff
Mock mode availableYesYesNo
Secret managerNoYesYes
Rate limit tierLowMediumHigh
Error reportingConsoleSentrySentry
检查项开发环境预发布环境生产环境
独立API密钥
调试日志开启开启关闭
支持模拟模式
集成密钥管理器
限流等级
错误上报控制台SentrySentry

Resources

参考资源

Next Steps

下一步操作

Proceed to
gamma-observability
for monitoring setup.
继续查看
gamma-observability
进行监控设置。