Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
73c243c
Add picocli to project
janhoy Apr 5, 2026
3cbac74
Add sha and license for picocli
janhoy Apr 5, 2026
cb41a69
Add changelog entry for SOLR-17697
janhoy Apr 5, 2026
79feaf5
Enable picocli for start, stop, status, version and zk ls
janhoy Apr 5, 2026
8c23c9f
SOLR-17697 Remove eager ZK connection from CliDefaultValueProvider (#…
janhoy Apr 6, 2026
bae63d4
SOLR-17697 Enable picocli for remaining zk sub commands (#4267)
janhoy Apr 7, 2026
5cd2ab3
SOLR-17697 Remove --version option for all tools except top-level bin…
janhoy Apr 9, 2026
41292ce
SOLR-17697 Implement picocli for create and delete commands (#4269)
janhoy May 14, 2026
f6d6f5f
SOLR-17697 Ref-guide documentation for new picocli commands (#4271)
janhoy May 15, 2026
ecde8f1
Fix precommit
janhoy May 15, 2026
d113b0f
SOLR-17697: visually flag required options (#4433)
epugh May 18, 2026
b064eb6
Spike of supporting longer option description for ref guide and short…
epugh Jun 21, 2026
76cb327
Merge remote-tracking branch 'upstream/main' into jira/SOLR-17697-pic…
janhoy Jul 30, 2026
1b51884
Update lockfiles for jar-checks Copy configurations after merging main
janhoy Jul 30, 2026
b990f9f
Post-merge review fixes: align DeleteTool/CreateTool with main's Conf…
janhoy Jul 30, 2026
6f680d3
SOLR-17697: Bring picocli path to parity with main's --solr-connectio…
janhoy Jul 30, 2026
3784607
Fix Error Prone UnnecessarilyFullyQualified violations failing CI
janhoy Jul 30, 2026
4ec40c9
Fix dropped --credentials in StatusTool.waitToSeeSolrUp
janhoy Jul 30, 2026
4ab0149
Fix CLI docs generation under Gradle 9 and regenerate CLI ref-guide p…
janhoy Jul 30, 2026
91c9460
SOLR-17697: Implement picocli for auth command / AuthTool (#4684)
janhoy Aug 3, 2026
e5cef69
Merge branch 'main' into jira/SOLR-17697-picocli
janhoy Aug 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
8 changes: 8 additions & 0 deletions changelog/unreleased/SOLR-17697-picocli.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
title: Add picocli as a dependency to enable migration of CLI tools away from commons-cli
type: other
authors:
- name: Jan Høydahl
url: https://home.apache.org/phonebook.html?uid=janhoy
links:
- name: SOLR-17697
url: https://issues.apache.org/jira/browse/SOLR-17697
32 changes: 32 additions & 0 deletions dev-docs/ref-guide/antora.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,38 @@ Instead, update `antora.template.yaml`, and `gradlew buildLocalSite` will build

The only reason you will likely need to change the `antora.template.yml` is if you are introducing new variables for dependency versions.

== Auto-generated CLI Reference Pages

The `bin/solr` command-line tool documentation is partially auto-generated from the picocli `@Command`, `@Option`, and `@Parameters` annotations in the Java source.

=== How it works

For each command registered in `org.apache.solr.cli.SolrCLI` that uses picocli annotations, a dedicated AsciiDoc page is generated by `picocli.codegen.docgen.manpage.ManPageGenerator` and committed to:

----
solr/solr-ref-guide/modules/deployment-guide/pages/cli/
----

The generated pages are post-processed to be Antora-compatible (correct page title, `:page-toclevels:` attribute, ASF license header, DO NOT EDIT notice).
The navigation section in `deployment-nav.adoc` between the `// CLI-DOCS-START` and `// CLI-DOCS-END` markers is also updated automatically.

The main landing page `solr-control-script-reference.adoc` provides an overview of the available tools with links to each man-page.

=== Gradle targets

`./gradlew :solr:solr-ref-guide:generateCliDocs`::
Regenerates all pages under `pages/cli/` from the current picocli annotations and updates the nav.
Run this after modifying any `@Command`, `@Option`, or `@Parameters` annotation in `solr/core/src/java/org/apache/solr/cli/`.

`./gradlew :solr:solr-ref-guide:checkCliDocsUpToDate`::
Verifies that the committed pages in `pages/cli/` are in sync with the current annotations.
This target is wired into `gradlew check`, so CI will catch annotation changes that were not followed by a `generateCliDocs` run.

=== Adding docs for a new tool

The new command will automatically appear in the generated pages and the navigation when running `gradlew generateCliDocs`.
You will need to tie it in to the `solr-control-script-reference.adoc` yourself.

== Building the HTML Site

A Gradle target `gradlew buildLocalSite` will build the full HTML site (found in `solr/solr-ref-guide/build/site`).
Expand Down
3 changes: 2 additions & 1 deletion gradle/java/javac.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ allprojects {
"-Xlint:text-blocks",
"-proc:none", // proc:none was added because of LOG4J2-1925 / JDK-8186647
"-Xlint:removal",
"--should-stop=ifError=FLOW" // error-prone 2.41
"--should-stop=ifError=FLOW", // error-prone 2.41
"-Aproject=${project.group}/${project.name}"
]

if (propertyOrDefault("javac.failOnWarnings", true).toBoolean()) {
Expand Down
3 changes: 3 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ ow2-asm = "9.10.1"
owasp-dependencycheck = "12.2.2"
# @keep for version alignment
perfmark = "0.27.0"
picocli = "4.7.6"
prometheus-metrics = "1.1.0"
quicktheories = "0.26"
semver4j = "6.0.0"
Expand Down Expand Up @@ -504,6 +505,8 @@ ow2-asm-commons = { module = "org.ow2.asm:asm-commons", version.ref = "ow2-asm"
ow2-asm-tree = { module = "org.ow2.asm:asm-tree", version.ref = "ow2-asm" }
# @keep transitive dependency for version alignment
perfmark-api = { module = "io.perfmark:perfmark-api", version.ref = "perfmark" }
picocli = { module = "info.picocli:picocli", version.ref = "picocli" }
picocli-codegen = { module = "info.picocli:picocli-codegen", version.ref = "picocli" }
prometheus-metrics-expositionformats = { module = "io.prometheus:prometheus-metrics-exposition-formats", version.ref = "prometheus-metrics" }
prometheus-metrics-model = { module = "io.prometheus:prometheus-metrics-model", version.ref = "prometheus-metrics" }
quicktheories-quicktheories = { module = "org.quicktheories:quicktheories", version.ref = "quicktheories" }
Expand Down
1 change: 1 addition & 0 deletions solr/api/gradle.lockfile
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ com.tdunning:t-digest:3.3=jarValidation,testRuntimeClasspath
commons-cli:commons-cli:1.11.0=jarValidation,testRuntimeClasspath
commons-codec:commons-codec:1.22.0=jarValidation,testRuntimeClasspath
commons-io:commons-io:2.22.0=jarValidation,testCompileClasspath,testRuntimeClasspath
info.picocli:picocli:4.7.6=jarValidation,testRuntimeClasspath
io.dropwizard.metrics:metrics-core:4.2.39=jarValidation,testRuntimeClasspath
io.github.classgraph:classgraph:4.8.184=swaggerBuild
io.github.eisop:dataflow-errorprone:3.41.0-eisop1=annotationProcessor,errorprone,testAnnotationProcessor
Expand Down
1 change: 1 addition & 0 deletions solr/benchmark/gradle.lockfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ com.tdunning:t-digest:3.3=jarValidation,runtimeClasspath,testRuntimeClasspath
commons-cli:commons-cli:1.11.0=jarValidation,runtimeClasspath,testRuntimeClasspath
commons-codec:commons-codec:1.22.0=jarValidation,runtimeClasspath,testRuntimeClasspath
commons-io:commons-io:2.22.0=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
info.picocli:picocli:4.7.6=jarValidation,runtimeClasspath,testRuntimeClasspath
io.dropwizard.metrics:metrics-core:4.2.39=jarValidation,runtimeClasspath,testRuntimeClasspath
io.github.eisop:dataflow-errorprone:3.41.0-eisop1=annotationProcessor,errorprone,testAnnotationProcessor
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,errorprone,testAnnotationProcessor
Expand Down
6 changes: 5 additions & 1 deletion solr/bin/solr
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,11 @@ if [ $# -gt 0 ]; then
shift 2
;;
-h|--help)
print_usage "$SCRIPT_CMD"
if [[ "${SOLR_PICOCLI:-}" == "true" ]]; then
run_tool "$SCRIPT_CMD" --help
else
print_usage "$SCRIPT_CMD"
fi
exit 0
;;
-y|--no-prompt)
Expand Down
18 changes: 16 additions & 2 deletions solr/bin/solr.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -417,8 +417,22 @@ IF "%1"=="--all" goto set_stop_all
:parse_general_args

REM Print usage of command in case help option included
IF "%1"=="--help" goto usage
IF "%1"=="-h" goto usage
IF "%1"=="--help" goto check_picocli_help
IF "%1"=="-h" goto check_picocli_help
goto after_help_check

:check_picocli_help
IF "%SOLR_PICOCLI%"=="true" goto run_picocli_help
goto usage

:run_picocli_help
"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% %SOLR_TOOL_OPTS% -Dsolr.install.dir="%SOLR_TIP%" ^
-Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^
-classpath "%SOLR_TIP%\lib\*;%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^
org.apache.solr.cli.SolrCLI %SCRIPT_CMD% --help
goto done

:after_help_check

REM other args supported by all special commands
IF "%1"=="-p" goto set_port
Expand Down
22 changes: 22 additions & 0 deletions solr/core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ dependencies {
implementation libs.commonscodec.commonscodec

implementation libs.commonscli.commonscli
implementation libs.picocli
annotationProcessor libs.picocli.codegen

implementation libs.locationtech.spatial4j

Expand Down Expand Up @@ -200,3 +202,23 @@ dependencies {

testImplementation libs.opentelemetry.sdk.testing
}

// Expose a configuration for CLI doc generation in the solr-ref-guide project.
// This bundles the full runtime classpath plus picocli-codegen (ManPageGenerator)
// and the compiled CLI classes so that generateCliDocs can invoke ManPageGenerator.
configurations {
cliDocsRuntime {
canBeResolved = true
canBeConsumed = true
// Inherit all runtime dependencies (implementation + runtimeOnly transitively)
extendsFrom configurations.runtimeClasspath
}
}

dependencies {
// picocli-codegen provides ManPageGenerator (not in runtime, only needed for doc gen)
cliDocsRuntime libs.picocli.codegen
// Include the compiled CLI classes themselves
cliDocsRuntime files(sourceSets.main.output.classesDirs)
cliDocsRuntime files(sourceSets.main.output.resourcesDir)
}
Loading
Loading