Skip to content

Commit 124017e

Browse files
aepfliclaude
andauthored
refactor: changing evaluation lib etc (#45)
## Description <!-- Provide a brief description of your changes --> ## Related Issue <!-- Link to the related issue(s) --> Closes # ## Type of Change <!-- Mark the relevant option with an "x" --> - [ ] `feat`: New feature (minor version bump) - [ ] `fix`: Bug fix (patch version bump) - [ ] `docs`: Documentation only changes - [ ] `chore`: Maintenance tasks, dependency updates - [ ] `refactor`: Code refactoring without functional changes - [ ] `test`: Adding or updating tests - [ ] `ci`: CI/CD changes - [ ] `perf`: Performance improvements - [ ] `build`: Build system changes - [ ] `style`: Code style/formatting changes ## PR Title Format **IMPORTANT**: Since we use squash and merge, your PR title will become the commit message. Please ensure your PR title follows the [Conventional Commits](https://www.conventionalcommits.org/) format: ``` <type>(<optional-scope>): <description> ``` ### Examples: - `feat(operators): add new string comparison operator` - `fix(wasm): correct memory allocation bug` - `docs: update API examples in README` - `chore(deps): update rust dependencies` For breaking changes, use `!` after the type/scope or include `BREAKING CHANGE:` in the PR description: - `feat(api)!: redesign evaluation API` ## Testing <!-- Describe the testing you've performed --> - [ ] Unit tests added/updated - [ ] Integration tests added/updated - [ ] Manual testing performed - [ ] All tests pass (`cargo test`) - [ ] Code is formatted (`cargo fmt`) - [ ] Clippy checks pass (`cargo clippy -- -D warnings`) - [ ] WASM builds successfully (if applicable) ## Breaking Changes <!-- If this introduces breaking changes, describe them here --> - [ ] This PR includes breaking changes - [ ] Documentation has been updated to reflect breaking changes - [ ] Migration guide included (if needed) ## Additional Notes <!-- Any additional information, context, or screenshots --> --------- Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent cb7843a commit 124017e

26 files changed

Lines changed: 2150 additions & 1291 deletions

.cargo/config.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Cargo configuration for flagd-evaluator
2+
3+
# Disable SIMD for WASM target (Chicory doesn't support V128/SIMD128)
4+
[target.wasm32-unknown-unknown]
5+
rustflags = [
6+
"-C", "target-feature=-simd128"
7+
]

.github/workflows/ci.yml

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -76,64 +76,6 @@ jobs:
7676
- name: Check formatting
7777
run: cargo fmt -- --check
7878

79-
build-cli:
80-
name: Build CLI
81-
strategy:
82-
matrix:
83-
include:
84-
- os: ubuntu-latest
85-
target: x86_64-unknown-linux-gnu
86-
artifact: flagd-eval
87-
- os: macos-latest
88-
target: x86_64-apple-darwin
89-
artifact: flagd-eval
90-
- os: windows-latest
91-
target: x86_64-pc-windows-msvc
92-
artifact: flagd-eval.exe
93-
runs-on: ${{ matrix.os }}
94-
steps:
95-
- uses: actions/checkout@v4
96-
97-
- name: Install Rust
98-
uses: dtolnay/rust-toolchain@stable
99-
with:
100-
targets: ${{ matrix.target }}
101-
102-
- name: Cache cargo
103-
uses: actions/cache@v4
104-
with:
105-
path: |
106-
~/.cargo/bin/
107-
~/.cargo/registry/index/
108-
~/.cargo/registry/cache/
109-
~/.cargo/git/db/
110-
target/
111-
key: ${{ runner.os }}-cargo-cli-${{ hashFiles('**/Cargo.lock') }}
112-
restore-keys: |
113-
${{ runner.os }}-cargo-cli-
114-
115-
- name: Build CLI
116-
run: cargo build --release --bin flagd-eval
117-
118-
- name: Test CLI binary
119-
run: |
120-
./target/release/${{ matrix.artifact }} --help
121-
./target/release/${{ matrix.artifact }} operators
122-
shell: bash
123-
124-
- name: Validate example files
125-
run: |
126-
./target/release/${{ matrix.artifact }} eval --rule @examples/rules/basic.json --data '{"age": 25}'
127-
./target/release/${{ matrix.artifact }} test examples/rules/test-suite.json
128-
shell: bash
129-
130-
- name: Upload CLI artifact
131-
uses: actions/upload-artifact@v4
132-
with:
133-
name: flagd-eval-${{ matrix.target }}
134-
path: target/release/${{ matrix.artifact }}
135-
retention-days: 30
136-
13779
build-wasm:
13880
name: Build WASM
13981
runs-on: ubuntu-latest

.github/workflows/release.yml

Lines changed: 1 addition & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -30,80 +30,6 @@ jobs:
3030
config-file: release-please-config.json
3131
manifest-file: .release-please-manifest.json
3232

33-
build-cli:
34-
name: Build CLI (${{ matrix.target }})
35-
needs: release-please
36-
if: always() && (needs.release-please.outputs.release_created == 'true' || startsWith(github.ref, 'refs/tags/'))
37-
strategy:
38-
matrix:
39-
include:
40-
- os: ubuntu-latest
41-
target: x86_64-unknown-linux-gnu
42-
artifact: flagd-eval
43-
archive: flagd-eval-linux-x64.tar.gz
44-
- os: macos-latest
45-
target: x86_64-apple-darwin
46-
artifact: flagd-eval
47-
archive: flagd-eval-macos-x64.tar.gz
48-
- os: macos-latest
49-
target: aarch64-apple-darwin
50-
artifact: flagd-eval
51-
archive: flagd-eval-macos-arm64.tar.gz
52-
- os: windows-latest
53-
target: x86_64-pc-windows-msvc
54-
artifact: flagd-eval.exe
55-
archive: flagd-eval-windows-x64.zip
56-
runs-on: ${{ matrix.os }}
57-
steps:
58-
- uses: actions/checkout@v4
59-
60-
- name: Install Rust
61-
uses: dtolnay/rust-toolchain@stable
62-
with:
63-
targets: ${{ matrix.target }}
64-
65-
- name: Cache cargo
66-
uses: actions/cache@v4
67-
with:
68-
path: |
69-
~/.cargo/bin/
70-
~/.cargo/registry/index/
71-
~/.cargo/registry/cache/
72-
~/.cargo/git/db/
73-
target/
74-
key: ${{ runner.os }}-${{ matrix.target }}-cargo-release-${{ hashFiles('**/Cargo.lock') }}
75-
restore-keys: |
76-
${{ runner.os }}-${{ matrix.target }}-cargo-release-
77-
78-
- name: Build CLI
79-
run: cargo build --release --target ${{ matrix.target }} --bin flagd-eval
80-
81-
- name: Create archive (Unix)
82-
if: runner.os != 'Windows'
83-
run: |
84-
cd target/${{ matrix.target }}/release
85-
tar czvf ../../../${{ matrix.archive }} ${{ matrix.artifact }}
86-
cd ../../..
87-
sha256sum ${{ matrix.archive }} > ${{ matrix.archive }}.sha256
88-
89-
- name: Create archive (Windows)
90-
if: runner.os == 'Windows'
91-
shell: pwsh
92-
run: |
93-
cd target/${{ matrix.target }}/release
94-
Compress-Archive -Path ${{ matrix.artifact }} -DestinationPath ../../../${{ matrix.archive }}
95-
cd ../../..
96-
$hash = (Get-FileHash ${{ matrix.archive }} -Algorithm SHA256).Hash.ToLower()
97-
"$hash ${{ matrix.archive }}" | Out-File -Encoding ASCII ${{ matrix.archive }}.sha256
98-
99-
- name: Upload CLI artifact
100-
uses: actions/upload-artifact@v4
101-
with:
102-
name: cli-${{ matrix.target }}
103-
path: |
104-
${{ matrix.archive }}
105-
${{ matrix.archive }}.sha256
106-
10733
build-wasm:
10834
name: Build WASM
10935
needs: release-please
@@ -169,17 +95,10 @@ jobs:
16995
17096
create-release:
17197
name: Create Release
172-
needs: [release-please, build-cli, build-wasm]
98+
needs: [release-please, build-wasm]
17399
if: always() && (needs.release-please.outputs.release_created == 'true' || startsWith(github.ref, 'refs/tags/'))
174100
runs-on: ubuntu-latest
175101
steps:
176-
- name: Download CLI artifacts
177-
uses: actions/download-artifact@v4
178-
with:
179-
pattern: cli-*
180-
path: artifacts
181-
merge-multiple: true
182-
183102
- name: Download WASM artifact
184103
uses: actions/download-artifact@v4
185104
with:

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "testbed"]
2+
path = testbed
3+
url = git@github.com:open-feature/flagd-testbed.git

CLAUDE.md

Lines changed: 11 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ cargo build --target wasm32-unknown-unknown --no-default-features --release --li
2222
# WASM output location
2323
# target/wasm32-unknown-unknown/release/flagd_evaluator.wasm
2424

25-
# Build CLI tool
26-
cargo build --release --bin flagd-eval
2725
```
2826

2927
### Testing
@@ -34,7 +32,7 @@ cargo test
3432

3533
# Run specific test file
3634
cargo test --test integration_tests
37-
cargo test --test cli_tests
35+
cargo test --test gherkin_tests
3836

3937
# Run specific test by name
4038
cargo test test_fractional_operator
@@ -56,22 +54,6 @@ cargo fmt -- --check
5654
cargo clippy -- -D warnings
5755
```
5856

59-
### CLI Tool Usage
60-
61-
```bash
62-
# Evaluate a JSON Logic rule
63-
cargo run --bin flagd-eval -- eval --rule '{"==": [1, 1]}' --data '{}'
64-
65-
# Load rule/data from file (use @ prefix)
66-
cargo run --bin flagd-eval -- eval --rule @examples/rules/basic.json --data '{"age": 25}'
67-
68-
# Run test suite
69-
cargo run --bin flagd-eval -- test examples/rules/test-suite.json
70-
71-
# List available operators
72-
cargo run --bin flagd-eval -- operators
73-
```
74-
7557
## Architecture
7658

7759
### Core Design Principles
@@ -96,9 +78,7 @@ src/
9678
│ ├── starts_with.rs # String prefix matching
9779
│ └── ends_with.rs # String suffix matching
9880
├── model/ # Flag configuration data structures
99-
├── validation.rs # JSON Schema validation against flagd schemas
100-
└── bin/
101-
└── flagd-eval.rs # CLI tool for testing rules without WASM
81+
└── validation.rs # JSON Schema validation against flagd schemas
10282
```
10383

10484
### Key Architectural Concepts
@@ -142,7 +122,7 @@ strip = true # Strip symbols
142122
panic = "abort" # Remove panic unwinding infrastructure
143123
```
144124

145-
**No Default Features for WASM**: Always build with `--no-default-features` to exclude CLI dependencies (clap, colored) from WASM binary.
125+
**No Default Features for WASM**: Always build with `--no-default-features` to exclude unnecessary dependencies from WASM binary.
146126

147127
### Memory Safety Rules
148128

@@ -171,7 +151,7 @@ Resolution reasons: `STATIC`, `DEFAULT`, `TARGETING_MATCH`, `DISABLED`, `ERROR`,
171151

172152
### Testing Philosophy
173153

174-
**Integration Tests** (tests/integration_tests.rs): 72 comprehensive tests covering:
154+
**Integration Tests** (tests/integration_tests.rs): Comprehensive tests covering:
175155
- Basic JSON Logic operations
176156
- All custom operators (fractional, sem_ver, starts_with, ends_with)
177157
- Memory management
@@ -180,7 +160,7 @@ Resolution reasons: `STATIC`, `DEFAULT`, `TARGETING_MATCH`, `DISABLED`, `ERROR`,
180160
- Type-specific evaluation functions
181161
- Context enrichment ($flagd properties)
182162

183-
**CLI Tests** (tests/cli_tests.rs): End-to-end tests for the flagd-eval binary.
163+
**Gherkin Tests** (tests/gherkin_tests.rs): Specification compliance tests using the official flagd testbed.
184164

185165
**When to Run Tests**:
186166
- ✅ After making code changes that affect behavior
@@ -197,7 +177,6 @@ Resolution reasons: `STATIC`, `DEFAULT`, `TARGETING_MATCH`, `DISABLED`, `ERROR`,
197177
3. Register in `src/operators/mod.rs` via `create_evaluator()`
198178
4. Add tests in both unit tests and `tests/integration_tests.rs`
199179
5. Document in README.md under "Custom Operators" section
200-
6. Consider adding to CLI's `operators` command output
201180

202181
**Modifying Flag Evaluation Logic**:
203182
1. Primary logic is in `src/evaluation.rs`
@@ -287,14 +266,14 @@ This project uses [Release Please](https://github.com/googleapis/release-please)
287266
**Core Production**:
288267
- `datalogic-rs` (4.0) - JSON Logic implementation
289268
- `serde`, `serde_json` - JSON serialization (no_std compatible with alloc)
290-
- `jsonschema` (0.37) - Flag configuration validation
291-
292-
**CLI Only** (excluded from WASM):
293-
- `clap` - Command-line argument parsing
294-
- `colored` - Terminal colors
269+
- `boon` (0.6) - JSON Schema validation
270+
- `murmurhash3` - Hash function for fractional operator
271+
- `ahash` - Hash table implementation (SIMD-disabled for Chicory compatibility)
272+
- `getrandom` - Random number generation for WASM
295273

296274
**Dev**:
297-
- `assert_cmd`, `predicates` - CLI integration testing
275+
- `cucumber` - Gherkin/BDD testing
276+
- `tokio` - Async runtime for tests
298277

299278
## Cross-Language Integration
300279

Cargo.toml

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,27 @@ categories = ["wasm", "web-programming"]
1313
[lib]
1414
crate-type = ["cdylib", "rlib"]
1515

16-
[[bin]]
17-
name = "flagd-eval"
18-
path = "src/bin/flagd-eval.rs"
19-
2016
[dependencies]
2117
datalogic-rs = "4.0"
2218
serde = { version = "1.0", features = ["derive", "alloc"], default-features = false }
2319
serde_json = { version = "1.0", features = ["alloc"], default-features = false }
24-
jsonschema = { version = "0.37", default-features = false }
25-
26-
# CLI-only dependencies (used by the binary, not the WASM lib)
27-
clap = { version = "4.5", features = ["derive", "cargo"], optional = true }
28-
colored = { version = "2.1", optional = true }
29-
30-
[features]
31-
default = ["cli"]
32-
cli = ["clap", "colored"]
20+
boon = "0.6"
21+
murmurhash3 = "0.0.5"
22+
# Override ahash to avoid SIMD/AES-NI instructions that break Chicory WASM compatibility
23+
# ahash is pulled in by boon and uses AES-NI by default
24+
# We disable default features and use compile-time-rng to avoid runtime randomness
25+
ahash = { version = "0.8.12", default-features = false, features = ["compile-time-rng"] }
26+
# Enable wasm_js feature for getrandom in WASM builds (required for wasm32-unknown-unknown)
27+
getrandom = { version = "0.3", features = ["wasm_js"] }
3328

3429
[dev-dependencies]
3530
wasm-bindgen-test = "0.3"
3631
assert_cmd = "2.0"
3732
predicates = "3.0"
33+
cucumber = "0.22.1"
34+
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
35+
async-trait = "0.1"
36+
glob = "0.3"
3837

3938
[profile.release]
4039
opt-level = "z"

0 commit comments

Comments
 (0)