apollo-multi-env-setup
Apollo.ioのマルチ環境設定を構成します。 開発環境、ステージング環境、本番環境のセットアップ、または複数のApollo設定の管理が必要な場合に使用してください。「apollo environments」「apollo staging」「apollo dev prod」「apollo multi-tenant」「apollo env config」といったフレーズでトリガーできます。
description の原文を見る
Configure Apollo.io multi-environment setup. Use when setting up development, staging, and production environments, or managing multiple Apollo configurations. Trigger with phrases like "apollo environments", "apollo staging", "apollo dev prod", "apollo multi-tenant", "apollo env config".
SKILL.md 本文
Apollo マルチ環境セットアップ
概要
Apollo.io を複数の環境 (開発、ステージング、本番) で構成し、適切な分離、設定管理、デプロイメント戦略を実装します。
環境戦略
| 環境 | 用途 | API キー | レート制限 | データアクセス |
|---|---|---|---|---|
| Development | ローカル開発 | Dev/Sandbox | 低 (10/分) | テストデータのみ |
| Staging | 本番前テスト | ステージングキー | 中 (50/分) | 限定的な本番データ |
| Production | ライブシステム | 本番キー | フル (100/分) | 完全なアクセス |
設定構造
// src/config/apollo/environments.ts
import { z } from 'zod';
const EnvironmentConfigSchema = z.object({
apiKey: z.string().min(1),
baseUrl: z.string().url().default('https://api.apollo.io/v1'),
rateLimit: z.number().positive(),
timeout: z.number().positive().default(30000),
cacheEnabled: z.boolean().default(true),
cacheTtl: z.number().positive().default(300),
features: z.object({
search: z.boolean().default(true),
enrichment: z.boolean().default(true),
sequences: z.boolean().default(false),
webhooks: z.boolean().default(false),
}),
logging: z.object({
level: z.enum(['debug', 'info', 'warn', 'error']),
redactPII: z.boolean().default(true),
}),
});
type EnvironmentConfig = z.infer<typeof EnvironmentConfigSchema>;
const configs: Record<string, EnvironmentConfig> = {
development: {
apiKey: process.env.APOLLO_API_KEY_DEV || '',
baseUrl: 'https://api.apollo.io/v1',
rateLimit: 10,
timeout: 30000,
cacheEnabled: true,
cacheTtl: 60, // Short cache in dev
features: {
search: true,
enrichment: true,
sequences: false, // Disabled in dev
webhooks: false,
},
logging: {
level: 'debug',
redactPII: false, // Show full data in dev
},
},
staging: {
apiKey: process.env.APOLLO_API_KEY_STAGING || '',
baseUrl: 'https://api.apollo.io/v1',
rateLimit: 50,
timeout: 30000,
cacheEnabled: true,
cacheTtl: 300,
features: {
search: true,
enrichment: true,
sequences: true,
webhooks: true,
},
logging: {
level: 'info',
redactPII: true,
},
},
production: {
apiKey: process.env.APOLLO_API_KEY || '',
baseUrl: 'https://api.apollo.io/v1',
rateLimit: 90, // Buffer below 100
timeout: 30000,
cacheEnabled: true,
cacheTtl: 900, // 15 min in prod
features: {
search: true,
enrichment: true,
sequences: true,
webhooks: true,
},
logging: {
level: 'warn',
redactPII: true,
},
},
};
export function getConfig(): EnvironmentConfig {
const env = process.env.NODE_ENV || 'development';
const config = configs[env];
if (!config) {
throw new Error(`Unknown environment: ${env}`);
}
// Validate configuration
const result = EnvironmentConfigSchema.safeParse(config);
if (!result.success) {
throw new Error(`Invalid Apollo config for ${env}: ${result.error.message}`);
}
return result.data;
}
export function validateEnvironment(): void {
const config = getConfig();
if (!config.apiKey) {
throw new Error('Apollo API key is required');
}
console.log(`Apollo configured for ${process.env.NODE_ENV || 'development'}`);
console.log(` Rate limit: ${config.rateLimit}/min`);
console.log(` Features: ${Object.entries(config.features).filter(([,v]) => v).map(([k]) => k).join(', ')}`);
}
環境ファイル
# .env.development
NODE_ENV=development
APOLLO_API_KEY_DEV=your-dev-api-key
APOLLO_RATE_LIMIT=10
APOLLO_CACHE_TTL=60
APOLLO_LOG_LEVEL=debug
# .env.staging
NODE_ENV=staging
APOLLO_API_KEY_STAGING=your-staging-api-key
APOLLO_RATE_LIMIT=50
APOLLO_CACHE_TTL=300
APOLLO_LOG_LEVEL=info
# .env.production
NODE_ENV=production
APOLLO_API_KEY=your-prod-api-key
APOLLO_RATE_LIMIT=90
APOLLO_CACHE_TTL=900
APOLLO_LOG_LEVEL=warn
Kubernetes ConfigMaps
# k8s/configmaps/apollo-config-dev.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: apollo-config
namespace: development
data:
NODE_ENV: "development"
APOLLO_RATE_LIMIT: "10"
APOLLO_CACHE_TTL: "60"
APOLLO_LOG_LEVEL: "debug"
APOLLO_FEATURES_SEARCH: "true"
APOLLO_FEATURES_ENRICHMENT: "true"
APOLLO_FEATURES_SEQUENCES: "false"
APOLLO_FEATURES_WEBHOOKS: "false"
---
# k8s/configmaps/apollo-config-staging.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: apollo-config
namespace: staging
data:
NODE_ENV: "staging"
APOLLO_RATE_LIMIT: "50"
APOLLO_CACHE_TTL: "300"
APOLLO_LOG_LEVEL: "info"
APOLLO_FEATURES_SEARCH: "true"
APOLLO_FEATURES_ENRICHMENT: "true"
APOLLO_FEATURES_SEQUENCES: "true"
APOLLO_FEATURES_WEBHOOKS: "true"
---
# k8s/configmaps/apollo-config-prod.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: apollo-config
namespace: production
data:
NODE_ENV: "production"
APOLLO_RATE_LIMIT: "90"
APOLLO_CACHE_TTL: "900"
APOLLO_LOG_LEVEL: "warn"
APOLLO_FEATURES_SEARCH: "true"
APOLLO_FEATURES_ENRICHMENT: "true"
APOLLO_FEATURES_SEQUENCES: "true"
APOLLO_FEATURES_WEBHOOKS: "true"
シークレット管理
# k8s/secrets/apollo-secrets.yaml (実運用では sealed-secrets を使用してください)
apiVersion: v1
kind: Secret
metadata:
name: apollo-secrets
namespace: ${NAMESPACE}
type: Opaque
stringData:
api-key: ${APOLLO_API_KEY}
webhook-secret: ${APOLLO_WEBHOOK_SECRET}
# External Secrets Operator を使用する場合
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: apollo-secrets
spec:
refreshInterval: 1h
secretStoreRef:
name: gcp-secret-manager
kind: ClusterSecretStore
target:
name: apollo-secrets
data:
- secretKey: api-key
remoteRef:
key: apollo-api-key-${ENV}
- secretKey: webhook-secret
remoteRef:
key: apollo-webhook-secret-${ENV}
環境対応クライアント
// src/lib/apollo/env-client.ts
import { getConfig } from '../../config/apollo/environments';
class EnvironmentAwareApolloClient {
private config = getConfig();
async request<T>(options: RequestOptions): Promise<T> {
// Check feature flag
if (!this.isFeatureEnabled(options.feature)) {
throw new Error(`Feature ${options.feature} is disabled in ${process.env.NODE_ENV}`);
}
// Apply environment-specific rate limiting
await this.rateLimiter.acquire();
// Make request with environment config
const response = await axios({
...options,
baseURL: this.config.baseUrl,
timeout: this.config.timeout,
params: {
...options.params,
api_key: this.config.apiKey,
},
});
// Log based on environment
this.log('info', `Apollo ${options.method} ${options.url}`, {
status: response.status,
duration: response.headers['x-response-time'],
});
return response.data;
}
private isFeatureEnabled(feature: string): boolean {
return this.config.features[feature as keyof typeof this.config.features] ?? true;
}
private log(level: string, message: string, meta?: object): void {
if (this.shouldLog(level)) {
const sanitized = this.config.logging.redactPII
? this.redactPII(meta)
: meta;
console[level as 'log'](`[Apollo] ${message}`, sanitized);
}
}
private shouldLog(level: string): boolean {
const levels = ['debug', 'info', 'warn', 'error'];
return levels.indexOf(level) >= levels.indexOf(this.config.logging.level);
}
}
環境を跨いだテスト
// tests/integration/env-tests.ts
describe('Environment Configuration', () => {
const originalEnv = process.env.NODE_ENV;
afterEach(() => {
process.env.NODE_ENV = originalEnv;
});
it('loads development config correctly', () => {
process.env.NODE_ENV = 'development';
const config = getConfig();
expect(config.rateLimit).toBe(10);
expect(config.features.sequences).toBe(false);
});
it('loads staging config correctly', () => {
process.env.NODE_ENV = 'staging';
const config = getConfig();
expect(config.rateLimit).toBe(50);
expect(config.features.sequences).toBe(true);
});
it('loads production config correctly', () => {
process.env.NODE_ENV = 'production';
const config = getConfig();
expect(config.rateLimit).toBe(90);
expect(config.logging.redactPII).toBe(true);
});
it('throws on missing API key', () => {
process.env.NODE_ENV = 'production';
delete process.env.APOLLO_API_KEY;
expect(() => validateEnvironment()).toThrow();
});
});
環境プロモーション
#!/bin/bash
# scripts/promote-to-staging.sh
echo "Promoting to staging environment..."
# Verify staging key is configured
if [ -z "$APOLLO_API_KEY_STAGING" ]; then
echo "Error: APOLLO_API_KEY_STAGING not set"
exit 1
fi
# Run staging tests
NODE_ENV=staging npm run test:integration
# Deploy to staging
kubectl apply -f k8s/configmaps/apollo-config-staging.yaml
kubectl apply -f k8s/secrets/apollo-secrets-staging.yaml
kubectl rollout restart deployment/apollo-service -n staging
# Verify deployment
kubectl rollout status deployment/apollo-service -n staging
curl -sf https://staging.example.com/health/apollo || exit 1
echo "Successfully promoted to staging"
出力
- 環境固有の設定
- Kubernetes ConfigMaps と Secrets
- 環境対応クライアント
- 環境ごとの機能フラグ
- 環境プロモーションスクリプト
エラーハンドリング
| 問題 | 解決策 |
|---|---|
| 間違った環境 | NODE_ENV 変数を確認してください |
| API キーの欠落 | シークレット設定を確認してください |
| 機能が無効 | 環境設定を確認してください |
| レート制限の不一致 | 設定値を確認してください |
リソース
次のステップ
監視セットアップについては apollo-observability に進んでください。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- Brmbobo
- リポジトリ
- Brmbobo/Web2podcast
- ライセンス
- MIT
- 最終更新
- 2026/1/26
Source: https://github.com/Brmbobo/Web2podcast / ライセンス: MIT
関連スキル
superpowers-streamer-cli
SuperPowers デスクトップストリーマーの npm パッケージをインストール、ログイン、実行、トラブルシューティングできます。ユーザーが npm から `superpowers-ai` をセットアップしたい場合、メールまたは電話でサインインもしくはアカウント作成を行いたい場合、ストリーマーを起動したい場合、表示されたコントロールリンクを開きたい場合、後で停止したい場合、またはソースコードへのアクセスなしに npm やランタイムの一般的な問題から復旧したい場合に使用します。
catc-client-ops
Catalyst Centerのクライアント操作・監視機能 - 有線・無線クライアントのリスト表示・フィルタリング、MACアドレスによる詳細なクライアント検索、クライアント数分析、時間軸での分析、SSIDおよび周波数帯によるフィルタリング、無線トラブルシューティング機能を提供します。MACアドレスやIPアドレスでのクライアント検索、サイト別やSSID別のクライアント数集計、無線周波数帯の分布分析、Wi-Fi信号の問題調査が必要な場合に活用できます。
ci-cd-and-automation
CI/CDパイプラインの設定を自動化します。ビルドおよびデプロイメントパイプラインの構築または変更時に使用できます。品質ゲートの自動化、CI内のテストランナー設定、またはデプロイメント戦略の確立が必要な場合に活用します。
shipping-and-launch
本番環境へのリリース準備を行います。本番環境へのデプロイ準備が必要な場合、リリース前チェックリストが必要な場合、監視機能の設定を行う場合、段階的なロールアウトを計画する場合、またはロールバック戦略が必要な場合に使用します。
linear-release-setup
Linear Releaseに向けたCI/CD設定を生成します。リリース追跡の設定、LinearのCIパイプライン構築、またはLinearリリースとのデプロイメント連携を実施する際に利用できます。GitHub Actions、GitLab CI、CircleCIなど複数のプラットフォームに対応しています。
tracking-application-response-times
API エンドポイント、データベースクエリ、サービスコール全体にわたるアプリケーションのレスポンスタイムを追跡・最適化できます。パフォーマンス監視やボトルネック特定の際に活用してください。「レスポンスタイムを追跡する」「API パフォーマンスを監視する」「遅延を分析する」といった表現で呼び出せます。