Skip to content

SOLR-18302: DAGP external-lib api advice — ILLUSTRATIVE, not for merge (part 3/3)#4614

Closed
serhiy-bzhezytskyy wants to merge 8 commits into
apache:mainfrom
serhiy-bzhezytskyy:dagp-pr3-external-api
Closed

SOLR-18302: DAGP external-lib api advice — ILLUSTRATIVE, not for merge (part 3/3)#4614
serhiy-bzhezytskyy wants to merge 8 commits into
apache:mainfrom
serhiy-bzhezytskyy:dagp-pr3-external-api

Conversation

@serhiy-bzhezytskyy

@serhiy-bzhezytskyy serhiy-bzhezytskyy commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Draft — NOT for merge. Part 3 of 3, for discussion. Builds on #4613#4612.

This applies the remaining ~89 external-library implementation → api promotions that DAGP advises across the modules, so the full picture is visible as code.

Correction to my earlier framing (dev@ thread): I originally described these as the tool being "api-happy." Having actually checked, that was wrong, and I want to be straight about it. I verified every one of the 90 advised external promotions against each module's ABI dump (resolving the real jar packages so coordinate↔package mismatches couldn't hide anything). All 90 are genuinely ABI-exposed — the library type appears in a public return type, parameter, field, or supertype today, regardless of the implementation/api declaration. Examples:

  • caffeineCaffeineCache implements com.github.benmanes.caffeine.cache.RemovalListener
  • zookeeper — ~82 public methods declare throws org.apache.zookeeper.KeeperException
  • jsonpathpublic static Configuration jsonPathConfiguration()
  • simplemagicFileTypeMagicUtil implements ContentInfoUtil.ErrorCallBack
  • kafka-clients (cross-dc) — MirroredSolrRequestSerializer implements kafka Serializer

So this isn't "the tool over-reaching." The real question is one of API hygiene: do we want these types to be part of each module's public contract, or is the exposure accidental and worth encapsulating (narrowing the signatures) instead of promoting? That's the case-by-case judgement, and it's exactly why this is a discussion PR rather than something to merge.

One promotion is genuinely not applicable: DAGP advises jersey-core-serverapi in :solr:core (it is ABI-exposed), but promoting it breaks version resolution — its version comes from the jersey BOM, which is declared implementation, so as api it resolves to no version. Left as implementation here. A real example of advice that's correct about exposure yet can't be applied mechanically.

Suggested use: rather than accept/reject wholesale, point at any deps whose exposure is intended public API and I'll fold just those into #4613; for the rest, the better fix is likely encapsulation, tracked separately.

Layering: #4612 (safe advice, ready) → #4613 (inter-module project() api, all ABI-backed, draft) → this (external api, draft/illustrative).

AI-assisted, human-reviewed and verified per AGENTS.md.

Completes the dependency-analysis follow-up deferred from the Gradle 9 upgrade
(SOLR-18289), which dropped the Gradle-9-incompatible ca.cutterslade.analyze
plugin. Adds the Dependency Analysis Gradle Plugin (com.autonomousapps
build-health) configured to REPORT (warn), not fail — its advice is guidance
for human review, not enforcement.

Applies only the uncontroversial advice:
 - removal of genuinely-unused dependency declarations
 - a few test-scope corrections (implementation -> testImplementation)

Deliberately NOT included here (left for separate case-by-case review):
 - implementation -> api promotions (DAGP is aggressive here; per dev@ these
   need human judgement, as liberal api is viral/transitive)

Also forces kotlin-metadata-jvm to match Solr's Kotlin so DAGP can analyze the
:solr:ui (Compose/KMP) module. Lockfiles regenerated.
…oss-dc-manager tests)

DAGP flagged the kafka-clients test-classifier jar as an unused dependency, so the
earlier commit removed it. That was a false positive: no test compiles against it,
but EmbeddedKafkaCluster (from the kafka-streams test jar) loads
org.apache.kafka.test.TestCondition from it at runtime, so the *IntegrationTest
suites failed with ClassNotFoundException on CI.

Re-add it as testRuntimeOnly (runtime-only is the accurate scope, vs the
testImplementation it originally had) with a comment, and restore its license sha1.
A concrete example of why DAGP runs report-not-fail and its advice needs
case-by-case judgement.
@serhiy-bzhezytskyy serhiy-bzhezytskyy changed the title SOLR-18296: DAGP external-lib api promotions — ILLUSTRATIVE, not for merge (part 3/3) SOLR-18302: DAGP external-lib api advice — ILLUSTRATIVE, not for merge (part 3/3) Jul 7, 2026
…nts, fix changelog

Responding to review feedback on the safe-advice PR:

- Revert all external implementation->api promotions that had leaked in from the
  api-scope work (caffeine, zookeeper, jute, jsonpath, opentelemetry-sdk +
  exporter-prometheus in core; curator-client/jute in solrj-zookeeper; zookeeper
  +tests in test-framework; calcite in sql; cloud-storage in gcs; awssdk-s3 in
  s3). None are in the modules' public ABI and DAGP does not advise them; they
  belong in the separate api-scope discussion PRs, not here. Verified no
  downstream module relies on the former transitive leak.
- Revert solrj-jetty entirely: its changes were api promotions + manual cleanups,
  none part of the safe mechanical advice.
- Restore opentelemetry-sdk-metrics in test-framework: DAGP flagged it unused, but
  JettySolrRunner uses MetricReader from it and the prometheus exporter is
  declared transitive=false, so it is required (compile break otherwise).
- Restore the gjf-SOLR-18296 changelog entry that had been deleted by a rebase
  artifact; it belongs to the separate google-java-format change.
- Remove code comments that narrated the change/tool advice (per AGENTS.md); keep
  only terse why-comments matching existing style.
- Changelog: type changed->other; link to SOLR-18302 (the correct JIRA).
- Regenerate lockfiles/licenses.
…jetty

Remove testImplementation project(':solr:solrj-jetty') (a module test-depending on
itself — the test source set already sees its own main classes) and the duplicate
testImplementation project(':solr:solrj') (already api project(':solr:solrj')). The
project(path: ':solr:solrj', configuration: 'testArtifacts') declaration stays; it
provides solrj's test classes, which is a real dependency. Verified :solr:solrj-jetty
test compiles and all 59 tests pass.
…, doc the lockfile filter

- Convert gradle/validation/dependency-analyze.gradle to Kotlin DSL (.gradle.kts),
  per the project's preference for Kotlin build files. Behavior is unchanged;
  buildHealth runs and all suppressions (:solr:ui, solrj-jetty, jwt-auth,
  report-not-fail) remain active.
- Remove the redundant self-referential testImplementation project(':self')
  declarations in api, solrj, solrj-streaming, solrj-zookeeper, and core (two were
  left-over 'cutterslade requires we state the obvious' workarounds for the plugin
  removed in SOLR-18289). Test source sets already see their own main classes.
- Add a one-line comment explaining why resolveAndLockAll skips the plugin's
  synthetic dagp.* configurations.
- Regenerate the changelog entry with the writeChangelog task so it matches the
  documented format.
Applies DAGP's api advice ONLY for inter-module project() dependencies that are
genuinely part of the consuming module's public API (e.g. solr-core's public
types expose solrj), where 'api' is correct so downstream modules compile.

External-library api promotions are intentionally excluded here (see part 3/3);
per dev@ feedback those need case-by-case judgement rather than blanket promotion.

Builds on apache#4612. Lockfiles regenerated.
…ions (part 3/3)

Applies the 90 external-library implementation->api promotions DAGP advises across
the modules, for discussion. Verified all 90 against each module's ABI dump: every
one is genuinely exposed in public API (return type, parameter, field, or supertype)
today, regardless of the declaration -- e.g. CaffeineCache implements caffeine's
RemovalListener; ~82 core methods throw ZooKeeper's KeeperException. So this is an
api-hygiene question (is the exposure intended, or worth encapsulating?), not the
tool over-reaching.

jersey-core-server is left as implementation: DAGP advises api (it is ABI-exposed),
but its version comes from the implementation-scoped jersey BOM, so as api it fails
to resolve. A concrete case of advice that is correct about exposure yet cannot be
applied mechanically.

Builds on apache#4613. check -x test passes; lockfiles regenerated.
@serhiy-bzhezytskyy

Copy link
Copy Markdown
Contributor Author

Closing per discussion on #4612 — this was always illustrative (the full external-lib api advice for discussion), not for merge. The api-vs-implementation calls are best made case-by-case, not applied wholesale.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant