Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
db7b7ee
feat(flagd): run the provider conformance suite against both resolvers
aepfli Aug 24, 2026
f2a50f0
test(flagd): follow the @numeric-coercion rename
aepfli Sep 11, 2026
e58e0e2
test(flagd): declare @large-integers and withdraw @numeric-coercion
aepfli Sep 11, 2026
2d18a04
test(flagd): the falsy flags were a naming gap, not a backend gap
aepfli Sep 11, 2026
6439fe8
test(flagd): withhold @reinitialization, and say what was measured
aepfli Sep 11, 2026
b5f766b
test(flagd): declare @variants and @targeting, on a measured run
aepfli Sep 11, 2026
4442015
test(flagd): declare @disabled-flags on both resolvers, measured
aepfli Sep 12, 2026
fca1579
test(flagd): declare the stack instead of wiring it
aepfli Sep 12, 2026
5e343cb
test(flagd): keep the conformance suite out of the default build, and…
aepfli Sep 12, 2026
a3b59f4
test(flagd): point at Appendix F for the policy, and keep the suite i…
aepfli Sep 12, 2026
4d8fd3a
test(flagd): both resolvers claim the standard resolution reasons
aepfli Sep 13, 2026
dc63cd3
test(flagd): say what the numeric-coercion scenarios actually do, mea…
aepfli Sep 13, 2026
219ec1b
test(flagd): declare what a run supports, per resolver, and say what …
aepfli Sep 13, 2026
d58af84
docs(flagd): cite the declaring rule instead of stating it again
aepfli Sep 13, 2026
881e029
chore(flagd): ignore the flag file every e2e run generates
aepfli Sep 13, 2026
dd4856f
docs(flagd): cite rule six with the condition it was missing
aepfli Sep 13, 2026
27902c2
test(flagd): name the conformance modules for the resolver, not the s…
aepfli Sep 13, 2026
6149f0e
test(flagd): let the collect step run even when the default suite is red
aepfli Sep 13, 2026
7be3eae
test(flagd): drop a gitignore this branch has no reason to add
aepfli Sep 14, 2026
3e0888c
test(flagd): one compose definition of the backend for the whole repo
aepfli Sep 14, 2026
2f82f56
docs(flagd): keep the evidence, link the rules, delete the retellings
aepfli Sep 14, 2026
40670a6
test(tck): run the conformance suite against flagd-testbed v3.10.1
aepfli Sep 14, 2026
3a9b5b3
test(tck): stop naming one testbed release as the flag set's boundary
aepfli Sep 14, 2026
b183a32
test(flagd): declare @string-typing on both resolvers, measured
aepfli Sep 15, 2026
d7df5cd
test(flagd): declare @fully-typed-values on both resolvers, measured
aepfli Sep 16, 2026
2094639
docs(flagd): the standard-reasons note sits with the declarations it …
aepfli Sep 16, 2026
c11b513
test(flagd): sync the conformance assets where the scenarios execute
aepfli Sep 16, 2026
855d8f8
docs(flagd): stop naming a testbed release in the README tally
aepfli Sep 16, 2026
d1deaf0
test(flagd): run against flagd-testbed v3.10.3
aepfli Oct 5, 2026
4accfbc
test(flagd): cut comments the adoption does not own
aepfli Oct 7, 2026
d860700
test(flagd): run flagd-testbed's TCK extensions, replacing the e2e su…
aepfli Nov 3, 2026
f1694a9
test(flagd): pass Examples cells to the context steps as written
aepfli Nov 3, 2026
3e68eeb
test(flagd): follow flagd-testbed#445 to c5ac5de
aepfli Nov 3, 2026
5077642
chore(flagd): keep main's openfeature-sdk 0.10 dev floor beside the TCK
aepfli Nov 3, 2026
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
36 changes: 36 additions & 0 deletions providers/openfeature-provider-flagd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,42 @@ api.set_provider(
)
```

## Provider conformance suite

This provider runs the [OpenFeature Provider Conformance Suite][tck] against a flagd-testbed stack,
once per resolver, in `tests/tck`. Each run adds flagd-testbed's own scenarios, `tck-extensions/` in
the `openfeature/test-harness` submodule, to the canonical ones; `tests/tck/steps.py` defines the
flagd steps they use. The stack is the testbed's `docker-compose.yaml`, so the image follows the
submodule pin.

`config.feature` is not part of that run: it needs no backend, and `tests/test_config_feature.py`
runs it in the default build.

**It is excluded from the default build, and a maintainer runs it by hand before merging a change to
it.**

```
poe test-tck # both resolvers, needs Docker
poe test # everything else, which is what CI runs
```

The exclusion lives in `pyproject.toml`: `--ignore=tests/tck` on the two tasks `build.yml` reaches,
with the reason in a comment above them. Why a conformance suite is not a required gate is
[Appendix F, "Running the suite in CI"][appendix-f], and is not restated here.

Two things that are this provider's rather than the policy's:

- **The run is not green.** It is **5 failed, 648 passed, 75 skipped**, and
`tests/tck/conftest.py` accounts for each failure, so a reviewer running the suite can tell a new
failure from a known one.
- **The default build still collects the suite** — `poe test` and `poe test-cov` end in
`pytest tests/tck --collect-only`, which imports every module and starts no container. An excluded
suite that has quietly stopped importing against the harness is worse than one that runs and
fails, and `mypy` here is configured over `src` alone, so nothing else would notice.

[tck]: ../../tools/openfeature-tck/README.md
[appendix-f]: https://github.com/open-feature/spec/blob/main/specification/appendix-f-provider-conformance.md

## License

Apache 2.0 - See [LICENSE](./LICENSE) for more information.
52 changes: 49 additions & 3 deletions providers/openfeature-provider-flagd/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,18 @@ Homepage = "https://github.com/open-feature/python-sdk-contrib"

[dependency-groups]
dev = [
"asserts>=0.14.0,<0.15.0",
"coverage[toml]>=7.10.0,<8.0.0",
"grpcio-health-checking>=1.82.1,<2.0.0",
"mypy>=1.18.0,<2.0.0",
# The tests call `api.set_provider_and_wait`, which arrived in 0.10.0. The
# runtime floor stays at 0.8.2 because the provider itself needs nothing newer.
"openfeature-sdk>=0.10.0",
# The OpenFeature conformance suite. Ships the feature files, the flag set,
# the control-API client and the Compose harness that owns the container
# stack, and registers its step definitions through a pytest11 entry point --
# so tests/tck declares a Compose file and nothing else. The `compose` extra
# is what pulls testcontainers in for the harness.
"openfeature-tck[compose]",
"poethepoet>=0.37.0",
"pytest>=9.0.0,<10.0.0",
"pytest-bdd>=8.1.0,<9.0.0",
Expand Down Expand Up @@ -115,13 +120,54 @@ warn_unused_ignores = false

[tool.uv.sources]
openfeature-flagd-core = { workspace = true }
openfeature-tck = { workspace = true }

[tool.pytest]
strict = true

[tool.poe.tasks]
test = "pytest tests"
test-cov = "coverage run -m pytest tests"
# `tests/tck` is excluded from the default build on purpose, and a maintainer
# runs `poe test-tck` by hand before merging a change to it. Why a conformance
# suite is not a required gate is Appendix F, "Running the suite in CI" --
# linked from tools/openfeature-tck/README.md -- and is deliberately not
# restated here.
#
# What is local to this package: a full run is 5 failed, 648 passed, 75
# skipped, and tests/tck/conftest.py accounts for every failure.
#
# The suite is still *collected* on every default build, so it cannot quietly
# stop importing against the harness while nobody runs it. `--ignore` would
# otherwise leave nothing checking that, since mypy here is configured over
# `src` alone.
#
# `ignore_fail = "return_non_zero"` is what makes that true rather than
# aspirational: poe aborts a sequence at its first failing subtask, and this
# package's default suite is red on this branch -- the TCK requires
# openfeature-sdk >= 0.10 and this provider is not updated for it yet -- so the
# collect step sat behind a step that never succeeds and never ran. Every
# subtask now runs and a non-zero exit still propagates.
test = { sequence = ["test-default", "test-tck-collect"], ignore_fail = "return_non_zero" }
test-cov = { sequence = ["test-cov-default", "test-tck-collect"], ignore_fail = "return_non_zero" }
test-default = "pytest tests --ignore=tests/tck"
test-cov-default = "coverage run -m pytest tests --ignore=tests/tck"
# The sync is part of the run rather than something a maintainer remembers,
# because Appendix F requires the revision check to be in force **where the
# scenarios execute** and not only in the TCK implementation's own tests. This
# is a uv workspace, so `openfeature-tck` is installed editable and the
# canonical assets this suite collects are the gitignored copies under
# `tools/openfeature-tck/src`: a rebase that moves the submodule pin leaves them
# from the previous revision, and a suite run from here would neither notice nor
# say so. That is exactly how an adoption in another language published a full
# pass against stale scenarios. `hatch_build_sync.py` checks the submodule out
# at the pin, refuses to copy if it cannot, and needs nothing but the standard
# library.
#
# Not on `test-tck-collect`, deliberately: that runs on every default build, it
# executes no scenario, and it publishes no result, so the rule does not reach
# it and the default build stays free of a submodule operation.
sync-spec-assets = "python ../../tools/openfeature-tck/hatch_build_sync.py"
test-tck = ["sync-spec-assets", {cmd = "pytest tests/tck"}]
test-tck-collect = "pytest tests/tck --collect-only -q"
cov-report = "coverage xml"
cov = [
"test-cov",
Expand Down
5 changes: 0 additions & 5 deletions providers/openfeature-provider-flagd/tests/e2e/conftest.py

This file was deleted.

Empty file.
31 changes: 0 additions & 31 deletions providers/openfeature-provider-flagd/tests/e2e/file/conftest.py

This file was deleted.

This file was deleted.

104 changes: 0 additions & 104 deletions providers/openfeature-provider-flagd/tests/e2e/flagd_container.py

This file was deleted.

Empty file.

This file was deleted.

This file was deleted.

7 changes: 0 additions & 7 deletions providers/openfeature-provider-flagd/tests/e2e/parsers.py

This file was deleted.

2 changes: 0 additions & 2 deletions providers/openfeature-provider-flagd/tests/e2e/paths.py

This file was deleted.

Empty file.
27 changes: 0 additions & 27 deletions providers/openfeature-provider-flagd/tests/e2e/rpc/conftest.py

This file was deleted.

This file was deleted.

30 changes: 0 additions & 30 deletions providers/openfeature-provider-flagd/tests/e2e/step/_utils.py

This file was deleted.

Loading
Loading