Skip to content

ADFA-4936: Fix Jacoco/SonarQube workflow (plugin-manager compile + lsp:kotlin OOM) - #1603

Merged
hal-eisen-adfa merged 4 commits into
stagefrom
ADFA-4936-fix-jacoco-workflow
Jul 30, 2026
Merged

ADFA-4936: Fix Jacoco/SonarQube workflow (plugin-manager compile + lsp:kotlin OOM)#1603
hal-eisen-adfa merged 4 commits into
stagefrom
ADFA-4936-fix-jacoco-workflow

Conversation

@hal-eisen-adfa

Copy link
Copy Markdown
Collaborator

Summary

Fixes the nightly Analyze Repository with Jacoco and SonarQube workflow (ADFA-4936). The "Build and analyze" step was failing with two independent task failures under --continue, which skipped jacocoAggregateReport (the "No files were found for jacocoAggregateReport" upload warning) and failed the run with exit 1.

FAILURE: Build completed with 2 failures.
1: Execution failed for task ':plugin-manager:compileV8DebugUnitTestKotlin'. > Compilation error.
2: Execution failed for task ':lsp:kotlin:testV8DebugUnitTest'.              > Timeout has been exceeded

Failure 1 — plugin-manager unit tests didn't compile

The tests referenced a service model removed in an earlier refactor (FileServiceImpl/ProjectServiceImpl/ResourceServiceImpl, IdeResourceService). The impls were rewritten to a pluginId+permissions model (IdeFileServiceImpl, IdeProjectServiceImpl) taking File args and returning raw types; the Resource service was removed outright — so this was a rewrite, not a rename.

  • IdeFileServiceImplTest (replaces FileServiceImplTest) — constructs IdeFileServiceImpl with a permissive PathValidator (the production allowlist only permits fixed on-device roots) and FILESYSTEM_WRITE; covers write/read/replace/delete/list plus disallowed-path and missing-permission SecurityException.
  • E2EIntegrationTest — file workflow through ServiceRegistryImpl.
  • PluginManagerIntegrationTest — registration/retrieval + functional file ops + path-security.
  • Deleted ResourceServiceImplTest — the Resource service no longer exists.

Failure 2 — :lsp:kotlin test suite exhausted memory

KtLspTestRule built a heavy KtLspTestEnvironment (IntelliJ project, application env, FIR infra, background index workers) per test method, but env.close() was disabled — so environments accumulated for the JVM's lifetime. Locally this reproduces as java.lang.OutOfMemoryError after ~130 tests; in CI (larger heap) it manifested as GC-thrash plus a global-analysis-lock waiter crawling past the 10-minute per-task timeout.

  • KtLspTestRule — re-enable env.close(). The original "fails in test cases" was caused by calling it inside project.write { }; close() manages its own threading/locking, so it's called directly now.
  • AnalysisSerializationTest — add @Test(timeout = 60_000) to the two heavy concurrency tests that had no timeout, so a genuine liveness stall fails fast instead of burning the task budget (defense in depth).

No production code changed — both fixes are test-only.

Verification

  • :plugin-manager:testV8DebugUnitTest -> 13 tests, 0 failures
  • :lsp:kotlin:testV8DebugUnitTest -> 169 tests, 0 failures (previously OOM/timeout; the failing CI run only reached 131 before aborting)
  • spotlessCheck clean

Out of scope (follow-up)

While investigating, I found plugin-api's entire unit-test suite is broken by the same refactor (PluginContextTest.kt + 3 *ServiceTest.java referencing removed *OperationResult types). It doesn't affect this workflow because plugin-api has no v8 flavor, so jacocoAggregateReport (keyed on testV8DebugUnitTest) never compiles or runs it. Filing a separate ticket.

The nightly Jacoco/SonarQube workflow failed at :plugin-manager:compileV8DebugUnitTestKotlin: the tests referenced a service model removed in an earlier refactor (FileServiceImpl/ProjectServiceImpl/ResourceServiceImpl and IdeResourceService). Because the sonarqube task depends on jacocoAggregateReport which depends on every subproject's testV8DebugUnitTest, this compile failure skipped the aggregate report (the "no files found for jacocoAggregateReport" upload warning) and failed the run.

The impls were rewritten to a pluginId+permissions model (IdeFileServiceImpl, IdeProjectServiceImpl) that takes File args and returns raw types; the Resource service was removed outright. Rewrite the tests against the current API:

- IdeFileServiceImplTest (replaces FileServiceImplTest): construct IdeFileServiceImpl with a permissive PathValidator (the production allowlist only permits fixed on-device roots) and FILESYSTEM_WRITE; cover write/read/replace/delete/list plus disallowed-path and missing-permission SecurityException.
- E2EIntegrationTest: file-workflow-through-registry against the current API.
- PluginManagerIntegrationTest: service registration/retrieval + functional file ops + path-security.
- Delete ResourceServiceImplTest: the Resource service no longer exists, nothing to rewrite to.

Verified: :plugin-manager:testV8DebugUnitTest -> 13 tests, 0 failures.
The nightly's second failure was :lsp:kotlin:testV8DebugUnitTest exceeding its 10-minute per-task timeout. Root cause: KtLspTestRule built a heavy KtLspTestEnvironment (IntelliJ project, application env, FIR infra, background index workers) per test method but env.close() was disabled, so environments accumulated for the JVM's lifetime. Locally this reproduces as java.lang.OutOfMemoryError after ~130 tests; in CI (larger heap) it manifests as GC-thrash plus a global-analysis-lock waiter crawling past the 10-minute timeout. Either way the run fails and the aggregate report is skipped.

- KtLspTestRule: re-enable env.close() in the finally block. The original "fails in test cases" was caused by calling it inside project.write { }; close() manages its own threading/locking, so call it directly.
- AnalysisSerializationTest: add @test(timeout = 60_000) to the two heavy concurrency tests that previously had no timeout, so a genuine liveness stall fails fast instead of burning the task budget (defense in depth; ~130x their observed runtime).

No production code changed. Verified: :lsp:kotlin:testV8DebugUnitTest -> 169 tests, 0 failures (previously OOM/timeout).

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough
  • Fixed nightly Jacoco/SonarQube test failures by rewriting plugin-manager unit/integration coverage to match current service APIs.
  • Added/expanded plugin-manager test coverage for IDE file operations, permissions behavior, and secure path handling (including rejection of sibling-prefix and .. traversal escapes).
  • Strengthened test path validation by switching from naive prefix checks to canonical, component-wise containment via File.isWithin(...).
  • Removed obsolete tests (ResourceServiceImplTest, and FileServiceImplTest) and updated integration tests to use the current registry/service implementations.
  • Re-enabled per-test cleanup for KtLspTestEnvironment to prevent Kotlin LSP test suite memory accumulation (cleanup now calls env.close() directly, avoiding nesting inside project.write).
  • Added 60-second timeouts to two heavy AnalysisSerializationTest concurrency regression tests to prevent hangs in CI.
  • Verified: plugin-manager (15 tests), lsp:kotlin (169 tests), and spotlessCheck.
  • Risks/notes: test-only changes adjust coverage and failure modes (now exception-based) and introduce explicit timeouts; cleanup behavior relies on direct environment closure to avoid leaks.
  • No production code changes.

Walkthrough

Changes

Test infrastructure and service coverage

Layer / File(s) Summary
LSP test timeouts and environment cleanup
lsp/kotlin/src/test/.../AnalysisSerializationTest.kt, lsp/kotlin/src/test/.../KtLspTestRule.kt
Concurrency tests now have 60-second timeouts, and initialized LSP environments are closed directly during cleanup.
IDE file service behavior and enforcement
plugin-manager/src/test/.../services/IdeFileServiceImplTest.kt, plugin-manager/src/test/.../services/FileServiceImplTest.kt, plugin-manager/src/test/.../services/ResourceServiceImplTest.kt
IDE file service tests cover file operations, listings, canonical path validation, and permissions; older file and resource service test classes are removed.
Registry-backed file service integration
plugin-manager/src/test/.../E2EIntegrationTest.kt, plugin-manager/src/test/.../core/PluginManagerIntegrationTest.kt
Integration tests use registry service retrieval, direct File operations, project-root validation, and project-service wiring.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested reviewers: jatezzz, dara-abijo-adfa, daniel-adfa

Poem

A rabbit guards each project root,
Canonical paths defeat the spoofed route.
LSP tests race with time in sight,
Environments close cleanly at night.
“Hop!” says Bun, “the files are right!”

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main workflow fix and mentions the two key failure areas addressed.
Description check ✅ Passed The description is directly related to the test-only workflow fixes and matches the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ADFA-4936-fix-jacoco-workflow

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/services/IdeFileServiceImplTest.kt`:
- Around line 38-40: Replace the raw absolute-path prefix checks in
IdeFileServiceImplTest.kt (lines 38-40), E2EIntegrationTest.kt (lines 42-44),
and PluginManagerIntegrationTest.kt (lines 104-106) with canonical
Path.startsWith containment against the canonical project root. In
IdeFileServiceImplTest, add coverage rejecting both sibling-prefix paths and
traversal paths while preserving acceptance of paths within the root.
- Around line 4-10: Migrate the tests in
plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/services/IdeFileServiceImplTest.kt
(lines 4-10),
plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/E2EIntegrationTest.kt
(lines 7-13), and
plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/core/PluginManagerIntegrationTest.kt
(lines 11-18) from JUnit 4 to JUnit Jupiter and Truth: replace imports,
annotations, helpers, and assertions with their Jupiter/Truth equivalents, and
convert any `@Test`(expected = ...) cases to Jupiter exception assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 97e0016c-a7b1-4018-9faf-27a0b140cbf4

📥 Commits

Reviewing files that changed from the base of the PR and between c52cb7e and 60f150d.

📒 Files selected for processing (7)
  • lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AnalysisSerializationTest.kt
  • lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/fixtures/KtLspTestRule.kt
  • plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/E2EIntegrationTest.kt
  • plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/core/PluginManagerIntegrationTest.kt
  • plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/services/FileServiceImplTest.kt
  • plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/services/IdeFileServiceImplTest.kt
  • plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/services/ResourceServiceImplTest.kt
💤 Files with no reviewable changes (2)
  • plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/services/ResourceServiceImplTest.kt
  • plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/services/FileServiceImplTest.kt

…dators

Review feedback. The test PathValidator fakes used path.absolutePath.startsWith(root.absolutePath), which false-accepts a sibling-prefix path (e.g. "<root>-sibling") and an unnormalized traversal ("<root>/../escape"). Replace with canonical, component-wise containment (canonicalFile.toPath().startsWith(root.canonicalFile.toPath())) via a small File.isWithin helper, and add IdeFileServiceImplTest coverage rejecting both sibling-prefix and traversal paths (within-root acceptance stays covered by the existing read/write tests).

Verified: :plugin-manager:testV8DebugUnitTest -> 15 tests, 0 failures; spotlessCheck clean.

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (1)
plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/services/IdeFileServiceImplTest.kt (1)

132-134: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Centralize the duplicated containment helper.

The same canonical File.isWithin implementation is defined three times.

  • plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/services/IdeFileServiceImplTest.kt#L132-L134: move the helper to a shared test utility.
  • plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/E2EIntegrationTest.kt#L65-L67: reuse the shared helper.
  • plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/core/PluginManagerIntegrationTest.kt#L118-L120: reuse the shared helper.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/services/IdeFileServiceImplTest.kt`
around lines 132 - 134, Centralize the canonical File.isWithin containment
helper in a shared test utility, then remove the local definitions from
IdeFileServiceImplTest, E2EIntegrationTest, and PluginManagerIntegrationTest and
update each test to reuse the shared extension. Apply the change at
plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/services/IdeFileServiceImplTest.kt:132-134,
plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/E2EIntegrationTest.kt:65-67,
and
plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/core/PluginManagerIntegrationTest.kt:118-120.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/services/IdeFileServiceImplTest.kt`:
- Around line 132-134: Centralize the canonical File.isWithin containment helper
in a shared test utility, then remove the local definitions from
IdeFileServiceImplTest, E2EIntegrationTest, and PluginManagerIntegrationTest and
update each test to reuse the shared extension. Apply the change at
plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/services/IdeFileServiceImplTest.kt:132-134,
plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/E2EIntegrationTest.kt:65-67,
and
plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/core/PluginManagerIntegrationTest.kt:118-120.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b37bb7dc-90e0-4ba9-873c-3fd7e4242a7f

📥 Commits

Reviewing files that changed from the base of the PR and between 60f150d and bee1a0f.

📒 Files selected for processing (3)
  • plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/E2EIntegrationTest.kt
  • plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/core/PluginManagerIntegrationTest.kt
  • plugin-manager/src/test/kotlin/com/itsaky/androidide/plugins/manager/services/IdeFileServiceImplTest.kt

@hal-eisen-adfa
hal-eisen-adfa merged commit fb3d3d2 into stage Jul 30, 2026
4 checks passed
@hal-eisen-adfa
hal-eisen-adfa deleted the ADFA-4936-fix-jacoco-workflow branch July 30, 2026 21:27
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.

2 participants