https://github.com/sinashahoveisi/featureflags
A robust backend service for managing feature flags with dependency support, audit logging, and circular dependency detection.
https://github.com/sinashahoveisi/featureflags
feature-flag feature-flagging go golang
Last synced: 11 months ago
JSON representation
A robust backend service for managing feature flags with dependency support, audit logging, and circular dependency detection.
- Host: GitHub
- URL: https://github.com/sinashahoveisi/featureflags
- Owner: sinashahoveisi
- Created: 2025-07-25T19:28:36.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2025-07-25T22:41:52.000Z (11 months ago)
- Last Synced: 2025-07-26T03:25:31.569Z (11 months ago)
- Topics: feature-flag, feature-flagging, go, golang
- Language: Go
- Homepage:
- Size: 65.4 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# FeatureFlags Service
A robust backend service for managing feature flags with dependency support, audit logging, and circular dependency detection.
## Features
- ✅ **Feature Flag Management**: Create, enable, disable, and list feature flags
- ✅ **Dependency Support**: Flags can depend on other flags; dependent flags can only be enabled if all dependencies are active
- ✅ **Circular Dependency Detection**: Prevents creation of circular dependencies
- ✅ **Cascading Disables**: When a flag is disabled, all dependent flags are automatically disabled
- ✅ **Comprehensive Audit Logging**: Track all operations with timestamps, actors, and reasons
- ✅ **Graceful Shutdown**: Clean shutdown with configurable timeout
- ✅ **Structured Logging**: JSON-structured logs with configurable levels
- ✅ **Input Validation**: Comprehensive request validation with detailed error messages
- ✅ **Database Migrations**: Automated database schema management
- ✅ **Docker Support**: Fully containerized with Docker Compose
- ✅ **Comprehensive Tests**: Unit and integration tests with coverage reporting
- ✅ **Swagger Documentation**: Interactive API documentation with configurable enable/disable
## Architecture
The project follows a clean architecture pattern with clear separation of concerns:
```
featureflags/
├── cmd/ # Application entry point
├── config/ # Configuration management
├── entity/ # Domain models
├── repository/ # Data access layer
├── service/ # Business logic layer
├── controller/ # HTTP handlers
├── handler/ # Route registration
├── validator/ # Input validation
├── test/ # Test helpers
├── migrations/ # Database migrations
├── pkg/
│ └── logger/ # Structured logging
├── scripts/ # Utility scripts
└── docker-compose.yml # Container orchestration
```
## API Endpoints
### Health Check
- `GET /health` - Service health status
### Documentation
- `GET /swagger/index.html` - Interactive Swagger API documentation (if enabled)
### Flag Management
- `POST /api/v1/flags` - Create a new flag
- `GET /api/v1/flags` - List all flags
- `GET /api/v1/flags/:id` - Get a specific flag
- `POST /api/v1/flags/:id/toggle` - Enable/disable a flag
- `GET /api/v1/flags/:id/audit` - Get audit logs for a flag
## Example API Usage
### Create a Flag
```bash
curl -X POST http://localhost:8080/api/v1/flags \
-H "Content-Type: application/json" \
-H "X-Actor: user123" \
-d '{
"name": "checkout_v2",
"dependencies": [1, 2]
}'
```
### Enable a Flag
```bash
curl -X POST http://localhost:8080/api/v1/flags/1/toggle \
-H "Content-Type: application/json" \
-H "X-Actor: user123" \
-d '{
"enable": true,
"reason": "Ready for production"
}'
```
### Error Response for Missing Dependencies
```json
{
"error": "Missing active dependencies",
"missing_dependencies": ["auth_v2", "user_profile_v2"]
}
```
## Configuration
The service supports configuration via environment variables:
| Variable | Default | Description |
|----------|---------|-------------|
| `HTTP_SERVER_PORT` | `8080` | HTTP server port |
| `DATABASE_HOST` | `db` | PostgreSQL host |
| `DATABASE_PORT` | `5432` | PostgreSQL port |
| `DATABASE_USER` | `featureflags` | Database user |
| `DATABASE_PASSWORD` | `featureflags` | Database password |
| `DATABASE_NAME` | `featureflags` | Database name |
| `LOGGER_LEVEL` | `info` | Log level (debug, info, warn, error) |
| `LOGGER_MODE` | `production` | Log mode (development, production) |
| `APPLICATION_GRACEFUL_SHUTDOWN_TIMEOUT` | `30s` | Graceful shutdown timeout |
| `SWAGGER_ENABLED` | `true` | Enable/disable Swagger documentation |
## Running the Service
### Using Docker Compose (Recommended)
1. **Start the service:**
```bash
docker-compose up --build
```
2. **Run tests:**
```bash
docker-compose run --rm test
```
3. **Stop the service:**
```bash
docker-compose down
```
### Development with Hot Reload
For the best development experience, use the development environment with hot reload:
```bash
# Start development environment (recommended)
make dev
# or
./scripts/dev.sh
# The service will be available at:
# - API: http://localhost:8080
# - Swagger: http://localhost:8080/swagger/index.html
```
**Development Features:**
- 🔥 **Hot Reload**: Automatic restart on code changes using [Air](https://github.com/cosmtrek/air)
- 🐛 **Debug Logging**: Enhanced logging for development
- 📚 **Swagger Enabled**: Interactive API documentation
- 🗄️ **PostgreSQL Included**: Database automatically configured
- 📁 **Live Code Mounting**: Edit code directly, see changes instantly
**Development Commands:**
```bash
make dev # Start development environment
make dev-bg # Start in background
make dev-logs # View logs
make dev-stop # Stop development environment
make dev-test # Run tests in dev environment
```
### Local Development (Alternative)
If you prefer to run without Docker:
1. **Prerequisites:**
- Go 1.23+
- PostgreSQL 15+
- Air (for hot reload): `make install-air`
2. **Setup database:**
```bash
createdb featureflags
```
3. **Run with hot reload:**
```bash
make air-local
```
4. **Or run normally:**
```bash
make run
```
## Testing
The project includes comprehensive automated tests covering all core functionality and example scenarios from the requirements:
### Running Tests
```bash
# Run all tests with Docker Compose
docker-compose run --rm test
# Run example scenario tests
docker-compose run --rm scenario-test
# Run tests locally (requires PostgreSQL)
./scripts/test.sh
# Run scenario tests locally
./scripts/run-scenario-tests.sh
# Run specific test suites
go test -v ./service/... # Service layer unit tests
go test -v ./test/... # Integration tests
go test -v -run "TestExampleScenario" ./test/ # Example scenarios only
```
### Example Scenarios Tested
The test suite validates all example scenarios from the requirements:
1. **Scenario 1: Dependency Validation**
- `checkout_v2` depends on `auth_v2` and `user_profile_v2`
- Can only be enabled after both dependencies are active
2. **Scenario 2: Missing Dependency Error Format**
- Returns exact error format: `{"error": "Missing active dependencies", "missing_dependencies": ["auth_v2"]}`
3. **Scenario 3: Cascading Disable**
- When `auth_v2` is disabled, automatically disables `checkout_v2` and dependent flags
- Logs cascading changes with `system` actor and `cascade_disable` action
4. **Scenario 4: Circular Dependency Detection**
- Prevents creation of flags with circular dependencies
- Returns clear error messages for circular dependency attempts
5. **Complex Integration Scenario**
- Multi-service dependency tree with 7+ flags
- Tests realistic microservice dependency patterns
- Validates cascading behavior across complex dependency chains
### Test Coverage
Tests cover the following functionality:
- ✅ Flag creation with and without dependencies
- ✅ Dependency validation and missing dependency errors
- ✅ Cascading disable functionality with audit logging
- ✅ Circular dependency detection and prevention
- ✅ Flag toggling and status management
- ✅ Audit log creation and retrieval
- ✅ Input validation and error handling
- ✅ Database operations and transactions
- ✅ HTTP API endpoints and error responses
- ✅ Integration testing with full application stack
### CI/CD Testing
The project includes automated testing in both GitLab CI and GitHub Actions:
- **Unit Tests**: Run on every commit and pull request
- **Integration Tests**: Full application testing with PostgreSQL
- **Scenario Tests**: Validate all requirement examples
- **Security Scanning**: Vulnerability detection with Trivy
- **Coverage Reports**: Generate and upload test coverage
- **Docker Image Testing**: Test built images before deployment
## Database Schema
The service uses PostgreSQL with the following tables:
- **flags**: Store flag information (id, name, status, timestamps)
- **flag_dependencies**: Store flag dependency relationships
- **audit_logs**: Store audit trail of all operations
- **schema_migrations**: Track applied database migrations
## Graceful Shutdown
The service implements graceful shutdown:
- Listens for SIGTERM/SIGINT signals
- Stops accepting new requests
- Completes existing requests within timeout
- Closes database connections cleanly
## Logging
Structured JSON logging with configurable levels:
- **Development mode**: Human-readable format with colors
- **Production mode**: JSON format optimized for log aggregation
- **Request logging**: Automatic HTTP request/response logging
- **Error tracking**: Detailed error context and stack traces
## Example Scenarios
### Scenario 1: Basic Flag Management
```bash
# Create a simple flag
curl -X POST localhost:8080/api/v1/flags \
-H "Content-Type: application/json" \
-d '{"name": "simple_feature"}'
# Enable the flag
curl -X POST localhost:8080/api/v1/flags/1/toggle \
-H "Content-Type: application/json" \
-d '{"enable": true, "reason": "Feature is ready"}'
```
### Scenario 2: Dependency Management
```bash
# Create base flags
curl -X POST localhost:8080/api/v1/flags \
-d '{"name": "auth_v2"}'
curl -X POST localhost:8080/api/v1/flags \
-d '{"name": "user_profile_v2"}'
# Create dependent flag
curl -X POST localhost:8080/api/v1/flags \
-d '{"name": "checkout_v2", "dependencies": [1, 2]}'
# Try to enable checkout_v2 (will fail - dependencies not enabled)
curl -X POST localhost:8080/api/v1/flags/3/toggle \
-d '{"enable": true, "reason": "Launch checkout v2"}'
# Response: {"error": "Missing active dependencies", "missing_dependencies": ["auth_v2", "user_profile_v2"]}
# Enable dependencies first
curl -X POST localhost:8080/api/v1/flags/1/toggle \
-d '{"enable": true, "reason": "Auth v2 ready"}'
curl -X POST localhost:8080/api/v1/flags/2/toggle \
-d '{"enable": true, "reason": "User profile ready"}'
# Now enable checkout_v2 (will succeed)
curl -X POST localhost:8080/api/v1/flags/3/toggle \
-d '{"enable": true, "reason": "All dependencies ready"}'
```
### Scenario 3: Cascade Disable
```bash
# Disable auth_v2 (will cascade disable checkout_v2)
curl -X POST localhost:8080/api/v1/flags/1/toggle \
-d '{"enable": false, "reason": "Auth issues detected"}'
# Check audit logs to see cascade actions
curl localhost:8080/api/v1/flags/3/audit
```
## Development
### Adding New Features
1. **Add entity models** in `entity/`
2. **Implement repository methods** in `repository/`
3. **Add business logic** in `service/`
4. **Create HTTP handlers** in `controller/`
5. **Add validation** in `validator/`
6. **Write tests** in `*_test.go` files
7. **Update migrations** in `migrations/`
### Code Quality
- Follow Go best practices and idioms
- Maintain test coverage above 80%
- Use structured logging for observability
- Implement proper error handling
- Document public APIs
## Contributing
1. Fork the repository
2. Create a feature branch
3. Add tests for new functionality
4. Ensure all tests pass
5. Submit a pull request
## Swagger Documentation
The service includes interactive Swagger/OpenAPI documentation that can be enabled or disabled via configuration.
### Accessing Swagger UI
When enabled (default), you can access the interactive API documentation at:
- **Local Development**: http://localhost:8080/swagger/index.html
- **Docker**: http://localhost:8080/swagger/index.html
### Configuration
Control Swagger documentation via environment variables:
```bash
# Enable/disable Swagger (default: true)
SWAGGER_ENABLED=true
```
### Disabling Swagger in Production
For production environments, you may want to disable Swagger:
```bash
# In your .env or environment
SWAGGER_ENABLED=false
```
The Swagger documentation includes:
- **Interactive API Testing**: Test endpoints directly from the browser
- **Request/Response Examples**: See example payloads and responses
- **Schema Documentation**: Detailed information about data models
- **Error Response Examples**: Including dependency error formats
## CI/CD Pipeline
The project includes comprehensive CI/CD pipelines for both GitLab CI and GitHub Actions.
### Pipeline Features
- ✅ **Automated Testing**: Unit, integration, and scenario tests
- ✅ **Security Scanning**: Vulnerability detection with Trivy
- ✅ **Docker Image Building**: Multi-platform (amd64/arm64) builds
- ✅ **Container Registry**: Automatic image publishing with git commit hash
- ✅ **Coverage Reports**: Test coverage analysis and reporting
- ✅ **Integration Testing**: Full application testing with Docker Compose
- ✅ **Deployment Automation**: Staging and production deployment workflows
### GitLab CI Pipeline
The `.gitlab-ci.yml` includes:
```yaml
stages:
- test # Run tests with PostgreSQL
- build # Build Docker images
- publish # Push to GitLab Container Registry
```
**Image Tags:**
- `registry.gitlab.com/project/featureflags:latest` (main branch)
- `registry.gitlab.com/project/featureflags:${CI_COMMIT_SHA}` (commit hash)
- `registry.gitlab.com/project/featureflags:${CI_COMMIT_REF_SLUG}` (branch name)
### GitHub Actions Pipeline
The `.github/workflows/ci.yml` includes:
```yaml
jobs:
- test # Unit and integration tests
- build # Docker image building
- publish # Push to GitHub Container Registry
- security-scan # Trivy vulnerability scanning
- integration-test # Full application testing
- deploy-staging # Staging deployment
- deploy-production # Production deployment
```
**Image Tags:**
- `ghcr.io/username/featureflags:latest` (main branch)
- `ghcr.io/username/featureflags:${GITHUB_SHA}` (commit hash)
- `ghcr.io/username/featureflags:main-${GITHUB_SHA}` (branch-commit)
### Database Configuration for Testing
Both pipelines support the `POSTGRES_DB_test` naming convention:
```bash
# Environment variables
POSTGRES_DB=featureflags # Base database name
TEST_DB_NAME=featureflags_test # Test database name (auto-generated)
```
### Running CI/CD Locally
```bash
# Test the full CI pipeline locally
docker-compose run --rm scenario-test
# Test image building
docker build -t featureflags:test .
# Test with specific commit hash
docker build -t featureflags:$(git rev-parse --short HEAD) .
```
## License
This project is licensed under the MIT License.