Skip to content
Closed
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
97 changes: 91 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,17 +1,102 @@
# Binaries for programs and plugins
# =============================================================================
# Go
# =============================================================================

# Binaries
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
# Test binaries
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
# Coverage output
*.out
coverage.out

# Go workspace
go.work
go.work.sum

# =============================================================================
# Project
# =============================================================================

# Environment files (may contain secrets)
*.env
.env.local

# Task runner cache
.task/

# Split SDK local files
.split
.splits

# =============================================================================
# IDE - JetBrains (GoLand, IntelliJ)
# =============================================================================

.idea/*
!.idea/codeStyles/
!.idea/runConfigurations/

*.iml
*.ipr
*.iws

# =============================================================================
# IDE - VS Code
# =============================================================================

.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets

.history/
*.vsix

# =============================================================================
# OS - macOS
# =============================================================================

.DS_Store
.AppleDouble
.LSOverride
._*
.Spotlight-V100
.Trashes

# =============================================================================
# OS - Windows
# =============================================================================

Thumbs.db
ehthumbs.db
Desktop.ini
$RECYCLE.BIN/
*.lnk

# =============================================================================
# OS - Linux
# =============================================================================

*~
.directory
.Trash-*
.nfs*

# Dependency directories (remove the comment below to include it)
# vendor/
# =============================================================================
# Git
# =============================================================================

.idea/
*.orig
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
139 changes: 139 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# golangci-lint configuration for Split OpenFeature Provider
# Gold Standard Linting Configuration

version: "2"

run:
timeout: 5m
tests: true
modules-download-mode: readonly

linters:
enable:
# Enabled by default
- errcheck # Check for unchecked errors
- govet # Go vet
- ineffassign # Detect ineffectual assignments
- staticcheck # Static analysis
- unused # Check for unused code

# Additional recommended linters
- misspell # Check for misspelled words
- unconvert # Remove unnecessary type conversions
- unparam # Report unused function parameters
- prealloc # Find slice declarations that could be preallocated
- goconst # Find repeated strings that could be constants
- gocyclo # Cyclomatic complexity
- gocognit # Cognitive complexity
- dupl # Code clone detection
- gocritic # Comprehensive checks
- revive # Fast, extensible linter
- gosec # Security checks
- bodyclose # Check HTTP response bodies are closed
- noctx # Detect http.Request without context.Context
- rowserrcheck # Check sql.Rows.Err is checked
- sqlclosecheck # Check sql.Rows and sql.Stmt are closed
- errorlint # Error wrapping checks
- exhaustive # Check exhaustiveness of enum switch statements

exclusions:
paths:
- examples
- test
- '.*\.pb\.go$'

rules:
# Exclude all linters from test files - focus on production code quality
- path: '(.+)_test\.go'
linters:
- errcheck
- gocyclo
- gocognit
- dupl
- gocritic
- gosec
- goconst
- govet
- revive
- staticcheck
- misspell
- unconvert
- unparam
- prealloc

settings:
errcheck:
check-type-assertions: true
check-blank: true

govet:
enable-all: true
disable:
- shadow # Too many false positives

gocyclo:
min-complexity: 15

gocognit:
min-complexity: 30

dupl:
threshold: 100

goconst:
min-len: 3
min-occurrences: 3

misspell:
locale: US

staticcheck:
checks: [ "all" ]

revive:
confidence: 0.8
rules:
- name: blank-imports
- name: context-as-argument
- name: context-keys-type
- name: dot-imports
- name: error-return
- name: error-strings
- name: error-naming
- name: exported
- name: if-return
- name: increment-decrement
- name: var-declaration
- name: package-comments
- name: range
- name: receiver-naming
- name: time-naming
- name: unexported-return
- name: indent-error-flow
- name: errorf
- name: empty-block
- name: superfluous-else
- name: unused-parameter
- name: unreachable-code
- name: redefines-builtin-id

gosec:
severity: medium
confidence: medium

gocritic:
enabled-tags:
- diagnostic
- performance
- style
disabled-checks:
- commentedOutCode
- whyNoLint

exhaustive:
default-signifies-exhaustive: true

prealloc:
simple: true
range-loops: true
for-loops: false
14 changes: 14 additions & 0 deletions .mockery.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Mockery v3.6.4 configuration
# See: https://github.com/vektra/mockery/blob/v3/docs/configuration.md
all: false
template: testify
formatter: goimports
packages:
github.com/splitio/split-openfeature-provider-go/v2:
interfaces:
Client:
config:
dir: "{{.InterfaceDir}}"
filename: "mock_client_test.go"
pkgname: "split"
structname: "MockClient"
125 changes: 125 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.0.0] - 2025-11-24

**Complete architectural rewrite** with modern SDK support, production-grade lifecycle management, and critical bug
fixes.

See [MIGRATION.md](MIGRATION.md) for upgrade instructions.

### Breaking Changes

#### SDK Requirements

- **Split Go SDK upgraded to v6** (import: `github.com/splitio/go-client/v6`)
- **OpenFeature Go SDK upgraded to v1** (import: `github.com/open-feature/go-sdk/openfeature`)

#### API Changes

- **All evaluation methods now require `context.Context` as first parameter**
- **`Client()` renamed to `Factory()`** for Split SDK factory access
- **`NewWithClient()` constructor removed** - use `New()` instead

#### Behavioral Changes

- **`ObjectEvaluation()` return structure changed**:
- v1: Returns treatment string only
- v2: Returns `FlagSetResult` (typed struct with `Treatment` and `Config` fields)

### New Features

#### Context-Aware Lifecycle

- `InitWithContext(ctx)` - Context-aware initialization with timeout and cancellation
- `ShutdownWithContext(ctx)` - Graceful shutdown with timeout and proper cleanup
- Idempotent initialization with singleflight (prevents concurrent init races)
- Provider cannot be reused after shutdown (must create new instance)

#### Event System

- OpenFeature event support:
- `PROVIDER_READY` - Provider initialized
- `PROVIDER_ERROR` - Initialization or runtime errors
- `PROVIDER_CONFIGURATION_CHANGED` - Flag definitions updated (detected via 30s polling)
- Background monitoring (30s interval) for configuration change detection

#### Event Tracking

- `Track()` method implementing OpenFeature Tracker interface
- Associates feature flag evaluations with user actions for A/B testing and experimentation
- Supports custom traffic types via `trafficType` attribute in evaluation context
- Supports event properties via `TrackingEventDetails.Add()`
- Events viewable in Split Data Hub

#### Per-Request Evaluation Options

- `WithEvaluationMode(ctx, mode)` - Control per-request object evaluation behavior via `context.Context`
- `EvaluationModeIndividual` - Evaluate a single flag (useful in cloud mode to bypass flag set evaluation)
- `EvaluationModeSet` - Evaluate a flag set (explicit, same as cloud default; ignored in localhost mode)
- `EvaluationModeDefault` - Use provider's default behavior (flag set in cloud, individual in localhost)
- `WithImpressionDisabled(ctx)` - Forward-looking API for per-evaluation impression control (logged, not yet enforced)
- `WithEvalOptions(ctx, opts)` - Set multiple evaluation options at once

#### Per-Request Track Options

- `WithoutMetricValue(ctx)` - Send nil value to Split for count-only events, preventing pollution of sum/average metrics
- `WithTrackOptions(ctx, opts)` - Set multiple tracking options at once
- `GetTrackOptions(ctx)` - Extract tracking options from context

#### Client Interface

- Extracted `Client` interface for dependency injection and mock generation
- Enables mockery-based mock generation for unit testing without Split SDK

#### Observability

- Structured logging with `log/slog` throughout provider and Split SDK
- `Metrics()` method for health status and diagnostics
- Unified logging via `WithLogger()` option

### Bug Fixes

#### Critical Fixes

- **`ObjectEvaluation()` structure**: Now returns `FlagSetResult` with `Treatment` and `Config` fields (was: treatment
string only)
- **Dynamic Configuration**: All config types (objects, primitives, arrays) consistently accessible via
`FlagMetadata["value"]`
- **Dynamic Configuration JSON parsing**: Supports objects, arrays, and primitives (was: limited support)
- **Evaluation context attributes**: Now passed to Split SDK for targeting rules (was: ignored)
- **Shutdown resource cleanup**: Properly cleans up goroutines, channels, and SDK clients (was: resource leaks)

#### Error Handling

- **Shutdown timeout errors**: `ShutdownWithContext()` returns `ctx.Err()` when cleanup times out (was: no error
indication)
- **JSON parse warnings**: Malformed Dynamic Configuration logged instead of silent failures
- **Targeting key validation**: Non-string keys rejected with clear errors (was: silent failures)

#### Concurrency & Reliability

- **Atomic initialization**: Factory, client, and manager ready together (was: race conditions)
- **Thread-safe health checks**: Eliminated race conditions in `Status()` and `Metrics()`
- **Event channel lifecycle**: Properly closed during shutdown (was: potential goroutine leaks)
- **Panic recovery**: Monitoring goroutine recovers from panics and terminates gracefully

## [1.0.1] - 2022-10-14

- Updated to OpenFeature spec v0.5.0 and OpenFeature Go SDK v0.6.0

## [1.0.0] - 2022-10-03

- Initial release
- OpenFeature spec v0.5.0 compliance
- OpenFeature Go SDK v0.5.0 support

[2.0.0]: https://github.com/splitio/split-openfeature-provider-go/compare/v1.0.1...v2.0.0

[1.0.1]: https://github.com/splitio/split-openfeature-provider-go/compare/v1.0.0...v1.0.1

[1.0.0]: https://github.com/splitio/split-openfeature-provider-go/releases/tag/v1.0.0
4 changes: 0 additions & 4 deletions CHANGES.txt

This file was deleted.

Loading