mcpField
O
openfeature

openfeature

github.com/laurigates開発5972 回インストール1 日前に更新
リポジトリ

openfeature について

openfeatureは、アプリケーションにフィーチャーフラグを実装する開発者向けのOpenFeature SDK統合ガイドです。複数言語で共通のAPI、プロバイダー、評価コンテキスト、フック、テスト方法を説明します。

主な機能

  1. 01ベンダー非依存のフィーチャーフラグAPI
  2. 02Boolean・文字列・数値・オブジェクトの評価
  3. 03評価コンテキストとフック
  4. 04Node.js、Python、Go、Java、Rustへの統合
  5. 05インメモリプロバイダーとユニットテスト方法

活用シーン

  1. 01アプリケーションへのフィーチャーフラグSDK導入
  2. 02A/Bテストや段階的ロールアウトの実装
  3. 03フラグ評価でのユーザーターゲティング設定
  4. 04インメモリプロバイダーを使ったフラグロジックのテスト

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/laurigates/claude-plugins --skill openfeature

インストール後、Claude Code で/openfeatureを入力して読み込まれたか確認します。

詳細

OpenFeature SDK の統合

このスキルを使用する場面

このスキルを使用する場面...代わりに関連スキルを使用する場面...
ベンダーに依存しない OpenFeature SDK API、フック、評価パターンが必要な場合GO Feature Flag(GOFF)のセルフホスト型バックエンド固有の詳細が必要な場合は、go-feature-flag を使用します
プロバイダーを選択する場合や、OpenFeature クライアントをアプリケーションコードに組み込む場合フィーチャーフラグのスタック全体(SDK + プロバイダー + CI)をゼロから構築する場合は、configure-feature-flags を使用します
別のスキルで OpenFeature の仕様に関する標準リファレンスが必要な場合変更を加える前に、既存のフィーチャーフラグ設定を実行時に検出する場合は、configure-feature-flags を使用します

言語やプロバイダーを問わず、標準化された API を提供する、ベンダーに依存しないフィーチャーフラグ SDK です。フィーチャーフラグ、A/B テスト、カナリアリリース、プログレッシブロールアウトを、任意のフィーチャーフラグバックエンドで実装する際に使用します。

使用する場面

自動的に有効になる条件:

  • ユーザーが「feature flags」、「feature toggles」、「feature management」に言及した場合
  • ユーザーが A/B テストやカナリアリリースについて質問した場合
  • ユーザーがプログレッシブロールアウトの実装を希望する場合
  • プロジェクトに OpenFeature SDK の依存関係がある場合
  • ユーザーが OpenFeature、flagd、またはベンダーに依存しないフラグに言及した場合

関連スキル:

  • go-feature-flag - GO Feature Flag プロバイダー固有の詳細
  • launchdarkly - LaunchDarkly プロバイダーの統合

基本概念

アーキテクチャ
┌─────────────────────────────────────────────────────────────┐
│                    Application Code                          │
├─────────────────────────────────────────────────────────────┤
│                  OpenFeature SDK (API)                       │
│  ┌─────────────┬──────────────┬─────────────┬─────────────┐ │
│  │  getBool()  │  getString() │  getNumber()│  getObject()│ │
│  └─────────────┴──────────────┴─────────────┴─────────────┘ │
├─────────────────────────────────────────────────────────────┤
│                       Provider                               │
│  ┌─────────────────────────────────────────────────────────┐ │
│  │  GO Feature Flag │ flagd │ LaunchDarkly │ Split │ etc  │ │
│  └─────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│                    Flag Source                               │
│  ┌─────────────────────────────────────────────────────────┐ │
│  │   File   │   S3   │  GitHub  │  API  │  ConfigMap      │ │
│  └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
主なコンポーネント
  1. API - フラグ評価の標準化されたインターフェース
  2. プロバイダー - バックエンド固有の実装
  3. 評価コンテキスト - ターゲティングに使用するユーザー/リクエストデータ
  4. フック - ロギングやテレメトリーのためのライフサイクル拡張

SDK のインストール

Node.js(サーバー)
# Core SDK
npm install @openfeature/server-sdk

# Providers (choose one)
npm install @openfeature/go-feature-flag-provider  # GO Feature Flag
npm install @openfeature/flagd-provider            # flagd
npm install @openfeature/in-memory-provider        # Testing
Node.js(ブラウザー/React)
# Web SDK
npm install @openfeature/web-sdk

# React integration
npm install @openfeature/react-sdk

# Web providers
npm install @openfeature/go-feature-flag-web-provider
Python
uv add openfeature-sdk
uv add openfeature-provider-go-feature-flag  # GO Feature Flag provider
Go
go get github.com/open-feature/go-sdk
go get github.com/open-feature/go-sdk-contrib/providers/go-feature-flag
Java
<dependency>
    <groupId>dev.openfeature</groupId>
    <artifactId>sdk</artifactId>
    <version>1.7.0</version>
</dependency>
Rust
[dependencies]
open-feature = "0.2"

基本的な使用パターン

初期化
// TypeScript/Node.js
import { OpenFeature } from '@openfeature/server-sdk';
import { GoFeatureFlagProvider } from '@openfeature/go-feature-flag-provider';

// Initialize provider
const provider = new GoFeatureFlagProvider({
  endpoint: process.env.GOFF_RELAY_URL || 'http://localhost:1031',
});

// Set provider (awaitable for ready state)
await OpenFeature.setProviderAndWait(provider);

// Get client
const client = OpenFeature.getClient('my-app');
フラグ評価
// Boolean flag
const isEnabled = await client.getBooleanValue('new-feature', false);

// String flag
const buttonColor = await client.getStringValue('button-color', '#000000');

// Number flag
const maxItems = await client.getNumberValue('max-items', 10);

// Object/JSON flag
const config = await client.getObjectValue('feature-config', {});

// With evaluation context
const context = { targetingKey: userId, email: userEmail, groups: ['beta'] };
const isEnabled = await client.getBooleanValue('new-feature', false, context);
評価コンテキスト
// Creating context
const context: EvaluationContext = {
  // Required: unique identifier for targeting
  targetingKey: user.id,

  // Optional: additional attributes for targeting rules
  email: user.email,
  groups: user.roles,
  plan: user.subscription,

  // Custom attributes
  country: request.geoip.country,
  browser: request.headers['user-agent'],
};

// Set global context (applies to all evaluations)
OpenFeature.setContext(context);

// Or per-evaluation context
await client.getBooleanValue('feature', false, context);
フック
import { Hook, HookContext, EvaluationDetails } from '@openfeature/server-sdk';

// Logging hook
const loggingHook: Hook = {
  before: (hookContext: HookContext) => {
    console.log(`Evaluating flag: ${hookContext.flagKey}`);
  },
  after: (hookContext: HookContext, details: EvaluationDetails<unknown>) => {
    console.log(`Flag ${hookContext.flagKey} = ${details.value}`);
  },
  error: (hookContext: HookContext, error: Error) => {
    console.error(`Error evaluating ${hookContext.flagKey}:`, error);
  },
};

// Register globally
OpenFeature.addHooks(loggingHook);

// Or per-client
client.addHooks(loggingHook);
React の統合
import { OpenFeatureProvider, useFlag, useBooleanFlagValue } from '@openfeature/react-sdk';
import { GoFeatureFlagWebProvider } from '@openfeature/go-feature-flag-web-provider';

// Provider setup
const provider = new GoFeatureFlagWebProvider({
  endpoint: import.meta.env.VITE_GOFF_RELAY_URL,
});

function App() {
  return (
    <OpenFeatureProvider provider={provider}>
      <MyComponent />
    </OpenFeatureProvider>
  );
}

// Using flags in components
function MyComponent() {
  // Simple boolean value
  const isEnabled = useBooleanFlagValue('new-feature', false);

  // Full flag details
  const { value, isLoading, error } = useFlag('button-color', '#000');

  if (isLoading) return <Spinner />;

  return (
    <div>
      {isEnabled && <NewFeature />}
      <Button color={value}>Click me</Button>
    </div>
  );
}

テスト

インメモリプロバイダー
import { OpenFeature } from '@openfeature/server-sdk';
import { InMemoryProvider } from '@openfeature/in-memory-provider';

// Configure test flags
const testProvider = new InMemoryProvider({
  'new-feature': {
    variants: {
      on: true,
      off: false,
    },
    defaultVariant: 'off',
    disabled: false,
  },
  'button-color': {
    variants: {
      blue: '#0066CC',
      green: '#00CC66',
    },
    defaultVariant: 'blue',
    disabled: false,
  },
});

// Use in tests
beforeAll(async () => {
  await OpenFeature.setProviderAndWait(testProvider);
});

afterAll(async () => {
  await OpenFeature.close();
});
単体テストでのモック
import { vi } from 'vitest';
import { OpenFeature } from '@openfeature/server-sdk';

// Mock the entire SDK
vi.mock('@openfeature/server-sdk', () => ({
  OpenFeature: {
    getClient: vi.fn().mockReturnValue({
      getBooleanValue: vi.fn().mockResolvedValue(true),
      getStringValue: vi.fn().mockResolvedValue('test-value'),
    }),
  },
}));

ベストプラクティス

1. 早めに初期化する
// Initialize before app starts handling requests
async function bootstrap() {
  await initializeFeatureFlags();  // First
  await initializeDatabase();
  await startServer();
}
2. 意味のあるフラグ名を使用する
// Good: descriptive, namespaced
'checkout.new-payment-flow'
'dashboard.beta-analytics'
'api.rate-limit-v2'

// Bad: vague, unclear
'feature1'
'test-flag'
'enabled'
3. 必ずデフォルト値を指定する
// Good: safe default that works if provider fails
const isEnabled = await client.getBooleanValue('risky-feature', false);

// Consider: what's the safe behavior if flags fail?
const maxItems = await client.getNumberValue('max-items', 100); // Safe limit
4. プロバイダーのエラーを処理する
try {
  const value = await client.getBooleanValue('feature', false);
} catch (error) {
  // Log but don't crash - use default
  logger.error('Feature flag evaluation failed', { error });
  return defaultBehavior();
}
5. 古いフラグを整理する
// Track flag usage with hooks
const flagUsageHook: Hook = {
  after: (context, details) => {
    metrics.increment(`feature_flag.${context.flagKey}.evaluations`);
  },
};

// Regularly review and remove flags with 100% rollout
// or flags that haven't been evaluated in months

ドキュメント

関連コマンド

  • /configure:feature-flags - フィーチャーフラグのインフラストラクチャを設定します
  • /configure:sentry - エラー追跡(フィーチャーフラグのロールバック監視用)

コメント