Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/workflows/pr-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,26 @@ permissions:
checks: write

jobs:
format-check:
name: check formatting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
- name: Check Go formatting
run: |
unformatted=$(go fmt ./...)
if [ -n "$unformatted" ]; then
echo "::error ::The following files need formatting. Please run 'go fmt ./...' or 'make fmt'"
echo "$unformatted"
exit 1
fi
echo "✅ All Go files are properly formatted"

golangci:
name: lint
runs-on: ubuntu-latest
Expand Down
43 changes: 38 additions & 5 deletions .github/workflows/pr-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ jobs:
- name: Run tests
run: go test ./...

docs-check:
name: Validate docs
generated-files-check:
name: Validate generated files
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -36,11 +36,44 @@ jobs:
with:
go-version-file: 'go.mod'

- run: make generate-docs
- name: Check no diff
- name: Generate OpenAPI client
run: make generate-api
- name: Check OpenAPI client is up-to-date
run: |
if [ ! -z "$(git status --porcelain internal/api/client/)" ]; then
echo "::error ::OpenAPI client generation produced diff. Run 'make generate-api' and commit results."
git diff internal/api/client/
exit 1
fi

- name: Generate documentation
run: make generate-docs
- name: Check documentation is up-to-date
run: |
if [ ! -z "$(git status --porcelain docs/)" ]; then
echo "::error ::Documentation generation produced diff. Run 'make generate-docs' and commit results."
git diff docs/
exit 1
fi

- name: Generate schema
run: make generate-schema
- name: Check schema is up-to-date
run: |
if [ ! -z "$(git status --porcelain schema/)" ]; then
echo "::error ::Schema generation produced diff. Run 'make generate-schema' and commit results."
git diff schema/
exit 1
fi

- name: Final check for any uncommitted changes
run: |
if [ ! -z "$(git status --porcelain)" ]; then
echo "::error file=Makefile::Doc generation produced diff. Run 'make generate-docs' and commit results."
echo "::error ::Generation produced uncommitted changes. Please run 'make generate' and commit all changes."
echo "Changed files:"
git status --porcelain
echo ""
echo "Diff:"
git diff
exit 1
fi
Expand Down
122 changes: 120 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,71 @@

Thank you for your interest in contributing to the OpenFeature CLI! This document provides guidelines and instructions to help you get started with contributing to the project. Whether you're fixing a bug, adding a new feature, or improving documentation, your contributions are greatly appreciated.

## Development Setup

1. **Prerequisites**:
- Go 1.23 or later
- Make
- golangci-lint (will be auto-installed by make commands)

2. **Clone the repository**:
```bash
git clone https://github.com/open-feature/cli.git
cd cli
```

3. **Build the project**:
```bash
make build
```

4. **Run tests**:
```bash
make test
```

5. **Run all CI checks locally**:
```bash
make ci
```

This will format code, run linting, execute tests, and verify all generated files are up-to-date.

## Available Make Commands

The project includes a comprehensive Makefile with the following commands:

```bash
make help # Show all available commands
make build # Build the CLI binary
make install # Install the CLI to your system
make lint # Run golangci-lint
make lint-fix # Run golangci-lint with auto-fix
make test # Run unit tests
make test-integration # Run all integration tests
make generate # Generate all code (API clients, docs, schema)
make generate-api # Generate API clients from OpenAPI specs
make generate-docs # Generate documentation
make generate-schema # Generate schema
make verify-generate # Check if all generated files are up to date
make fmt # Format Go code
make ci # Run all CI checks locally (fmt, lint, test, verify-generate)
```

### Before Submitting a PR

Run the following command to ensure your changes will pass CI:

```bash
make ci
```

This command will:
- Format your code
- Run the linter
- Execute all tests
- Verify all generated files are up-to-date

## Contributing New Generators

We welcome contributions for new generators to extend the functionality of the OpenFeature CLI. Below are the steps to contribute a new generator:
Expand Down Expand Up @@ -62,6 +127,54 @@ make test-csharp-dagger

For more information on the integration testing framework, see [Integration Testing](./docs/integration-testing.md).

## Contributing to Remote Operations

The CLI uses an OpenAPI-driven architecture for remote flag synchronization. If you're contributing to the remote operations (pull/push commands) or API specifications:

### Modifying the OpenAPI Specification

1. **Edit the specification**: Update the OpenAPI spec at `api/v0/sync.yaml`
2. **Regenerate the client**: Run `make generate-api` to regenerate the client code
3. **Update the wrapper**: Modify `internal/api/sync/client.go` if needed
4. **Test your changes**: Add or update tests in `internal/api/sync/`

### Adding New Remote Operations

1. **Define in OpenAPI**: Add the new operation to `api/v0/sync.yaml`
2. **Regenerate**: Run `make generate-api`
3. **Implement wrapper method**: Add the method in `internal/api/sync/client.go`
4. **Create/update command**: Add or modify commands in `internal/cmd/`
5. **Add tests**: Include unit tests and integration tests
6. **Update documentation**: Update relevant documentation including command docs

### API Compatibility

When modifying the OpenAPI specification:

- **Backwards Compatibility**: Ensure changes don't break existing integrations
- **Versioning**: Use proper API versioning (currently v0)
- **Documentation**: Update the specification descriptions and examples
- **Schema Validation**: Ensure all request/response schemas are properly defined

For detailed information about the OpenAPI client pattern, see the [OpenAPI Client Pattern documentation](./docs/openapi-client-pattern.md).

## CI/CD Pipeline

The project uses GitHub Actions for continuous integration. The following workflows run automatically:

### PR Validation Workflow
- **Generated Files Check**: Ensures all generated files (OpenAPI client, docs, schema) are up-to-date
- **Format Check**: Verifies all Go code is properly formatted
- **Tests**: Runs all unit tests
- **Integration Tests**: Runs language-specific integration tests

### PR Test Workflow
- **Unit Tests**: Runs all unit tests
- **Integration Tests**: Runs Dagger-based integration tests for all supported languages

### PR Lint Workflow
- **golangci-lint**: Runs comprehensive linting with golangci-lint v1.64

## Setting Up Lefthook

To streamline the setup of Git hooks for this project, we utilize [Lefthook](https://github.com/evilmartians/lefthook). Lefthook automates pre-commit and pre-push checks, ensuring consistent enforcement of best practices across the team. These checks include code formatting, documentation generation, and running tests.
Expand Down Expand Up @@ -92,8 +205,13 @@ The pre-commit hook is configured to run the following check:

The pre-push hook is configured to run the following checks:

1. **Documentation Generation**: Runs `make generate-docs` to ensure documentation is up-to-date. If any changes are detected, the push will be blocked until the changes are committed.
2. **Tests**: Executes `make test` to verify that all tests pass. If any tests fail, the push will be blocked.
1. **Generated Files Check**: Verifies all generated files are up-to-date:
- **OpenAPI Client**: Ensures `internal/api/client/` is current with the OpenAPI spec
- **Documentation**: Ensures `docs/` is current with the latest command structure
- **Schema**: Ensures `schema/` files are up-to-date
2. **Tests**: Executes `make test` to verify that all tests pass

If any of these checks fail, the push will be blocked. Run `make generate` to update all generated files and commit the changes.

### Running Hooks Manually

Expand Down
43 changes: 43 additions & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,53 @@ Benefits of the code generation approach:
- **Modular and Extensible Design**: Create a format that allows for future extensions and modularization of flags.
- **Language Agnostic**: Support multiple programming languages through a common flag manifest format.
- **Provider Independence**: Work with any feature flag provider that can be adapted to the OpenFeature API.
- **Remote Flag Synchronization**: Enable bidirectional synchronization with remote flag management services through a standardized API.

## Non-Goals

- **Full Provider Integration**: The initial scope does not include creating tools to convert provider-specific configurations to the new flag manifest format.
- **Validation of Flag Configs**: The project will not initially focus on validating flag configurations for consistency with the flag manifest.
- **General-Purpose Configuration**: The project will not aim to create a general-purpose configuration tool for feature flags beyond the scope of the code generation tool.
- **Runtime Flag Management**: The CLI is not intended to replace provider SDKs for runtime flag evaluation.

## Architecture Patterns

### OpenAPI Client Pattern

The CLI uses an OpenAPI-driven architecture for all remote operations. This pattern provides several benefits:

#### Benefits

1. **Type Safety**: Generated clients from OpenAPI specs ensure compile-time checking of API requests and responses
2. **Self-Documenting**: The OpenAPI specification serves as both implementation guide and documentation
3. **Provider Agnostic**: Any service implementing the Manifest Management API can integrate with the CLI
4. **Maintainability**: Changes to the API are made in one place (the spec) and propagate to all consumers
5. **Extensibility**: New endpoints and operations can be added without breaking existing functionality

#### Implementation

The pattern follows this architecture:

```
OpenAPI Spec (api/v0/sync.yaml)
Generated Client (internal/api/client/*.gen.go)
Wrapper Client (internal/api/sync/client.go)
CLI Commands (internal/cmd/pull.go, push.go)
```

For detailed implementation guidelines, see the [OpenAPI Client Pattern documentation](./docs/openapi-client-pattern.md).

### Code Generation Pattern

The CLI generates strongly-typed flag accessors for multiple languages. This pattern:

1. **Parses** the flag manifest JSON/YAML
2. **Validates** the flag configurations against the schema
3. **Transforms** the data into language-specific structures
4. **Generates** code using Go templates
5. **Formats** the output according to language conventions

Each generator follows a consistent interface, making it easy to add support for new languages.
36 changes: 26 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ help:
@echo " generate-api - Generate API clients from OpenAPI specs"
@echo " generate-docs - Generate documentation"
@echo " generate-schema - Generate schema"
@echo " verify-generate - Check if generated files are up to date"
@echo " verify-generate - Check if all generated files are up to date"
@echo " fmt - Format Go code"
@echo " ci - Run all CI checks locally (lint, test, verify-generate)"
@echo " ci - Run all CI checks locally (fmt, lint, test, verify-generate)"

.PHONY: build
build:
Expand Down Expand Up @@ -110,15 +110,31 @@ lint-fix:
@echo "Linting with auto-fix completed successfully!"

.PHONY: verify-generate
verify-generate: generate
@echo "Checking for uncommitted changes after generation..."
@if [ ! -z "$$(git status --porcelain)" ]; then \
echo "Error: Generation produced diff. Please run 'make generate' and commit the results."; \
git diff; \
verify-generate:
@echo "Checking if all generated files are up-to-date..."
@make generate-api > /dev/null 2>&1
@if [ ! -z "$$(git diff --name-only internal/api/client/)" ]; then \
echo "❌ OpenAPI client needs regeneration"; \
echo " Run: make generate-api"; \
git diff --stat internal/api/client/; \
exit 1; \
fi
@echo "All generated files are up to date!"
@make generate-docs > /dev/null 2>&1
@if [ ! -z "$$(git diff --name-only docs/)" ]; then \
echo "❌ Documentation needs regeneration"; \
echo " Run: make generate-docs"; \
git diff --stat docs/; \
exit 1; \
fi
@make generate-schema > /dev/null 2>&1
@if [ ! -z "$$(git diff --name-only schema/)" ]; then \
echo "❌ Schema needs regeneration"; \
echo " Run: make generate-schema"; \
git diff --stat schema/; \
exit 1; \
fi
@echo "✅ All generated files are up-to-date!"

.PHONY: ci
ci: lint test verify-generate
@echo "All CI checks passed successfully!"
ci: fmt lint test verify-generate
@echo "All CI checks passed successfully!"
Loading
Loading