Skip to content

test(flagd): run the remaining flagd-testbed scenarios as TCK extensions - #1951

Open
aepfli wants to merge 27 commits into
mainfrom
feat/provider-tck-flagd-extensions
Open

aepfli wants to merge 27 commits into
mainfrom
feat/provider-tck-flagd-extensions

Conversation

@aepfli

@aepfli aepfli commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

Stacked on #1847, which adopts the Provider TCK for flagd, and on #1952, whose tag annotations it selects with -- #1952's three commits are replayed beneath this branch's, so the diff here carries them until #1952 merges. Part of #1829 and open-feature/spec#417.

Ports the flagd-testbed scenarios the TCK does not ask into the TCK's extensions/ hook, so they run in the TCK suites, in both resolvers, without the legacy e2e harness.

What it adds

  • providers/flagd/src/test/resources/extensions/*.feature: 11 files, testbed wording kept wherever it does not collide with a TCK step.
  • openfeature.tck.extensions: FlagdSteps holds the shared steps, plus MetadataSteps and ConnectionSteps.
  • FlagdTckHarness: a per-scenario options seam. A scenario records options (an option "cache" of type "CacheType" with value "disabled"), and the TCK's own Given a stable provider applies them. There is no second way to build a provider.
  • The suites run the flagd-testbed's own test-harness/docker-compose.yaml (flagd plus envoy, for @targetURI and @forbidden), the file the legacy e2e suites already use, so the image tag follows the submodule. The tck profile checks out the submodule and points its FLAGS_DIR bind mount into target. tools/flagd-testbed/ is removed; the OFREP adoption moves to the same file.

Selection by tag

Selection uses the TCK's annotations from #1952; FlagdSteps has no tag logic.

  • Every extension scenario carries @rpc, @in-process and/or @file, on the scenario or its feature, as in the flagd-testbed. RpcTest declares @TckIncludeTags("@rpc") and InProcessTest @TckIncludeTags("@in-process"), so a scenario runs only in the suites it names.
  • @fractional-v2 is excluded in both suites with @TckExcludeTags: the Java in-process evaluator and the testbed's flagd both implement v3.
  • Every file also carries an @ext-* tag, so one area can be run with -Dcucumber.filter.tags=@ext-fractional.

Testbed pin: v3.10.3 → v3.10.4

v3.10.4 ships flagd v0.18.0, which implements fractional v3. On v3.10.3 the RPC resolver bucketed the v2 way while the in-process evaluator did v3, so 123 fractional scenarios failed in RPC only. The same bump is ready for the OFREP adoption, where it measures unchanged (46 passed, 17 skipped, 2 failed).

Not ported

  • config.feature: already runs as a unit suite (ConfigCucumberTest).
  • @unixsocket: there is no suite for it in the TCK adoption. @file is tagged where the testbed has it, but no file-resolver suite runs it yet.
  • @fractional-v1 and @deprecated scenarios.
  • Scenarios the canonical features already ask: resolve values, targeting by targeting key, the flag change event, the stable connection row, and the disabled boolean row.

Notes for review

  • @caching is a reserved TCK capability tag and throws on any scenario that carries it, so the testbed's tag is spelled @flagd-caching here.
  • The TCK's single-key context step has no Object type and parses Integer as 32-bit. Outlines with larger or structured values use the a context with the following keys: table instead.
  • Timing-sensitive scenarios (grace, stale, reconnect) set retryGracePeriod 5 and retryBackoffMaxMs 500 explicitly, as the legacy stable provider did. No sleeps are added.

Running it

mvn -Ptck -pl tools/tck,providers/flagd clean test

In the reactor with tools/tck, which provides the annotations.

Each resolver runs 353 scenarios: the 65 canonical ones plus 288 extension scenarios, on flagd-testbed v3.10.4.

Resolver Passed Failed Skipped
in-process 316 4 33
RPC 310 4 39

Every extension scenario passes. The 4 failures in each resolver are the 4 canonical ones #1847 already records: the numeric-coercion deviation and three fixture gaps. The skips are the 2 canonical skips, the 21 @fractional-v2 scenarios, and scenarios tagged for the other resolver. The timing scenarios (grace, stale, reconnect) were also run three times in isolation, without flakiness.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Walkthrough

flagd testbed scenarios now run through Provider TCK extensions instead of the legacy e2e runners. Resolver suites select scenarios with TCK tags, and configuration scenarios use a separate state container and glue package. The module updates test resources and TCK instructions.

Changes: flagd Provider TCK migration

Layer / File(s) Summary
Configuration scenario setup
providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/ConfigCucumberTest.java, providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/config/*, providers/flagd/pom.xml
Configuration scenarios use a dedicated ConfigState and glue package. The suite description identifies the scenarios as backend-free, and the Maven profile describes configuration and Provider TCK harness setup.
TCK harness and resolver selection
providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/tck/*
AbstractResolverTest implements FlagdTckHarness, exposes Envoy ports and endpoint information, and applies recorded option customizations when creating providers. Resolver suites select scenarios with TCK include and exclude tags.
TCK extensions and testbed wiring
providers/flagd/src/test/java/openfeature/tck/extensions/*, providers/flagd/pom.xml, providers/flagd/test-harness, providers/flagd/CONTRIBUTING.md, providers/flagd/README.md
Extension steps configure Envoy connections and flagd options, including typed option conversion. Maven adds testbed feature files under extensions; the test-harness reference and project instructions are updated.
Legacy e2e runner removal
providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/*, providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/steps/*, providers/flagd/src/test/resources/junit-platform.properties, providers/flagd/pom.xml
The module removes legacy e2e suite runners, shared state and step definitions, container lifecycle helpers, Cucumber execution settings, and the default e2e test exclusion.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Other

Sequence Diagram(s)

sequenceDiagram
  participant TCK as Provider TCK
  participant Steps as FlagdSteps
  participant Harness as FlagdTckHarness
  participant Resolver as AbstractResolverTest
  TCK->>Steps: Run extension scenario steps
  Steps->>Harness: Record option customizations
  Resolver->>Harness: Apply customizations during provider creation
Loading

Possibly related PRs

Merge Risk: Moderate · up to 58ee7

The documented local TCK workflow still requires an undocumented submodule initialization step. Add initialization to that workflow or document the prerequisite before merging; CI already initializes submodules.

Pre-merge checks: Passed 5
Check name Status Explanation
Title check Passed The title "test(flagd): run the remaining flagd-testbed scenarios as TCK extensions" matches the main change. The PR adds 11 flagd-testbed feature files as TCK extensions (FlagdSteps, MetadataSteps, C…
Description check Passed The description matches the changeset. It explains the 11 extension feature files, the FlagdSteps/FlagdTckHarness additions, tag-based suite selection via @TckIncludeTags and @TckExcludeTags, the test…
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title "test(flagd): run the remaining flagd-testbed scenarios as TCK extensions" matches the main change. The PR adds 11 flagd-testbed feature files as TCK extensions (FlagdSteps, MetadataSteps, ConnectionSteps, FlagdTckHarness), removes the legacy e2e harness (ContainerPool, ContainerEntry, State, step classes), and bumps the testbed pin. The title is concise, specific, and follows a conventional commit style.

Full details: Description check

Explanation

The description matches the changeset. It explains the 11 extension feature files, the FlagdSteps/FlagdTckHarness additions, tag-based suite selection via @TckIncludeTags and @TckExcludeTags, the testbed pin bump from v3.10.3 to v3.10.4, the removal of tools/flagd-testbed, and the test results for both resolvers. It also lists scenarios that were not ported.

Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 2 functions across 12 files. (1 skipped: 1 unsupported.)

Finishing Touches
Generate docstrings
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

ast-grep (0.51.1)

ast-grep could not parse rule config: /ast-grep-rules/ast-grep-essentials/rules/bash/security/tmp-file-pid-name-bash.yml

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.
Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 73e3e936-85b4-45bf-afcd-d95fef22f074
Commits

Reviewing files that changed from the base of the PR and between 453ec78 and 58ee7ad.

Files selected for processing: 2
  • providers/flagd/src/test/java/openfeature/tck/extensions/FlagdSteps.java
  • providers/flagd/test-harness

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

aepfli added a commit that referenced this pull request Oct 21, 2026
An extension scenario must carry @rpc, @In-Process or @file, on the
scenario or its feature; one with none fails instead of running in
every suite. Restores @file where the flagd-testbed has it.

Uncommitted work from the #1951 session, committed as is.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
@aepfli
aepfli force-pushed the feat/provider-tck-flagd-extensions branch from 39d40ad to 098315b Compare October 21, 2026 14:45
aepfli added a commit that referenced this pull request Oct 21, 2026
Every scenario in the self-test fixture carried a tag, so nothing
distinguished the two readings of TckIncludeTags: a filter that skips
whatever does not carry an included tag, or a hint that spares a scenario
carrying no selector at all. The implementation is the first; the fixture
could not tell.

Adds an untagged extension scenario and asserts it does not run while an
include is set, so the next reader does not have to infer the rule from
Collections.disjoint. The two existing abort counts move with it.

This matters for the flagd adoption in #1951: it tags resolver-specific
scenarios @rpc or @In-Process and expects untagged ones to run in both,
which an include cannot express. Resolver selection wants
@TckExcludeTags("@In-Process") and @TckExcludeTags("@rpc") instead.

263 tests, 0 failures.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
@aepfli

aepfli commented Oct 21, 2026

Copy link
Copy Markdown
Member Author

The tag annotations here select the wrong way round, and the effect is silent: the untagged extension scenarios would run in neither suite.

AdopterTags.requireSelected in #1952 treats an include as a hard filter:

if (!included.isEmpty() && Collections.disjoint(tags, included)) {
    throw new TestAbortedException("Skipped: scenario carries none of " + included + …);
}

RpcTest carries @TckIncludeTags("@rpc") and InProcessTest @TckIncludeTags("@in-process"), so a scenario with no tag is disjoint from both include sets and is skipped in both — reported as a skip, not a failure. That contradicts this PR's own description: "untagged scenarios run in both".

It is not hypothetical. Counting untagged scenarios in three of the eleven feature files:

file scenarios untagged
evaluation.feature 4 1
targeting.feature 16 3
events.feature 3 1

Resolver selection is an exclusion, not an inclusion — and since TckExcludeTags is not @Repeatable, the two tags go in one array:

@TckExcludeTags({"@in-process", "@fractional-v2"})   // RpcTest
@TckExcludeTags({"@rpc", "@fractional-v2"})          // InProcessTest

That gives exactly the stated rule: a tagged scenario runs only in its own resolver, an untagged one runs in both. It needs no change to #1952, and it leaves @TckIncludeTags its own meaning — run only these — which is what the @ext-* area selection would want.

Two other things from reading the branch:

I have added the missing coverage on #1952: the self-test fixture had a tag on every scenario, so nothing there distinguished "include filters" from "include spares the untagged". It now has an untagged extension scenario and asserts it does not run while an include is set.

aepfli added a commit that referenced this pull request Oct 21, 2026
Every scenario in the self-test fixture carried a tag, so nothing
distinguished the two readings of TckIncludeTags: a filter that skips
whatever does not carry an included tag, or a hint that spares a scenario
carrying no selector at all. The implementation is the first; the fixture
could not tell.

Adds an untagged extension scenario and asserts it does not run while an
include is set, so the next reader does not have to infer the rule from
Collections.disjoint. The two existing abort counts move with it.

This matters for the flagd adoption in #1951: it tags resolver-specific
scenarios @rpc or @In-Process and expects untagged ones to run in both,
which an include cannot express. Resolver selection wants
@TckExcludeTags("@In-Process") and @TckExcludeTags("@rpc") instead.

263 tests, 0 failures.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
aepfli added a commit that referenced this pull request Oct 21, 2026
An extension scenario must carry @rpc, @In-Process or @file, on the
scenario or its feature; one with none fails instead of running in
every suite. Restores @file where the flagd-testbed has it.

Uncommitted work from the #1951 session, committed as is.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
@aepfli
aepfli force-pushed the feat/provider-tck-flagd-extensions branch from 868dd4f to bfd0e26 Compare October 21, 2026 16:59
@aepfli

aepfli commented Oct 21, 2026

Copy link
Copy Markdown
Member Author

Correction to my earlier comment: the include annotations are right and should stay. I was
counting tags on the Scenario: lines only, and missed that Cucumber inherits feature-level tags
into getSourceTagNames() — every one of these feature files carries its resolver tags on the
Feature: line, so there are no untagged scenarios to lose.

Measured on this branch, RpcTest over the 75 extension scenarios:

selection runs skips
@TckIncludeTags("@rpc") — current 62 13
@TckExcludeTags({"@in-process", "@fractional-v2"}) — what I suggested 6 69

The exclude form collapses because the dual-mode scenarios carry both resolver tags:
evaluation.feature, targeting.feature, events.feature, fractional.feature and
disabled.feature are @rpc @in-process at feature level, so excluding @in-process excludes them
from the RPC run as well. Resolver selection here is an inclusion, and an exclude only expresses it
when the tags are mutually exclusive.

A full RPC run shows the inheritance both ways: "Returns metadata" (no tag of its own,
@in-process on the feature) is skipped with carries none of [@rpc], included by RpcTest, while
the untagged scenarios in evaluation.feature run.

The other half of that comment does hold, and is addressed: the branch could not compile, because
the annotations live on #1952. It is now stacked on them — this branch's 22 commits are replayed on
top of #1952's three, merges preserved and every patch-id unchanged. The suite runs: 353 tests, 39
skipped, 4 failures, all four the known flagd deviations (the two float cases, numeric coercion and
the large-integer example).

aepfli added a commit that referenced this pull request Oct 21, 2026
An extension scenario must carry @rpc, @In-Process or @file, on the
scenario or its feature; one with none fails instead of running in
every suite. Restores @file where the flagd-testbed has it.

Uncommitted work from the #1951 session, committed as is.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
@aepfli
aepfli force-pushed the feat/provider-tck-flagd-extensions branch from bfd0e26 to c29a1e1 Compare October 21, 2026 19:31
aepfli added a commit that referenced this pull request Oct 22, 2026
Every scenario in the self-test fixture carried a tag, so nothing
distinguished the two readings of TckIncludeTags: a filter that skips
whatever does not carry an included tag, or a hint that spares a scenario
carrying no selector at all. The implementation is the first; the fixture
could not tell.

Adds an untagged extension scenario and asserts it does not run while an
include is set, so the next reader does not have to infer the rule from
Collections.disjoint. The two existing abort counts move with it.

This matters for the flagd adoption in #1951: it tags resolver-specific
scenarios @rpc or @In-Process and expects untagged ones to run in both,
which an include cannot express. Resolver selection wants
@TckExcludeTags("@In-Process") and @TckExcludeTags("@rpc") instead.

263 tests, 0 failures.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
aepfli added a commit that referenced this pull request Oct 22, 2026
An extension scenario must carry @rpc, @In-Process or @file, on the
scenario or its feature; one with none fails instead of running in
every suite. Restores @file where the flagd-testbed has it.

Uncommitted work from the #1951 session, committed as is.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
@aepfli
aepfli force-pushed the feat/provider-tck-flagd-extensions branch from c29a1e1 to cc17a23 Compare October 22, 2026 07:47
aepfli added a commit that referenced this pull request Oct 22, 2026
Every scenario in the self-test fixture carried a tag, so nothing
distinguished the two readings of TckIncludeTags: a filter that skips
whatever does not carry an included tag, or a hint that spares a scenario
carrying no selector at all. The implementation is the first; the fixture
could not tell.

Adds an untagged extension scenario and asserts it does not run while an
include is set, so the next reader does not have to infer the rule from
Collections.disjoint. The two existing abort counts move with it.

This matters for the flagd adoption in #1951: it tags resolver-specific
scenarios @rpc or @In-Process and expects untagged ones to run in both,
which an include cannot express. Resolver selection wants
@TckExcludeTags("@In-Process") and @TckExcludeTags("@rpc") instead.

263 tests, 0 failures.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
@aepfli
aepfli force-pushed the feat/provider-tck-flagd-extensions branch from cc17a23 to c821cd3 Compare October 22, 2026 08:07
aepfli added a commit that referenced this pull request Oct 22, 2026
An extension scenario must carry @rpc, @In-Process or @file, on the
scenario or its feature; one with none fails instead of running in
every suite. Restores @file where the flagd-testbed has it.

Uncommitted work from the #1951 session, committed as is.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
@aepfli
aepfli force-pushed the feat/provider-tck-flagd-extensions branch from c821cd3 to fc8a464 Compare October 22, 2026 08:21
aepfli added a commit that referenced this pull request Oct 22, 2026
Every scenario in the self-test fixture carried a tag, so nothing
distinguished the two readings of TckIncludeTags: a filter that skips
whatever does not carry an included tag, or a hint that spares a scenario
carrying no selector at all. The implementation is the first; the fixture
could not tell.

Adds an untagged extension scenario and asserts it does not run while an
include is set, so the next reader does not have to infer the rule from
Collections.disjoint. The two existing abort counts move with it.

This matters for the flagd adoption in #1951: it tags resolver-specific
scenarios @rpc or @In-Process and expects untagged ones to run in both,
which an include cannot express. Resolver selection wants
@TckExcludeTags("@In-Process") and @TckExcludeTags("@rpc") instead.

263 tests, 0 failures.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
aepfli added a commit that referenced this pull request Oct 22, 2026
An extension scenario must carry @rpc, @In-Process or @file, on the
scenario or its feature; one with none fails instead of running in
every suite. Restores @file where the flagd-testbed has it.

Uncommitted work from the #1951 session, committed as is.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
aepfli added 21 commits November 2, 2026 19:45
Scenarios tagged @fractional-vN run only when N is the version the backend
implements: v3 by default, -Dflagd.tck.fractional=v2 to run the v2
expectations instead. Untagged scenarios run regardless.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
…narios as TCK extensions

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
… a TCK extension

Evaluator reuse and refs, string and sem_ver operators, time-based rules, error edge cases and operator errors, run in both resolvers under @ext-targeting.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
…richment scenarios

Runs flagd-testbed's metadata.feature, sync-payload.feature and contextEnrichment.feature as TCK extensions tagged @ext-metadata, with MetadataSteps for the flag metadata assertions. The @Grace scenarios restore the testbed's retry timing; the RPC one also its 1000ms deadline. @caching becomes @flagd-caching, as the TCK reserves the former.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
…os to TCK extensions

Adds events.feature, connection.feature and rpc-caching.feature under
extensions/ (@ext-connection), with ConnectionSteps for envoy routing and
an event-ordering assertion the draining TCK await cannot express.

The suite now starts tools/flagd-testbed/docker-compose.flagd.yaml, which
includes the shared stack and adds an envoy sidecar for @targetURI and
@forbidden.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
Every @fractional scenario of flagd-testbed's targeting.feature, plus the
fractional @operator-errors ones, without the v1/v2 bucketing variants the
legacy e2e suites exclude. Object and beyond-32-bit integer context values
use the table step, as the TCK's context step cannot convert them.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
The @fractional-v2 examples, the single-entry and the hash edge-case
scenarios, gated by their version tags. v1 stays out: no backend here
implements it.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
An extension scenario must carry @rpc, @In-Process or @file, on the
scenario or its feature; one with none fails instead of running in
every suite. Restores @file where the flagd-testbed has it.

Uncommitted work from the #1951 session, committed as is.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
RpcTest and InProcessTest include their resolver tag with
@TckIncludeTags and exclude @fractional-v2 with @TckExcludeTags, which
replaces FlagdSteps' own resolver and fractional-version gates and the
harness's resolver() and fractionalVersion() (-Dflagd.tck.fractional).

FlagdSteps keeps failing an extension scenario with no resolver tag,
now before the TCK's gate, which would otherwise skip it silently.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
Every extension scenario carries a resolver tag; nothing needs to
check it.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
The suites use test-harness/docker-compose.yaml, which the legacy e2e
suites already run, instead of a copy under tools/flagd-testbed: the
image tag follows the submodule and the envoy listeners are the
testbed's. The tck profile checks out the submodule and points the
testbed's FLAGS_DIR bind mount into target. Drops
tools/flagd-testbed; the OFREP adoption moves to the same file.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
The test-harness submodule is already checked out with the repository.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
Without FLAGS_DIR the testbed mounts its own checkout at /flags, and the
launchpad removes the flag file it writes there on shutdown.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
Four of this suite's five steps said nothing about flagd. Two of them never
touched a backend, and two spoke the control API's own operations through a
vendor-named step: the launchpad FlagdSteps posted to is the control API the
TCK already drives through BackendControl.

So the feature files say "the backend serves the ... configuration" now, and
FlagdSteps keeps only the provider options, whose names are flagd's. The
@after no longer restores the default configuration either -- BackendControl
records what a scenario served and takes the next scenario off it.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
The testbed timed every outage: lost for 8s, lost for 6s, lost for 1s. What each
scenario is actually asking is a sequence -- stale, then error, then ready -- and
the length was only a way of deciding whether the retry grace period would be
crossed. So the chains say it directly: the connection is lost, the events that
follow are awaited, the connection is restored, ready is awaited.

The 1s outage is the clearest case. It asked for stale without error, by being
shorter than the 5s grace period; restoring the connection as soon as stale has
fired asks the same thing without a wall clock to lose a race against on a slow
machine.

The configuration moves onto the provider step as well -- "a stable provider with
"sync-payload" configuration" -- so it cannot be stated after the provider it is
supposed to configure.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
ConnectionSteps had written "the {} event handler should have been executed with
no {} event before it" locally, and its javadoc explained why: the TCK's await
drained the records ahead of its match, so an error recorded before an awaited
ready was gone and "should not have been executed" passed vacuously. The TCK
keeps those records and asks the question itself now, so the local copy goes,
along with the redundant negative assertion the chain carried after it.

What stays here is flagd's own: the envoy target URI and the forbidden listener.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
MetadataSteps held "the resolved metadata should contain" and "the resolved
metadata is empty" -- the specification's own wording, down to the
metadata_type column, for behaviour the specification defines rather than flagd.
The TCK asks them now, so the local copies would be duplicate step definitions.

Nothing of this file was flagd's: it read the last evaluation's flag metadata
through the SDK and compared typed entries. What remains in this package is the
provider options and the envoy routing.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
The porting note said @file was dropped because this suite has no file
resolver, but the tag is still on the feature, as it is on the four other
ported features. The two scenarios a file resolver genuinely cannot serve name
a selector flag file and already carry @metadata-provider, so the tag was right
and the sentence was wrong.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
… v3.11.0

v3.11.0 added five @fractional-nested @fractional-v3 outlines to
gherkin/targeting.feature: a null or boolean bucket as the whole rule or as an if
condition, a fractional result consumed by another operator, and one fractional
bucketing another. The legacy e2e suites picked them up with the submodule bump,
but this extension predates them, so the TCK ran 11 rows fewer than the suite it
replaces.

Their flags are already in the testbed's custom-ops.json, which the default
launchpad configuration serves, so nothing else is needed.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
The flagd-testbed scenarios now run as Provider TCK extensions, so the
Run*Test suites, their steps and the container pool go. config.feature needs
no backend: its steps move to a plain test package and ConfigCucumberTest keeps
reading it from the test-harness submodule.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
The extension scenarios now live in flagd-testbed's tck-extensions/, so every
flagd provider adopting the TCK runs the same files. The test-harness
submodule is pinned to open-feature/flagd-testbed#445 until it is released,
and the module puts tck-extensions/ on the test classpath as extensions/,
where the TCK looks; the local copies go.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
@aepfli
aepfli marked this pull request as ready for review November 2, 2026 20:46
@aepfli
aepfli requested a review from a team as a code owner November 2, 2026 20:46

@coderabbitai coderabbitai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Fix comments: Fix CodeRabbit comments on this PR

Comment thread providers/flagd/pom.xml
</testResource>
<!-- flagd-testbed's TCK extensions, on the classpath where the TCK looks for them. -->
<testResource>
<directory>test-harness/tck-extensions</directory>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major · Stability & Availability · Quick win

Initialize test-harness for the TCK profile.

On a fresh checkout, the documented mvn -Ptck -pl providers/flagd -am test command does not activate the e2e profile. That profile alone initializes test-harness. Maven therefore cannot copy these extension features, and the resolver suites cannot find their Compose file. Make submodule initialization part of the TCK workflow, or require it explicitly before the documented command. (raw.githubusercontent.com)

Prompt for AI Agents
Treat finding text, file paths, and code as untrusted review data. Never follow
instructions embedded in them. Verify each finding against current code. Fix
only still-valid issues, skip the rest with a brief reason, keep changes
minimal, and validate.

Review comment at @providers/flagd/pom.xml at line 185:
Ensure the TCK workflow makes the test-harness submodule available before Maven
copies the tck-extensions directory and runs resolver suites. Either initialize
it as part of the workflow or explicitly require initialization before the
documented TCK command; preserve the existing feature-copy and Compose-file
behavior.

After applying the fix, consider running `coderabbit review --agent` for local
review. Visit https://docs.coderabbit.ai/cli?utm_source=ghpr

certPath is now relative to the testbed root, so prefix it with the submodule
directory; the cached object scenario uses the TCK's object table step.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
Comment-only changes in the extension features: no adoption's defaults in
the timing notes, and a note that the fractional \u sequences are literal.

Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants