Skip to content

open-feature/action

OpenFeature Logo

OpenFeature Action

work-in-progress Slack GitHub release License

OpenFeature is an open specification that provides a vendor-agnostic, community-driven API for feature flagging that works with your favorite feature flag management tool or in-house solution.

The OpenFeature GitHub Action compares OpenFeature flag manifests between your local configuration stored in your git repository, and/or a remote source using the OpenFeature CLI. This action helps teams maintain consistency between their local feature flag configurations and centralized flag management systems. It also enables Feature-Flag Driven Development by providing gitops for your feature flags.

Table of Contents

For Different Users

New to Feature Flags?

Feature flags (also called feature toggles) allow you to control which features are enabled in your application without deploying new code. This action helps you:

  • Track changes to your feature flag configuration
  • Prevent drift between your local configs and production
  • Review flag changes in pull requests before they go live

Quick example: If you have a feature flag for a new UI design, this action will notify you when someone changes the flag's default value from "off" to "on", helping you catch unintended changes before deployment.

DevOps Engineers

This action integrates seamlessly into CI/CD pipelines to:

  • Automate flag validation in pull request workflows
  • Detect configuration drift between environments
  • Compare multiple flag providers or environments directly
  • Enforce governance by requiring review of flag changes
  • Generate audit trails of all flag modifications

Recommended setup: Use both git comparison (to see what changed in your PR) and remote comparison (to check drift from your flag management system). For multi-environment setups, use remote-to-remote comparison to validate consistency.

Security Teams

Use this action for security and compliance:

  • Configuration drift detection - Know when local configs diverge from production
  • Change auditing - Every flag change is tracked and visible in pull requests
  • Access control - Require code review for flag changes just like any other code
  • Environment consistency - Ensure development matches production flag states

Contributors

Want to contribute? This action is built with:

  • GitHub Actions composite action pattern
  • OpenFeature CLI for the heavy lifting
  • Bash scripts for orchestration
  • YAML parsing for structured output

See the Contributing section for development setup.

Use Cases

  • Pull Request Validation: Compare flag changes between feature branches and base branches automatically
  • Branch Comparison: Validate flag manifest changes during development workflow
  • Remote Source Validation: Check if local flag changes align with external flag management systems
  • Remote-to-Remote Comparison: Compare flag configurations between different remote providers or environments
  • Drift Detection: Identify when local configurations have diverged from remote configurations
  • Environment Synchronization: Ensure consistency across development, staging, and production environments
  • Multi-Provider Validation: Compare flag configurations across different feature flag management systems
  • Compliance Checking: Verify that flag configurations meet organizational standards

Features

  • 🔍 Manifest Comparison - Compare local flag manifests against remote sources OR git branches
  • 🌿 Git Branch Comparison - Automatically compare against PR base branches with minimal configuration
  • 🔗 Smart Mode Detection - Automatically detects URL vs git mode based on input format
  • 🔐 Authentication Support - Secure access to protected flag sources using tokens
  • 📊 Rich GitHub Integration - Detailed summaries with change breakdowns in GitHub Action results
  • ⚙️ Flexible Configuration - Support for various protocols and git branch comparisons
  • 🛡️ Error Handling - Graceful handling of network issues, missing files, and CLI failures
  • 🔧 CI/CD Ready - Designed for seamless integration into existing workflows
  • 💬 Smart PR Comments - Automatically posts/updates comments on pull requests with differences

Prerequisites

  • GitHub Actions workflow
  • Git repository with OpenFeature manifest file
  • For git branch comparison: fetch-depth: 0 in your checkout action (to access branch history)
  • For remote source comparison: Access to a remote manifest source (URL or provider)
  • (Optional) Authentication token for protected sources

Note: The action uses the OpenFeature CLI, which is automatically installed during the workflow run.

Quick Start

For Pull Request Workflows (Recommended)

This is the simplest setup - just compare your changes against the target branch:

name: Validate Flag Changes
on: pull_request

jobs:
  validate-flags:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Required for git comparison
      
      - name: Compare flag manifests
        uses: open-feature/action@v1
        with:
          manifest: "flags.json"
          # Automatically compares against PR base branch

For Remote Source Comparison

Compare your local manifest against a remote flag management system:

name: Check Flag Drift
on: [push, pull_request]

jobs:
  check-drift:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Compare against production flags
        uses: open-feature/action@v1
        with:
          against: "https://your-flag-provider.com/api/flags"
          manifest: "flags.json"
          auth-token: ${{ secrets.FLAG_PROVIDER_TOKEN }}

Inputs & Outputs

Inputs

Input Description Required Default
against URL/remote source OR local path for git comparison (optional for PR workflows) No -
manifest Path to your local flag manifest file relative to repository root OR URL to remote manifest No flags.json
base-branch Base branch for git comparison (auto-detected in PRs) No -
auth-token Authentication token for accessing protected against sources (use GitHub secrets) No -
manifest-auth-token Authentication token for accessing protected manifest sources (use GitHub secrets) No -
cli-version OpenFeature CLI version to use No latest
against-manifest-path Path where the fetched manifest from the against source will be saved locally No against-flags.json
strict Strict mode - fail the action if differences are found No false
post-pr-comment Post a comment on the PR when differences are detected No true

Mode Detection

The action automatically detects the comparison mode based on the against input:

  • URL Mode: When against contains a protocol (e.g., http://, https://, git://, ssh://, file://) or Git SSH format
  • Git Mode: When against is a local path or omitted entirely

Git Mode Behavior:

  • If in a pull request context: Uses $GITHUB_BASE_REF (the PR's target branch)
  • If base-branch is provided: Uses the specified branch
  • Otherwise: Defaults to main branch

Outputs

Output Description
has-differences Boolean string indicating if differences were found ("true"/"false")
comparison-result Raw comparison output from OpenFeature CLI in YAML format
against-manifest-path File path where the against manifest was saved
local-manifest-path File path of the local manifest (original path or downloaded from URL)
summary Human-readable summary of the comparison result

Usage Examples

Basic Examples

Minimal PR Validation

- name: Validate flag changes
  uses: open-feature/action@v1
  with:
    manifest: "flags.json"

Compare Against Specific Branch

- name: Compare against develop
  uses: open-feature/action@v1
  with:
    manifest: "flags.json"
    base-branch: "develop"

Compare Against Remote Source

- name: Check against production
  uses: open-feature/action@v1
  with:
    against: "https://api.flagprovider.com/flags.json"
    manifest: "flags.json"
    auth-token: ${{ secrets.FLAG_TOKEN }}

Remote-to-Remote Comparison

- name: Compare two remote sources
  uses: open-feature/action@v1
  with:
    manifest: "https://staging.flagprovider.com/flags.json"
    against: "https://production.flagprovider.com/flags.json"
    manifest-auth-token: ${{ secrets.STAGING_TOKEN }}
    auth-token: ${{ secrets.PRODUCTION_TOKEN }}

Advanced Examples

Strict Mode (Fail on Differences)

- name: Enforce flag sync
  uses: open-feature/action@v1
  with:
    against: "https://api.flagprovider.com/flags.json"
    manifest: "flags.json"
    strict: true

Use Comparison Results

- name: Compare manifests
  id: compare
  uses: open-feature/action@v1
  with:
    against: "https://api.flagprovider.com/flags.json"
    manifest: "flags.json"

- name: Notify Slack on differences
  if: steps.compare.outputs.has-differences == 'true'
  run: |
    curl -X POST -H 'Content-type: application/json' \
      --data '{"text":"🚨 Flag drift detected: ${{ steps.compare.outputs.summary }}"}' \
      ${{ secrets.SLACK_WEBHOOK }}

Multi-Environment Validation

name: Multi-Environment Flag Validation
on: [push, pull_request]

jobs:
  validate-environments:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        environment: [staging, production]
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Validate ${{ matrix.environment }}
        uses: open-feature/action@v1
        with:
          against: ${{ secrets[format('FLAG_URL_{0}', upper(matrix.environment))] }}
          manifest: "flags.json"
          auth-token: ${{ secrets[format('FLAG_TOKEN_{0}', upper(matrix.environment))] }}
          against-manifest-path: "${{ matrix.environment }}-flags.json"

Different Manifest Paths

- name: Compare different paths
  uses: open-feature/action@v1
  with:
    manifest: "new-location/flags.json"    # Current branch
    against: "old-location/flags.json"     # Base branch
    base-branch: "main"

Remote Provider Comparison

name: Compare Flag Providers
on: [push, workflow_dispatch]

jobs:
  compare-providers:
    runs-on: ubuntu-latest
    steps:
      - name: Compare LaunchDarkly vs Flagsmith
        uses: open-feature/action@v1
        with:
          manifest: "https://app.launchdarkly.com/api/v2/flags/export"
          against: "https://api.flagsmith.com/api/v1/environments/flags/"
          manifest-auth-token: ${{ secrets.LAUNCHDARKLY_TOKEN }}
          auth-token: ${{ secrets.FLAGSMITH_TOKEN }}
          
      - name: Compare staging vs production
        uses: open-feature/action@v1
        with:
          manifest: "https://staging-api.yourcompany.com/flags"
          against: "https://api.yourcompany.com/flags"
          manifest-auth-token: ${{ secrets.STAGING_API_TOKEN }}
          auth-token: ${{ secrets.PRODUCTION_API_TOKEN }}
          strict: true  # Fail if environments don't match

Manifest Format

This action supports OpenFeature manifest files in JSON or YAML format. The manifest format differs from basic feature flag configurations:

OpenFeature Manifest Format

{
  "flags": {
    "enableNewUI": {
      "state": "ENABLED",
      "variants": {
        "on": true,
        "off": false
      },
      "defaultVariant": "off",
      "targeting": {}
    },
    "featureToggle": {
      "state": "ENABLED", 
      "variants": {
        "control": "control-experience",
        "treatment": "new-experience"
      },
      "defaultVariant": "treatment",
      "targeting": {
        "if": [
          {
            "in": [
              {"var": "userId"},
              ["user-1", "user-2"]
            ]
          },
          "treatment",
          "control"
        ]
      }
    }
  }
}

Key Properties

  • state: "ENABLED" or "DISABLED" - whether the flag is active
  • variants: Object defining possible values for the flag
  • defaultVariant: Which variant to use when targeting doesn't match
  • targeting: JSON Logic rules for determining which variant to serve

For more details, see the OpenFeature Flag Configuration Specification.

Testing

This repository includes comprehensive tests to ensure reliability:

Test Types

  1. Integration Tests (pr-validation.yml)

    • Purpose: Real-world testing that simulates actual usage
    • What it tests: Both git comparison and remote source comparison
    • When it runs: On PRs that modify flags.json
  2. Feature Tests (test.yml)

    • Purpose: Test individual features and error handling
    • What it tests: Different manifest scenarios, CLI versions, error conditions
    • When it runs: On pushes and PRs
  3. Git Mode Tests (test-git-mode.yml)

    • Purpose: Specifically test git branch comparison functionality
    • What it tests: Branch detection, path mapping, minimal configuration
    • When it runs: On flag changes and workflow modifications

Running Tests Locally

You can test this action locally using act:

# Test the basic functionality
act -j test-action

# Test git mode functionality  
act -j test-git-mode

# Test with a specific event
act pull_request -e .github/workflows/pr-validation.yml

Test Scenarios Covered

  • Added flags: Local manifest has flags not in remote
  • Removed flags: Remote has flags not in local manifest
  • Modified flags: Same flags with different configurations
  • Identical manifests: No differences detected
  • Mixed changes: Complex scenarios with multiple types of changes
  • Error handling: Missing files, network issues, invalid manifests
  • CLI versions: Compatibility with different OpenFeature CLI versions
  • Authentication: Token-based access to protected sources

Troubleshooting

Common Issues

"CLI installation failed"

  1. Check if the specified CLI version exists in OpenFeature CLI releases
  2. Verify network connectivity to GitHub from your runner
  3. Try using cli-version: "latest" to get the most recent version

"Failed to pull manifest from against source"

  1. Verify the against URL is accessible and returns valid JSON/YAML

  2. Check if authentication is required:

    auth-token: ${{ secrets.FLAG_SOURCE_TOKEN }}
  3. Test the URL manually:

    curl -H "Authorization: Bearer YOUR_TOKEN" "your-against-url"

"Manifest file not found"

  1. Verify the manifest file exists at the specified path
  2. Check the file path is relative to the repository root
  3. For git comparisons, ensure the file exists in the target branch

Git Comparison Issues

  1. Ensure fetch-depth: 0 is set in your checkout action
  2. Verify the target branch exists and is accessible
  3. Check that the manifest path exists in both branches

Debug Mode

Enable debug logging by setting ACTIONS_STEP_DEBUG secret to true in your repository.

Security

Best Practices

Authentication Tokens

  1. Always use GitHub Secrets for authentication tokens:

    auth-token: ${{ secrets.FLAG_SOURCE_TOKEN }}  # ✅ Good
    auth-token: "abc123xyz"                       # ❌ Never hardcode
  2. Use environment-specific secrets:

    auth-token: ${{ secrets[format('TOKEN_{0}', matrix.environment)] }}
  3. Limit token permissions to read-only access when possible

  4. Rotate tokens regularly and update GitHub secrets accordingly

Workflow Security

  • Set appropriate permissions:

    permissions:
      contents: read
      pull-requests: write  # Only if using PR comments
  • Use specific action versions:

    uses: open-feature/[email protected]  # ✅ Specific version
    uses: open-feature/action@v1      # ❌ Moving tag
  • Pin CLI versions for reproducible builds:

    cli-version: "v0.3.6"  # ✅ Pinned version
    cli-version: "latest"  # ❌ May change unexpectedly

Handling Sensitive Data

  • Never commit flag configurations with production secrets
  • Use separate manifests for different environments
  • Audit flag changes just like code changes
  • Consider using encrypted manifests for sensitive configurations

Support & Community

Getting Help

Community

Contributing

We welcome contributions! Here's how to get started:

  1. Fork the repository and create a feature branch
  2. Make your changes and add tests if needed
  3. Test locally using the test workflows
  4. Submit a pull request with a clear description

Development Setup

# Clone your fork
git clone https://github.com/YOUR_USERNAME/action.git
cd action

# Test your changes
act -j test-action

Code Style

  • Use clear, descriptive commit messages
  • Follow existing shell script conventions
  • Add tests for new features
  • Update documentation for any changes

Support the Project

  • Star this repository to show your support
  • 🐛 Report bugs and suggest improvements
  • 📝 Contribute code, documentation, or examples
  • 🗣️ Share your experience with the community

Project Contributors

Thanks to all our contributors:

Pictures of the folks who have contributed to the project

Made with contrib.rocks.

Compatibility

GitHub Actions Runners

  • Supported: ubuntu-latest, ubuntu-22.04, ubuntu-20.04
  • Requirements: Go is pre-installed on GitHub-hosted runners

OpenFeature CLI Versions

  • Default: Latest stable release
  • Stable Versions: v0.3.6, v0.3.5, v0.3.4, etc. (CLI releases)
  • Version Selection: Use cli-version input to pin a specific version
  • Format: Version tags must include the v prefix (e.g., v0.3.6, not 0.3.6)

Manifest Formats

  • JSON (.json) - Recommended for most use cases
  • YAML (.yml, .yaml) - Good for complex configurations
  • Schema: Must conform to OpenFeature manifest schema

License

This project is licensed under the Apache License, Version 2.0 - see the LICENSE file for details.


Part of the OpenFeature ecosystem - A CNCF project

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •