Skip to content

feat/v2-deprecations: Warn on legacy config knobs and flip docs to v2#22

Merged
vedanthvdev merged 1 commit intomasterfrom
feat/v2-deprecations
Apr 22, 2026
Merged

feat/v2-deprecations: Warn on legacy config knobs and flip docs to v2#22
vedanthvdev merged 1 commit intomasterfrom
feat/v2-deprecations

Conversation

@vedanthvdev
Copy link
Copy Markdown
Owner

Summary

Phase 2 of the v2 rollout per docs/DESIGN-v2.md §4 — signal that v1 config is on its way out without breaking any existing build.

Three things:

  1. Per-run deprecation warnings for callers who explicitly set runAllIfNoMatches, runAllOnNonJavaChange, or excludePaths. Zero-config installs stay silent.
  2. README examples flipped to v2. Legacy knobs removed from the main config sample and the AffectedTestsExtension javadoc. Behaviour-reference table drops the legacy-flag mentions from its "override knob" column.
  3. README Migration section expanded with a deprecation timeline, before/after table, worked example, and a per-knob decision tree.

What the warnings look like

WARNING: [affected-tests] 'runAllIfNoMatches' is deprecated and will be removed in v2.0.0.
  Replace it with per-situation actions (onEmptyDiff / onAllFilesIgnored /
  onAllFilesOutOfScope / onDiscoveryEmpty), each set to 'full_suite' to match
  runAllIfNoMatches=true, or 'skipped' to match runAllIfNoMatches=false.
  See README.md section 'Migrating from v1 config'.

WARNING: [affected-tests] 'runAllOnNonJavaChange' is deprecated and will be removed in v2.0.0.
  Replace it with 'onUnmappedFile' (full_suite / selected / skipped).
  See README.md section 'Migrating from v1 config'.

WARNING: [affected-tests] 'excludePaths' is deprecated and will be removed in v2.0.0.
  Rename it to 'ignorePaths' — identical semantics, and leaving it unset picks up
  the broader v2 default list (markdown, generated/, licence/changelog, images).
  See README.md section 'Migrating from v1 config'.

Emitted via `Logger.warn(...)` on every `affectedTest` run, immediately before the summary line so the warning sits adjacent to the config it describes. Gradle's deprecation dashboard and build-scan `warnings` stream pick this up as a first-class warning (not an info line).

Why the detection is on *caller intent*, not resolution path

The config builder uses `Boolean` / `List` nullable backing fields for the legacy setters. `deprecationWarnings()` is populated by inspecting those nullables directly — `null` means "caller never typed it", non-null means "caller typed it".

This matters: zero-config installs still internally route through the legacy-boolean shim (because the effective `onEmptyDiff` default etc. is derived from the `runAllIfNoMatches=false` hardcoded fallback). If the detection were based on the shim walking that path, we'd spam a warning on every zero-config build and train users to ignore deprecations before the real ones land. Instead, only callers who actually typed the old name in their `build.gradle` see anything.

Migration guide highlights

The new README section boils down to one insight: for 95% of legacy configs, a single `mode = "ci"` line replaces both booleans. The decision tree covers the remaining 5% (specifically: `runAllIfNoMatches=false` → just delete it; `runAllOnNonJavaChange=false` → `onUnmappedFile = "selected"`).

Before:
```groovy
affectedTests {
runAllIfNoMatches = true
runAllOnNonJavaChange = true
excludePaths = ["/generated/"]
transitiveDepth = 4
}
```

After:
```groovy
affectedTests {
mode = "ci"
}
```

(v2's `ignorePaths` default already covers `/generated/`, and `transitiveDepth = 4` is the new default.)

Tests

  • `AffectedTestsConfigTest` gains 7 new tests locking down:
    • Zero warnings for zero-config builds (the key back-compat guarantee).
    • One warning per legacy knob, each containing the knob name and the v2 replacement name in its text.
    • Stable ordering (runAllIfNoMatches → runAllOnNonJavaChange → excludePaths) when multiple are set, so CI log greps stay deterministic.
    • The warnings list is unmodifiable — prevents the Gradle task from accidentally mutating a shared config.
    • v2-native configs (mode, onXxx, ignorePaths, outOfScope\*) emit zero warnings, so migrators have a clear target.

Deprecation timeline

Release Behaviour
v1.9.x and earlier Legacy knobs work silently.
v1.10.x (this PR) Legacy knobs still work. Per-run `WARNING` names each one and its replacement. Zero-config users see nothing.
v2.0.0 (next major) Legacy knobs removed. Gradle will fail configuration if any of them appear in `build.gradle`.

Test plan

  • `./gradlew check` (core + gradle unit + functionalTest + validatePlugins) passes locally.
  • CI run on this branch stays green.
  • Verify on the existing Modulr security-service MR that switching to `mode = "ci"` + removing the legacy flags produces the same effective behaviour.

Phase 2 of the v2 rollout per docs/DESIGN-v2.md §4: surface
deprecation warnings for the three legacy config knobs
(runAllIfNoMatches, runAllOnNonJavaChange, excludePaths) without
breaking any existing build, and flip every documentation example
to the v2 vocabulary so new users only see the supported API.

AffectedTestsConfig now exposes a deprecationWarnings() list
populated at build time by detecting which nullable builder fields
the caller explicitly touched. Zero-config installs produce zero
warnings even though the effective config still resolves via the
legacy-boolean shim — the list tracks caller intent, not the
engine's resolution path, so builds that never typed the old names
stay silent. The AffectedTestTask emits each warning through
getLogger().warn() right before the summary line so the message
sits adjacent to the config it describes. Each warning names the
deprecated knob, the removal version (v2.0.0), and the v2
replacement (onEmptyDiff/onDiscoveryEmpty, onUnmappedFile, or
ignorePaths) so operators can fix their build.gradle from the log
alone.

The README gains a full "Migrating from v1 config" section with a
deprecation timeline, before/after table, worked example (single
mode="ci" line replaces two legacy booleans in the common case),
and a decision tree for each legacy knob. The main configuration
example drops the "Legacy booleans (still supported)" block so new
users only see v2 vocabulary, and the AffectedTestsExtension
javadoc sample flips to mode + onXxx + ignorePaths + outOfScopeTestDirs.
The behaviour reference table also updates its "override knob"
column to name v2 knobs instead of the legacy flags.

Seven new tests in AffectedTestsConfigTest lock down the contract:
zero warnings for zero-config builds, one warning per legacy knob
(each containing the knob name and the v2 replacement), stable
ordering when multiple legacy knobs are set, and an immutability
guard so the task cannot accidentally leak mutations to the list.
@vedanthvdev vedanthvdev merged commit 4edf0dd into master Apr 22, 2026
1 check passed
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.

1 participant