A Ruby provider for OpenFeature that integrates with AWS AppConfig for feature flag management.
- ✅ Full OpenFeature specification compliance
- ✅ AWS AppConfig integration using the latest AppConfigData API
- ✅ Support for all data types (boolean, string, number, object) - Note: AWS AppConfig natively supports boolean, string, number, and arrays. Object types are handled by storing JSON strings and parsing them client-side.
- ✅ Multi-variant feature flags with targeting rules
- ✅ Advanced targeting operators (equals, contains, starts_with, etc.)
- ✅ Complex targeting conditions with multiple attributes
- ✅ Session management for efficient configuration retrieval
- ✅ Comprehensive error handling
- ✅ Type conversion and validation
- ✅ Unit tests with mocking
- ✅ Integration tests with AppConfig Agent
- ✅ Docker Compose setup for easy integration testing
- ✅ GitHub Actions CI with integration tests
Add this line to your application's Gemfile:
gem "openfeature-provider-ruby-aws-appconfig"And then execute:
bundle installThis provider supports two operation modes for AWS AppConfig integration:
Uses the latest AWS AppConfigData API directly. This mode provides:
- Free API calls: No charges for configuration retrieval
- Session management: Efficient configuration retrieval with session tokens
- Better performance: Optimized for frequent configuration access
- Future-proof: Uses the recommended AWS API
- Client-side targeting: Custom targeting logic evaluation
The provider automatically handles:
- Session creation and management
- Token refresh when sessions expire
- Error handling and retry logic
Uses AWS AppConfig Agent for configuration retrieval. This mode provides:
- Server-side targeting: More secure targeting rule evaluation
- Local endpoint: Efficient local HTTP API access
- Simplified authentication: Agent handles AWS credentials
- Network efficiency: Reduced AWS API calls
# Direct SDK mode (default)
provider = Openfeature::Provider::Ruby::Aws::Appconfig::Provider.new(
application: "my-application",
environment: "production",
configuration_profile: "feature-flags",
mode: :direct_sdk # or omit for default
)
# Agent mode
provider = Openfeature::Provider::Ruby::Aws::Appconfig::Provider.new(
application: "my-application",
environment: "production",
configuration_profile: "feature-flags",
mode: :agent,
agent_endpoint: "http://localhost:2772" # default endpoint
)require "open_feature/sdk"
require "openfeature/provider/ruby/aws/appconfig"
# Initialize the OpenFeature client
client = OpenFeature::SDK::Client.new
# Create and register the AWS AppConfig provider
provider = Openfeature::Provider::Ruby::Aws::Appconfig::Provider.new(
application: "my-application",
environment: "production",
configuration_profile: "feature-flags",
region: "us-east-1"
)
client.set_provider(provider)
# Resolve feature flags
is_feature_enabled = client.get_boolean_value("new-feature", false)
welcome_message = client.get_string_value("welcome-message", "Welcome!")
max_retries = client.get_number_value("max-retries", 3)
user_config = client.get_object_value("user-config", {})The provider supports AWS AppConfig's multi-variant feature flags with targeting rules:
# Create evaluation context with user attributes
context = OpenFeature::EvaluationContext.new(
targeting_key: "user-123",
attributes: {
"language" => "ja",
"country" => "JP",
"plan" => "premium",
"user_type" => "admin"
}
)
# Resolve multi-variant flags with context
personalized_message = client.get_string_value("welcome-message", "Hello", context)
discount_percentage = client.get_number_value("discount-percentage", 0, context)
user_theme = client.get_object_value("user-theme", {}, context)# Create evaluation context
context = OpenFeature::EvaluationContext.new(
targeting_key: "user-123",
attributes: {
"user_id" => "123",
"country" => "US",
"plan" => "premium"
}
)
# Resolve feature flags with context
is_feature_enabled = client.get_boolean_value("new-feature", false, context)bundle exec rake test_unitWe provide Docker Compose configurations for easy integration testing:
# Start integration test environment
./scripts/start-integration-tests.shThis script will:
- Check if Docker is running
- Verify port availability
- Let you choose between:
- Real AppConfig Agent (requires AWS credentials)
- Mock server (no AWS credentials required)
- Start the appropriate service
- Verify the service is responding
If you prefer to set up manually:
-
Install and start AppConfig Agent:
# Install AppConfig Agent (follow AWS documentation) # Start the agent with your AWS credentials
-
Configure test data in AWS AppConfig:
- Create application:
test-integration-app - Create environment:
test-integration-env - Create configuration profile:
test-integration-profile - Deploy test configuration (see
test/integration_test_helper.rbfor expected data)
- Create application:
-
Run integration tests:
bundle exec rake test_integration
# Start real AppConfig Agent (requires AWS credentials)
docker-compose up -d appconfig-agent
# Start mock server (no AWS credentials required)
docker-compose -f docker-compose.mock.yml up -d
# Stop services
docker-compose down
docker-compose -f docker-compose.mock.yml down
# View logs
docker-compose logs appconfig-agent
docker-compose -f docker-compose.mock.yml logs mock-appconfig-serverbundle exec rake test_all-
Unit Tests: Located in
test/openfeature/provider/ruby/aws/- Use mocking for AWS SDK calls
- Fast execution
- No external dependencies
- Test both Direct SDK mode and Agent mode with mocks
-
Integration Tests: Located in
test/openfeature/provider/ruby/aws/integration_test_provider.rb- Use real AppConfig Agent or mock server
- Test actual HTTP communication
- Require AppConfig Agent to be running
- Test real configuration retrieval and targeting
# Start the integration test environment
./scripts/start-integration-tests.sh
# Choose your preferred mode when prompted
# Then run the tests
bundle exec rake test_integration# For mock server (no AWS credentials needed)
docker-compose -f docker-compose.mock.yml up -d
# For real AppConfig Agent (requires AWS credentials)
export AWS_ACCESS_KEY_ID=your-access-key
export AWS_SECRET_ACCESS_KEY=your-secret-key
export AWS_REGION=us-east-1
docker-compose up -d appconfig-agent
# Run tests
bundle exec rake test_integrationThis project includes comprehensive CI/CD with GitHub Actions:
- RuboCop: Code style and quality checks
- Unit Tests: Multi-Ruby version testing (3.1, 3.2, 3.3, 3.4)
- Integration Tests: Automated integration testing with mock AppConfig server
The CI pipeline runs on every push and pull request:
- RuboCop: Code style validation
- Unit Tests: Tests across multiple Ruby versions
- Integration Tests:
- Sets up mock AppConfig server using Docker
- Runs integration tests against the mock server
- Verifies all functionality works with real HTTP communication
- Go to the Actions tab in the repository
- Each workflow run shows detailed results for all test stages
- Integration test logs include mock server setup and test execution details
To test the CI workflow locally:
# Run the same tests as CI
bundle exec rubocop
bundle exec rake test_unit
bundle exec rake test_integration{
"feature-flag": true,
"welcome-message": "Hello World!",
"max-retries": 5,
"user-config": "{\"theme\": \"dark\", \"language\": \"en\"}"
}Note: AWS AppConfig natively supports boolean, string, number, and arrays. For object types, store them as JSON strings in AWS AppConfig. The provider will automatically parse JSON strings into objects when using get_object_value().
The provider supports AWS AppConfig's multi-variant feature flag format:
{
"welcome-message": {
"variants": [
{ "name": "english", "value": "Hello World" },
{ "name": "japanese", "value": "こんにちは世界" },
{ "name": "spanish", "value": "Hola Mundo" }
],
"defaultVariant": "english",
"targetingRules": [
{
"conditions": [
{ "attribute": "language", "operator": "equals", "value": "ja" }
],
"variant": "japanese"
},
{
"conditions": [
{ "attribute": "language", "operator": "equals", "value": "es" }
],
"variant": "spanish"
}
]
},
"discount-percentage": {
"variants": [
{ "name": "none", "value": 0 },
{ "name": "standard", "value": 10 },
{ "name": "premium", "value": 20 },
{ "name": "vip", "value": 30 }
],
"defaultVariant": "none",
"targetingRules": [
{
"conditions": [
{ "attribute": "plan", "operator": "equals", "value": "premium" },
{ "attribute": "country", "operator": "equals", "value": "US" }
],
"variant": "premium"
},
{
"conditions": [
{ "attribute": "plan", "operator": "equals", "value": "vip" }
],
"variant": "vip"
}
]
}
}The provider supports the following targeting operators:
equals: Exact matchnot_equals: Not equalcontains: String containsnot_contains: String does not containstarts_with: String starts withends_with: String ends withgreater_than: Numeric comparisongreater_than_or_equal: Numeric comparisonless_than: Numeric comparisonless_than_or_equal: Numeric comparison
Each multi-variant flag should have:
variants: Array of variant objects withnameandvaluepropertiesdefaultVariant: Name of the default variant to use when no targeting rules matchtargetingRules(optional): Array of targeting rules
Each targeting rule contains:
conditions: Array of conditions (all must match for the rule to apply)variant: Name of the variant to return when conditions match
Each condition contains:
attribute: The attribute name from the evaluation contextoperator: The comparison operatorvalue: The value to compare against
- Create an application in AWS AppConfig
- Create an environment
- Create a configuration profile
- Create a configuration version with your JSON (simple or multi-variant)
- Deploy the configuration
The provider handles various error scenarios:
- Configuration Not Found: Returns error with appropriate message
- Throttling: Handles AWS throttling exceptions
- Parse Errors: Handles JSON parsing errors
- Type Conversion: Graceful handling of type mismatches
- Targeting Rule Errors: Falls back to default variant when targeting fails
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for your changes
- Run the test suite
- Submit a pull request
This gem is available as open source under the terms of the MIT License.
For issues and questions:
- Check the OpenFeature specification
- Review AWS AppConfig documentation
- Open an issue in this repository