feat(batch): add batch workspace analysis action and settings UI#253
feat(batch): add batch workspace analysis action and settings UI#253a-oren wants to merge 3 commits intoredhat-developer:mainfrom
Conversation
Add a new "Batch Workspace Analysis Report" action that triggers batch stack analysis on all packages in a JS/TS monorepo or Cargo workspace from the project root. The action validates workspace layout before calling the API and shows a warning dialog for unsupported projects. Includes batch-specific settings (concurrency, continueOnError, metadata) in the settings UI, a dedicated setBatchRequestProperties() method in ApiService, and tests for both the API delegation and settings defaults. Upgrades trustify-da-java-client to 0.0.16-SNAPSHOT for the batch API, Java target to 21 for bytecode compatibility, and Mockito to 5.x for Java 21 support. Implements TC-3865 Assisted-by: Claude Code
Review Summary by QodoAdd batch workspace analysis action with settings UI and Java 21 support
WalkthroughsDescription• Add batch workspace analysis action for JS/TS monorepos and Cargo workspaces • Implement batch-specific settings UI (concurrency, continueOnError, metadata) • Add workspace layout validation with user-friendly warning dialogs • Upgrade Java target to 21, trustify-da-java-client to 0.0.16-SNAPSHOT, Mockito to 5.x Diagramflowchart LR
A["SaBatchAction"] -->|validates workspace| B["isSupportedWorkspace"]
A -->|calls| C["ApiService.getBatchStackAnalysis"]
C -->|sets properties| D["setBatchRequestProperties"]
D -->|reads| E["ApiSettingsState batch settings"]
C -->|delegates to| F["ExhortApi.stackAnalysisBatchHtml"]
F -->|returns| G["HTML Report"]
A -->|displays| H["AnalyticsReportUtils.openCustomEditor"]
I["ApiSettingsComponent"] -->|manages UI| E
J["ApiSettingsConfigurable"] -->|persists| E
File Changes1. src/main/java/org/jboss/tools/intellij/exhort/ApiService.java
|
Code Review by Qodo
1. Java target set to 21
|
| sourceCompatibility = JavaVersion.VERSION_21 | ||
| targetCompatibility = JavaVersion.VERSION_21 |
There was a problem hiding this comment.
1. Java target set to 21 📎 Requirement gap ⚙ Maintainability
The build configuration changes the project source/target compatibility to Java 21, which violates the repository convention requirement to target Java 17.
Agent Prompt
## Issue description
The project is configured to build with Java 21, but the repository convention requires Java 17.
## Issue Context
This PR changed Gradle `sourceCompatibility`/`targetCompatibility` to `VERSION_21`.
## Fix Focus Areas
- build.gradle.kts[17-18]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
There was a problem hiding this comment.
This change is required because trustify-da-java-client 0.0.16-SNAPSHOT is compiled with maven.compiler.release=21 (upgraded in guacsec/trustify-da-java-client#390). Building with Java 17 fails with class file has wrong version 65.0, should be 61.0. We need to match the client's Java target to use the batch API.
| void setBatchRequestProperties() { | ||
| String ideName = ApplicationInfo.getInstance().getFullApplicationName(); | ||
| PluginDescriptor pluginDescriptor = PluginManagerCore.getPlugin(PluginId.getId("org.jboss.tools.intellij.analytics")); | ||
| if (pluginDescriptor != null) { | ||
| String pluginName = pluginDescriptor.getName() + " " + pluginDescriptor.getVersion(); | ||
| System.setProperty("TRUST_DA_SOURCE", ideName + " / " + pluginName); | ||
| } else { | ||
| System.setProperty("TRUST_DA_SOURCE", ideName); | ||
| } | ||
|
|
||
| ApiSettingsState settings = ApiSettingsState.getInstance(); | ||
| System.setProperty("TRUST_DA_TOKEN", settings.rhdaToken); | ||
|
|
||
| setBackendUrl(); | ||
|
|
||
| if (settings.batchConcurrency != null && !settings.batchConcurrency.isBlank()) { | ||
| System.setProperty("TRUSTIFY_DA_BATCH_CONCURRENCY", settings.batchConcurrency); | ||
| } else { | ||
| System.setProperty("TRUSTIFY_DA_BATCH_CONCURRENCY", "10"); | ||
| } | ||
| System.setProperty("TRUSTIFY_DA_CONTINUE_ON_ERROR", String.valueOf(settings.batchContinueOnError)); | ||
| System.setProperty("TRUSTIFY_DA_BATCH_METADATA", String.valueOf(settings.batchMetadata)); | ||
|
|
||
| // Set tool paths needed for batch analysis | ||
| if (settings.npmPath != null && !settings.npmPath.isBlank()) { | ||
| System.setProperty("TRUSTIFY_DA_NPM_PATH", settings.npmPath); | ||
| } else { | ||
| System.clearProperty("TRUSTIFY_DA_NPM_PATH"); | ||
| } | ||
| if (settings.yarnPath != null && !settings.yarnPath.isBlank()) { | ||
| System.setProperty("TRUSTIFY_DA_YARN_PATH", settings.yarnPath); | ||
| } else { | ||
| System.clearProperty("TRUSTIFY_DA_YARN_PATH"); | ||
| } | ||
| if (settings.nodePath != null && !settings.nodePath.isBlank()) { | ||
| System.setProperty("NODE_HOME", settings.nodePath); | ||
| } else { | ||
| System.clearProperty("NODE_HOME"); | ||
| } | ||
| if (settings.pnpmPath != null && !settings.pnpmPath.isBlank()) { | ||
| System.setProperty("TRUSTIFY_DA_PNPM_PATH", settings.pnpmPath); | ||
| } else { | ||
| System.clearProperty("TRUSTIFY_DA_PNPM_PATH"); | ||
| } | ||
| if (settings.cargoPath != null && !settings.cargoPath.isBlank()) { | ||
| System.setProperty("TRUSTIFY_DA_CARGO_PATH", settings.cargoPath); | ||
| } else { | ||
| System.clearProperty("TRUSTIFY_DA_CARGO_PATH"); | ||
| } | ||
|
|
||
| Optional<String> proxyUrlOpt = getProxyUrl(); | ||
| if (proxyUrlOpt.isPresent()) { | ||
| System.setProperty("TRUSTIFY_DA_PROXY_URL", proxyUrlOpt.get()); | ||
| } else { | ||
| System.clearProperty("TRUSTIFY_DA_PROXY_URL"); | ||
| } | ||
| } |
There was a problem hiding this comment.
3. Global property race 🐞 Bug ☼ Reliability
ApiService.setBatchRequestProperties mutates JVM-wide System properties from a project-scoped service, so concurrent analyses (or multiple open projects) can overwrite each other’s token/tool-path/batch settings mid-request. This can lead to incorrect analysis behavior (wrong backend settings, wrong tool paths) and hard-to-debug cross-project interference.
Agent Prompt
## Issue description
`ApiService` is `@Service(PROJECT)` but configures the Trustify client via JVM-global `System.setProperty/clearProperty`. This is vulnerable to races/interleaving when multiple analyses run concurrently (or multiple projects are open), causing one analysis to run with another analysis' configuration.
## Issue Context
This PR introduces `setBatchRequestProperties()` which sets additional global keys (batch concurrency, continueOnError, metadata). The existing stack/component analysis already uses the same global-property pattern, so batch analysis increases the surface area for cross-call contamination.
## Fix Focus Areas
- Implement a small utility to (a) snapshot relevant System properties, (b) set required properties, (c) perform the API call, (d) restore the snapshot in a `finally` block.
- Serialize property mutations + API invocation with a static lock to prevent interleaving.
- Apply the same mechanism to both `setRequestProperties(...)` call sites and the new batch call path.
### Focus areas (paths/lines)
- src/main/java/org/jboss/tools/intellij/exhort/ApiService.java[71-122]
- src/main/java/org/jboss/tools/intellij/exhort/ApiService.java[159-308]
- src/main/java/org/jboss/tools/intellij/exhort/ApiService.java[310-366]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
There was a problem hiding this comment.
The global System.setProperty pattern is pre-existing- setRequestProperties() (used by stack and component analysis) has the same thread-safety concern. setBatchRequestProperties() follows the established convention.
Replace Messages.showErrorDialog and Messages.showWarningDialog with NotificationGroupManager notifications using the existing "Red Hat Dependency Analytics" notification group, matching the pattern used in ReportFileManager. Implements TC-3865 Assisted-by: Claude Code
Add batch analysis feature and settings documentation to README.md, batch telemetry events to USAGE_DATA.md, and batch analysis quick start entry to plugin.xml description. Implements TC-3865 Assisted-by: Claude Code
|
ruromero
left a comment
There was a problem hiding this comment.
only one refactoring comment, the rest looks good
| } | ||
| } | ||
|
|
||
| void setBatchRequestProperties() { |
There was a problem hiding this comment.
this method shares most of the code with setRequestProperties
Actually this one leaves out the Java, Gradle, Maven, and other properties. It is true that this is not supported it's not a problem to configure the properties in the same way.
The only difference is the concurrency which can also be configured in both cases (stack and batchStack).
The image.ApiService has the same duplication logic. I don't see any problem in configuring all the properties in a common place unless you see any contradiction.
The 3 methods are doing the same:
- Setup the plugin descriptor
- Configure the backend
- Set System properties based on user settings



Summary
Test plan
JAVA_HOME=/usr/lib/jvm/java-21-openjdk ./gradlew build)test-workspace) — report opens with vulnerabilitiestest-plain-java) — shows warning dialog instead of cryptic errortest-no-lockfile) — shows warning dialogImplements TC-3865
🤖 Generated with Claude Code