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.
- For Different Users
- Use Cases
- Features
- Prerequisites
- Quick Start
- Inputs & Outputs
- Usage Examples
- Manifest Format
- Testing
- Troubleshooting
- Security
- Support & Community
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.
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.
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
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.
- 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
- 🔍 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
- GitHub Actions workflow
- Git repository with OpenFeature manifest file
- For git branch comparison:
fetch-depth: 0in 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.
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 branchCompare 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 }}| 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 |
The action automatically detects the comparison mode based on the against input:
- URL Mode: When
againstcontains a protocol (e.g.,http://,https://,git://,ssh://,file://) or Git SSH format - Git Mode: When
againstis 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-branchis provided: Uses the specified branch - Otherwise: Defaults to
mainbranch
| 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 |
- name: Validate flag changes
uses: open-feature/action@v1
with:
manifest: "flags.json"- name: Compare against develop
uses: open-feature/action@v1
with:
manifest: "flags.json"
base-branch: "develop"- 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 }}- 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 }}- name: Enforce flag sync
uses: open-feature/action@v1
with:
against: "https://api.flagprovider.com/flags.json"
manifest: "flags.json"
strict: true- 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 }}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"- 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"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 matchThis action supports OpenFeature manifest files in JSON or YAML format. The manifest format differs from basic feature flag configurations:
{
"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"
]
}
}
}
}state:"ENABLED"or"DISABLED"- whether the flag is activevariants: Object defining possible values for the flagdefaultVariant: Which variant to use when targeting doesn't matchtargeting: JSON Logic rules for determining which variant to serve
For more details, see the OpenFeature Flag Configuration Specification.
This repository includes comprehensive tests to ensure reliability:
-
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
-
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
-
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
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- ✅ 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
- Check if the specified CLI version exists in OpenFeature CLI releases
- Verify network connectivity to GitHub from your runner
- Try using
cli-version: "latest"to get the most recent version
-
Verify the
againstURL is accessible and returns valid JSON/YAML -
Check if authentication is required:
auth-token: ${{ secrets.FLAG_SOURCE_TOKEN }}
-
Test the URL manually:
curl -H "Authorization: Bearer YOUR_TOKEN" "your-against-url"
- Verify the manifest file exists at the specified path
- Check the file path is relative to the repository root
- For git comparisons, ensure the file exists in the target branch
- Ensure
fetch-depth: 0is set in your checkout action - Verify the target branch exists and is accessible
- Check that the manifest path exists in both branches
Enable debug logging by setting ACTIONS_STEP_DEBUG secret to true in your repository.
-
Always use GitHub Secrets for authentication tokens:
auth-token: ${{ secrets.FLAG_SOURCE_TOKEN }} # ✅ Good auth-token: "abc123xyz" # ❌ Never hardcode
-
Use environment-specific secrets:
auth-token: ${{ secrets[format('TOKEN_{0}', matrix.environment)] }}
-
Limit token permissions to read-only access when possible
-
Rotate tokens regularly and update GitHub secrets accordingly
-
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
- 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
- 📖 Documentation: OpenFeature Documentation
- 🐛 Bug Reports: GitHub Issues
- 💬 Community Chat: CNCF Slack #openfeature
- 🛠️ CLI Issues: OpenFeature CLI Repository
-
CNCF Slack Channels:
- #openfeature - General discussion
- #openfeature-cli - CLI-specific topics
-
Regular Meetings: Community Calls
-
Social Media:
- Twitter: @openfeature
- LinkedIn: OpenFeature
We welcome contributions! Here's how to get started:
- Fork the repository and create a feature branch
- Make your changes and add tests if needed
- Test locally using the test workflows
- Submit a pull request with a clear description
# Clone your fork
git clone https://github.com/YOUR_USERNAME/action.git
cd action
# Test your changes
act -j test-action- Use clear, descriptive commit messages
- Follow existing shell script conventions
- Add tests for new features
- Update documentation for any changes
- ⭐ Star this repository to show your support
- 🐛 Report bugs and suggest improvements
- 📝 Contribute code, documentation, or examples
- 🗣️ Share your experience with the community
Thanks to all our contributors:
Made with contrib.rocks.
- Supported:
ubuntu-latest,ubuntu-22.04,ubuntu-20.04 - Requirements: Go is pre-installed on GitHub-hosted runners
- Default: Latest stable release
- Stable Versions: v0.3.6, v0.3.5, v0.3.4, etc. (CLI releases)
- Version Selection: Use
cli-versioninput to pin a specific version - Format: Version tags must include the
vprefix (e.g.,v0.3.6, not0.3.6)
- JSON (
.json) - Recommended for most use cases - YAML (
.yml,.yaml) - Good for complex configurations - Schema: Must conform to OpenFeature manifest schema
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