feat/v2-situation-config: Introduce Situation/Action/Mode model for v2 decision tree#19
Merged
vedanthvdev merged 1 commit intomasterfrom Apr 22, 2026
Merged
Conversation
…2 decision tree This commit realises Phase 1 of the v2 design (docs/DESIGN-v2.md) by replacing the two legacy boolean flags (`runAllIfNoMatches`, `runAllOnNonJavaChange`) with a richer per-situation decision model so every user who adopts the plugin can express "selected / full suite / skipped" on each distinct branch the engine can take, without giving up the existing safety net. Three new enums — `Action` (SELECTED, FULL_SUITE, SKIPPED), `Situation` (EMPTY_DIFF, ALL_FILES_IGNORED, ALL_FILES_OUT_OF_SCOPE, UNMAPPED_FILE, DISCOVERY_EMPTY, DISCOVERY_SUCCESS) and `Mode` (AUTO, LOCAL, CI, STRICT) — now drive `AffectedTestsEngine`, which has been rewritten to follow a single top-to-bottom decision tree: ignore the diff → bucket files into ignored / out-of-scope / production / test / unmapped → resolve the matching `Situation` → look up the configured `Action` and either short-circuit (FULL_SUITE or SKIPPED) or continue into discovery. This makes the common cases visible from the log line itself and removes the hidden coupling between the two legacy flags. `PathToClassMapper` and `ProjectIndex` gained first-class support for two new path categories — `ignorePaths` (files that must not influence test selection, e.g. markdown/generated) and `outOfScopeTestDirs` / `outOfScopeSourceDirs` (source sets like `api-test` that are built by a separate Gradle task and must not be dispatched here). The api-test-only regression that used to trigger a full unit-test run now routes to `ALL_FILES_OUT_OF_SCOPE → SKIPPED`, and a docs-only diff now routes to `ALL_FILES_IGNORED → SKIPPED` on zero-config installs because the default ignore list covers `*.md`, `*.txt`, LICENSE, CHANGELOG and common image formats at both the repository root and nested paths. `AffectedTestsConfig` resolves each `Situation → Action` with a strict precedence so nobody silently regresses: explicit v2 settings win; then the two legacy booleans translate into `UNMAPPED_FILE` and `DISCOVERY_EMPTY` actions for users who haven't migrated yet; then the `Mode` profile (CI biases toward FULL_SUITE, LOCAL toward SKIPPED, STRICT is paranoid, AUTO sniffs the `CI` env var) supplies defaults; and finally the pre-v2 hardcoded defaults (`runAllIfNoMatches=true`, `runAllOnNonJavaChange=true`) apply so zero-config users keep their current safety net. Default `transitiveDepth` is raised to 4 to match typical controller→service→repo chains, `implementationNaming` now includes the `Default` prefix idiomatic in Spring code, and the legacy `excludePaths` getter is preserved but aliases `ignorePaths`. The Gradle extension exposes `mode`, `ignorePaths`, `outOfScopeTestDirs`, `outOfScopeSourceDirs` and per-situation overrides (`onEmptyDiff`, `onAllFilesIgnored`, `onAllFilesOutOfScope`, `onUnmappedFile`, `onDiscoveryEmpty`), and the task's escalation log now names both the v2 decision and the legacy flag name for grep compatibility. Tests cover the new routing, the legacy shim, mode defaults, default ignore-path glob coverage at the repo root and the api-test-only scenario end-to-end; the full plugin `./gradlew check` passes with 87 tests. The README and architecture diagram are rewritten alongside the code so new users start with the v2 API (mode, per-situation actions, path buckets, the resolution-priority ladder) and existing users see their legacy flags mapped explicitly to the v2 situations they translate to. The rendered diagram in `docs/architecture.svg` now shows the five decision branches and the four-tier action-resolution ladder.
a6268a8 to
5316b52
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 1 of the v2 design in
docs/DESIGN-v2.md. Replaces the two legacy boolean flags with a richer per-Situationdecision model so users can independently configureSELECTED,FULL_SUITEorSKIPPEDon each distinct branch the engine can take. The legacy flags are still honoured through a shim so zero-config users keep today's safety net.What changes
Action(SELECTED / FULL_SUITE / SKIPPED),Situation(EMPTY_DIFF, ALL_FILES_IGNORED, ALL_FILES_OUT_OF_SCOPE, UNMAPPED_FILE, DISCOVERY_EMPTY, DISCOVERY_SUCCESS) andMode(AUTO / LOCAL / CI / STRICT) drive a rewrittenAffectedTestsEnginethat follows one top-to-bottom decision tree.ignorePaths(files that must not influence selection, e.g.*.md, LICENSE, generated code) andoutOfScopeTestDirs/outOfScopeSourceDirs(e.g.api-test/src/test/java, built by a different Gradle task).PathToClassMappernow buckets a diff into ignored / out-of-scope / production / test / unmapped, andProjectIndexfilters the same dirs so discovery never picks up out-of-scope tests.AffectedTestsConfig: explicit v2 settings > legacy boolean translation > Mode defaults > pre-v2 hardcoded defaults.transitiveDepth=4,implementationNamingnow includesDefault, richerignorePathscovering root-level*.md/*.txt/LICENSE/CHANGELOG/images at both the repo root and nested paths.AffectedTestsExtensionexposesmode,ignorePaths,outOfScopeTestDirs,outOfScopeSourceDirsand per-situation overrides (onEmptyDiff,onAllFilesIgnored,onAllFilesOutOfScope,onUnmappedFile,onDiscoveryEmpty). The escalation log line names both the v2 decision and the legacy flag name for grep compatibility.excludePathsaliasesignorePaths;runAllIfNoMatchesandrunAllOnNonJavaChangecontinue to work and translate intoUNMAPPED_FILE/DISCOVERY_EMPTYactions.README.mdnow leads with the v2Situation/Action/Modemodel, documents the resolution-priority ladder, and maps every legacy flag to the v2 situation it translates to.docs/architecture.svgis regenerated to show the five decision branches and the four-tier action-resolution ladder.Why
The api-test-only regression that used to trigger a full unit-test run now routes to
ALL_FILES_OUT_OF_SCOPE → SKIPPED, and a docs-only diff now routes toALL_FILES_IGNORED → SKIPPEDon zero-config installs — the two scenarios that drove the v2 design.Test plan
./gradlew check(87 tests pass)Mode.CIDISCOVERY_EMPTYPathToClassMapperTestcovers ignored / out-of-scope / unmapped bucketsAffectedTestsConfigTestcovers explicit-situation precedence, legacy boolean shim, mode defaults andignorePathsaliasingexcludePathsAffectedTestTaskLogFormatTestcovers v2 phrasing + legacy grep compatibilitydocs/architecture.svgrewritten to match the shipped v2 API--explaintask flag and richer summary log format — tracked for Phase 1 close-outRelated
docs/DESIGN-v2.md(merged in docs/design-v2: Add v2 design document for scenario-based configuration #18)