Skip to content

SOLR-18515 | PackageTool Migration to PicoCLI - #5047

Open
jaykay12 wants to merge 21 commits into
apache:mainfrom
jaykay12:SOLR-18515-PackageTool
Open

jaykay12 wants to merge 21 commits into
apache:mainfrom
jaykay12:SOLR-18515-PackageTool

Conversation

@jaykay12

@jaykay12 jaykay12 commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Description

Implementing PicoCLI for the PackageTool

Past PR for reference (some code review took place here) - #4739

Solution

Used Prompt provided in the Jira & got initial migration done by Cursor.

Majoryly, common code which was being used in the commons-cli call path, which could be used in picocli as well, is being refactored to private functions.

#4739 (comment)

Tests

Please describe the tests you've developed or run to confirm this patch implements the feature or solves the problem.

Checklist

Please review the following and check all that apply:

  • I have reviewed the guidelines for How to Contribute and my code conforms to the standards described there to the best of my ability.
  • I have created a Jira issue and added the issue ID to my pull request title.
  • I have given Solr maintainers access to contribute to my PR branch. (optional but recommended, not available for branches on forks living under an organisation)
  • I have developed this patch against the main branch.
  • I have run ./gradlew check.
  • I have added tests for my changes.
  • I have added documentation for the Reference Guide
  • I have added a changelog entry for my change

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests cat:cli labels Oct 6, 2026
@jaykay12

jaykay12 commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

@janhoy can please trigger the workflows on this PR?

[pending-on-me] test these commands locally with respect to main

@jaykay12 jaykay12 changed the title SOLR-18515 | Implement PicoCLI for package command / PackageTool SOLR-18515 | PackageTool Migration to PicoCLI Oct 7, 2026
@jaykay12

jaykay12 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor Author

List-Available

Command main branch picoCLI enabled feature branch
Happy Path Screenshot 2026-10-07 at 9 17 31 AM Screenshot 2026-10-07 at 10 00 57 AM
- - -
Failure Path Screenshot 2026-10-07 at 9 17 44 AM Screenshot 2026-10-07 at 10 01 49 AM

@jaykay12

jaykay12 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor Author

Add-Repo

Command main branch picoCLI enabled feature branch
Happy Path Screenshot 2026-10-07 at 9 54 12 AM Screenshot 2026-10-07 at 10 03 32 AM
- - -
Failure Path Screenshot 2026-10-07 at 9 54 59 AM Screenshot 2026-10-07 at 10 04 30 AM

@jaykay12

jaykay12 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor Author

Add-Key

Command main branch picoCLI enabled feature branch
Happy Path Screenshot 2026-10-07 at 10 13 29 AM Screenshot 2026-10-07 at 11 47 26 AM
- - -
Failure Path Screenshot 2026-10-07 at 10 13 41 AM Screenshot 2026-10-07 at 11 48 33 AM

@jaykay12

jaykay12 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor Author

List-Installed

Command main branch picoCLI enabled feature branch
Happy Path Screenshot 2026-10-07 at 10 18 36 AM Screenshot 2026-10-07 at 11 53 28 AM
- - -
Failure Path Screenshot 2026-10-07 at 10 28 05 AM Screenshot 2026-10-07 at 11 54 22 AM

@jaykay12

jaykay12 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor Author

Install

Command main branch picoCLI enabled feature branch
Functional Correctness Screenshot 2026-10-07 at 10 18 36 AM Screenshot 2026-10-07 at 11 53 28 AM
- - -
Happy Path Screenshot 2026-10-07 at 10 19 40 AM Screenshot 2026-10-07 at 11 58 43 AM
- - -
Failure Path Screenshot 2026-10-07 at 10 21 07 AM Screenshot 2026-10-07 at 11 59 42 AM

@jaykay12

jaykay12 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor Author

Uninstall

This was not being getting tested properly from local, raised bug fix PR: #5052 for the same & continued testing using that patch over main & feature branch.

Command main branch picoCLI enabled feature branch
Functional Correctness(Happy Path) Screenshot 2026-10-07 at 11 29 50 AM Screenshot 2026-10-07 at 12 08 16 PM
- - -
Failure Path Screenshot 2026-10-07 at 11 31 07 AM Screenshot 2026-10-07 at 12 09 28 PM

@jaykay12

jaykay12 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor Author

List Deployed

Command main branch picoCLI enabled feature branch
Happy Path Screenshot 2026-10-07 at 12 18 03 PM Screenshot 2026-10-07 at 12 41 27 PM
- - -
Failure Path Screenshot 2026-10-07 at 12 19 45 PM Screenshot 2026-10-07 at 12 43 21 PM

@jaykay12

jaykay12 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor Author

Deploy

Command main branch picoCLI enabled feature branch
Happy Path Screenshot 2026-10-07 at 1 02 35 PM Screenshot 2026-10-07 at 12 50 17 PM
- - -
Failure Path Screenshot 2026-10-07 at 12 29 42 PM Screenshot 2026-10-07 at 12 52 58 PM

@jaykay12

jaykay12 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor Author

Undeploy

Command main branch picoCLI enabled feature branch
Happy Path Screenshot 2026-10-07 at 1 03 48 PM Screenshot 2026-10-07 at 12 58 07 PM
- - -
Failure Path Screenshot 2026-10-07 at 12 33 08 PM Screenshot 2026-10-07 at 12 56 33 PM

@dsmiley dsmiley left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

wow; one ref guide page per command? It has a javadoc feel to me that I wonder should be published separately, not unlike how javadoc is separated from the ref guide. Maybe we don't need ref guide pages if the CLI is self documenting. Less to maintain!
CC @epugh @janhoy

Comment thread solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java Outdated
janhoy added 2 commits October 7, 2026 19:47
Main renamed the key from 'solr-connection' to 'solr.connection' in apache#5054;
EnvUtils maps SOLR_FOO -> solr.foo, so the hyphenated key was never set.
@janhoy

janhoy commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

The BATS tests fail, not because of this PR but a pre-existing bug, already fixed on main. I'll merge in main here now.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Connection resolution can mix clusters, and generated documentation displays invalid command syntax.

2 open findings
What changed in this PR

Migrates PackageTool to native picocli subcommands while retaining commons-cli compatibility.

Changes:

  • Adds nine package subcommands with shared connection and manager handling.
  • Reuses integration tests across both parser paths.
  • Adds generated CLI documentation and a changelog entry.
File Description
solr-package.adoc Documents the package command.
solr-package-uninstall.adoc Documents uninstall.
solr-package-undeploy.adoc Documents undeploy.
solr-package-list-installed.adoc Documents installed-package listing.
solr-package-list-deployed.adoc Documents deployment listing.
solr-package-list-available.adoc Documents available-package listing.
solr-package-install.adoc Documents installation.
solr-package-deploy.adoc Documents deployment.
solr-package-add-repo.adoc Documents repository addition.
solr-package-add-key.adoc Documents trusted-key addition.
cli/​index.adoc Lists migrated package commands.
deployment-nav.adoc Adds package documentation navigation.
PackageToolTest.java Makes tests reusable between parsers.
PackageToolPicocliTest.java Runs shared tests through picocli.
SolrCLI.java Registers PackageTool.
PackageUninstall.java Implements uninstall parsing.
PackageUndeploy.java Implements undeploy parsing.
PackageTool.java Refactors shared package operations.
PackageSubCommand.java Provides shared subcommand wiring.
PackageListInstalled.java Implements installed-package listing.
PackageListDeployed.java Implements deployment listing.
PackageListAvailable.java Implements available-package listing.
PackageInstall.java Implements installation parsing.
PackageDeploy.java Implements deployment parsing.
PackageAddRepo.java Implements repository addition.
PackageAddKey.java Implements trusted-key addition.
ConnectionOptions.java Adds package connection resolution.
SOLR-18515-package-tool-picocli.yml Records the migration.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread solr/core/src/java/org/apache/solr/cli/ConnectionOptions.java
Comment on lines +65 to +69
|xref:cli/solr-package-add-key.adoc[bin/solr package add key]
|xref:cli/solr-package-add-repo.adoc[bin/solr package add repo]
|xref:cli/solr-package-deploy.adoc[bin/solr package deploy]
|xref:cli/solr-package-install.adoc[bin/solr package install]
|xref:cli/solr-package-list-available.adoc[bin/solr package list available]

@jaykay12 jaykay12 Oct 8, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@janhoy will that be okay, if i take this up in a follow-up PR?

delta changes here will be clearly visible in the evidences of that PR. That PR will follow-up immediately once this is merged.

Comment thread changelog/unreleased/SOLR-18515-package-tool-picocli.yml Outdated

@jaykay12 jaykay12 left a comment •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

comments addressed ✅
local testing done for all 9 subcommands ✅

@janhoy can you trigger the workflows now? precommit check is passing on local for the most latest changes. verified ✅

@jaykay12
jaykay12 requested a review from janhoy October 8, 2026 12:31
# Conflicts:
#	changelog/unreleased/SOLR-17697-picocli-experimental-cli.yml
#	solr/core/src/java/org/apache/solr/cli/SolrCLI.java
#	solr/solr-ref-guide/modules/deployment-guide/deployment-nav.adoc
#	solr/solr-ref-guide/modules/deployment-guide/pages/cli/index.adoc
@janhoy janhoy added this to the 10.x milestone Oct 8, 2026

@janhoy janhoy left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I merged latest main into the branch to resolve the conflicts with the other picocli ports. Running the full org.apache.solr.cli.* test package turned up one real problem, and a convention pass against the already-merged ports turned up a few more. Details below.

Flaky failure in PackageToolPicocliTest.testPackageTool

PackageToolPicocliTest fails roughly a third of the time (e.g. -Ptests.seed=CE8CB19A405A7699 fails ~3 of 4 runs), while PackageToolTest passes with the same seed. The failing step is the second install question-answer in the random "auto-update to latest" branch, which returns exit code 1 with Failed verification after deployment.

Root cause is a pre-existing race that the commons-cli tool masked: RepositoryManager.install verifies the $LATEST-pegged collections immediately after installing the new version, a few milliseconds before the nodes have reloaded the package, so verify sees Actual: 1.0.0, expected: 1.1.0. The old PackageTool.install() was void, so the legacy path printed installation failed and still exited 0. Your PackageInstall correctly propagates the result, which is the right behavior, but it exposes the race.

I think the fix belongs in RepositoryManager.install: retry the post-install verification with a bounded wait (the reload is asynchronous by design) instead of verifying once. Happy to discuss if you see a better option. Note that testDeployValidationMessages creating validation-test on conf1 also makes it share PKG_VERSIONS with abc, so list-deployed reports it as deployed; isolating it on its own configset is a small tidy-up but does not fix the race on its own.

@janhoy

janhoy commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Flaky failure in PackageToolPicocliTest.testPackageTool

Turns out this is far from a flaky test. It's a race condition with zk watches. My plan is to let Claude make a fix, apply it, merge this to main and then let @jaykay12 handle follow-ups along with the pre-existing bin/solr package list available bug. Hope that is ok with you Jalaz. This is the last tool to land so I want to prep them all for 10.2

A node answering a /cluster/package?expectedVersion=N request could report
itself in sync as soon as its ZK watcher had bumped the packages.json version,
while that watcher thread was still building the classloader for the new
version and reloading plugins. A client that installed a new version and then
verified collections pegged to $LATEST could therefore observe the old
version. Only the exit code of the commons-cli package tool hid this, since it
ignored the install result; the picocli port propagates it.

Make SolrPackageLoader.refreshPackageConf() and notifyListeners() synchronized
and have syncToVersion always go through refreshPackageConf(), so both the
version sync and the explicit refresh command block until any in-flight
application of the new packages.json has completed.
testDeployValidationMessages created validation-test on conf1, shared with
abc, so a deploy to abc also showed up as a deployment on validation-test
through the shared PKG_VERSIONS params. Use a dedicated configset so the two
test methods do not influence each other.
@janhoy

janhoy commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

🤖 Bug fix and pr comment below written by Claude Fable


Flaky PackageToolPicocliTest.testPackageTool and the fix

Running org.apache.solr.cli.* on this branch, PackageToolPicocliTest failed in roughly a third of runs while PackageToolTest always passed. With -Ptests.seed=CE8CB19A405A7699 the picocli test failed 7 of 8 runs. The failing step is the second install question-answer in the random "auto-update to latest" branch of testPackageTool, which exits 1 after Actual: 1.0.0, expected: 1.1.0 / Failed verification after deployment.

This is not a bug in the port. The commons-cli PackageTool.install() was void, so the legacy path printed installation failed and still exited 0, which hid a pre-existing server-side race. The new PackageInstall correctly propagates the result, which is why the test now sees it.

The race. RepositoryManager.install adds the new version through POST /api/cluster/package {add: ...} and then immediately verifies the collections pegged to $LATEST. On the server, PackageAPI.Edit.add writes packages.json and calls notifyAllNodesToSync(znodeVersion), and each node answers via Read.syncToVersion. That method considered a node synced as soon as pkgs.znodeVersion had reached the expected version. But that field is bumped by the node's own ZK watcher thread at the start of refreshPackages, before SolrPackageLoader.refreshPackageConf() has built the new version's classloader and reloaded the plugins. So when the watcher fires first, which is the common case, the sync request returns instantly while the reload is still in flight, add returns to the client, and the verify reads the old plugin version. The explicit refresh command had the same hole: notifyListeners would run against a SolrPackage whose version list the watcher thread had not finished updating, so it reloaded nothing. I first tried posting a refresh from the client before verifying, the way the deploy path does, and it failed deterministically for exactly that reason.

The fix (separate commit on this branch, 3ca62e67c71) is server-side and small:

  • SolrPackageLoader.refreshPackageConf() and notifyListeners() are now synchronized, so a sync or refresh request blocks until any application of packages.json already started by the ZK watcher has completed, and is a no-op afterwards.
  • PackageAPI.Read.syncToVersion always goes through refreshPackageConf() once the expected version is visible, instead of skipping it when the watcher had already bumped the version number.

Lock order stays one-directional (loader monitor, then PackageListeners, then PackagePluginHolder), and nothing on the listener path calls back into the loader, so there is no new deadlock risk.

Verification. The failing seed now passes 8 of 8 runs, both PackageToolTest and PackageToolPicocliTest pass on repeated random seeds, and org.apache.solr.pkg.*, org.apache.solr.filestore.* and TestContainerPlugin all pass. gradlew check -x test is green.

A second small commit (7ee9561c11c) tidies the test: testDeployValidationMessages created validation-test on conf1, the same configset as abc, so after a deploy to abc the package also showed as deployed on validation-test via the shared PKG_VERSIONS params. It now gets its own configset so the two test methods do not influence each other. Both twins pass on repeated runs and list-deployed reports only abc.

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

Labels

cat:cli cat:packagemanager documentation Improvements or additions to documentation tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants