Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
0626170
feat: Add JaCoCo coverage and SonarCloud integration
kamiazya Sep 25, 2025
e82334b
fix: Address review feedback and fix CI issues
kamiazya Sep 25, 2025
f32b15e
fix: Fix coverage-report task configuration and CI conditional checks
kamiazya Sep 25, 2025
b1cfbd4
fix: Use shell conditional for SONAR_TOKEN check in GitHub Actions
kamiazya Sep 25, 2025
fb8efa5
refactor: Integrate JaCoCo and SonarCloud into existing Test workflow
kamiazya Sep 25, 2025
e4b7af8
fix: Correct user-preferences tests to match query handler behavior
kamiazya Sep 25, 2025
ef1c6b9
fix: SLSA workflow reference to use semantic version tag
kamiazya Sep 25, 2025
e9ab993
fix: Add continue-on-error to SonarCloud step
kamiazya Sep 25, 2025
877b9ec
refactor: Move coverage-report module to quality directory
kamiazya Sep 26, 2025
fe87b85
fix: Resolve ktlint code style violations
kamiazya Sep 26, 2025
6720031
fix: Fix SonarCloud coverage integration
kamiazya Sep 26, 2025
e05ead4
fix: Correct path syntax for SonarQube coverage report configuration
kamiazya Sep 26, 2025
d47572e
fix: Update SonarCloud integration for proper coverage reporting
kamiazya Sep 26, 2025
e1ee3cc
fix: Remove SonarCloud scan from CI workflow
kamiazya Sep 26, 2025
4af8f30
fix: Restore SonarCloud CI-based analysis with proper configuration
kamiazya Sep 26, 2025
d9097f7
feat: Enable CI-based SonarCloud analysis with JaCoCo coverage
kamiazya Sep 26, 2025
f44bec4
fix: Fix ktlint code style violations
kamiazya Sep 26, 2025
7e306b4
fix(coverage): Add explicit dependency on processResources tasks
kamiazya Sep 26, 2025
2d7e3d3
fix(coverage): Add explicit dependencies on compilation tasks
kamiazya Sep 26, 2025
32b0a0f
fix(coverage): Add comprehensive task dependencies with safe checks
kamiazya Sep 26, 2025
5cd2bcc
fix(coverage): Use task type-based dependencies for reliable ordering
kamiazya Sep 26, 2025
402c17a
fix(coverage): Add explicit dependencies on apps-scopes tasks
kamiazya Sep 26, 2025
644dcda
fix(coverage): Use comprehensive project-wide task dependencies
kamiazya Sep 26, 2025
44c8e3c
fix(sonarqube): Only set test sources if directory exists
kamiazya Sep 26, 2025
390a150
fix(sonarqube): Check both main and test directories existence
kamiazya Sep 26, 2025
4871ce1
fix(sonarqube): Fix duplicate file indexing and deprecated task name
kamiazya Sep 27, 2025
7898cc3
fix: Address SonarCloud Code Analysis issues
kamiazya Sep 27, 2025
269669f
fix: Properly fix GitHub Actions script injection vulnerability
kamiazya Sep 27, 2025
2dc6357
chore: Add Gradle dependency verification metadata
kamiazya Sep 27, 2025
deb6173
fix: Use full SHA hash for slsa-github-generator dependency
kamiazya Sep 27, 2025
680de63
fix: Remove verification metadata temporarily to fix CI failures
kamiazya Sep 27, 2025
8cf3ec8
fix: Add missing permissions to Security workflow
kamiazya Sep 27, 2025
f87cc2a
fix: Reduce cognitive complexity in DefaultErrorMapper
kamiazya Sep 27, 2025
d02c13f
feat: Add Gradle dependency verification metadata
kamiazya Sep 27, 2025
3b2ee2f
docs: Add changeset for coverage and security enhancements
kamiazya Sep 27, 2025
896499c
fix: Update verification metadata for SBOM generation
kamiazya Sep 27, 2025
c4edf73
fix: Resolve CI build failures and improve coverage report
kamiazya Sep 27, 2025
5316e87
fix: Resolve JaCoCo aggregation plugin task conflict in coverage-report
kamiazya Sep 27, 2025
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
22 changes: 22 additions & 0 deletions .changeset/coverage-security-enhancements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
"scopes": minor
---

Add comprehensive code coverage tracking, SonarCloud integration, and security enhancements

### New Features
- **JaCoCo Code Coverage**: Multi-module coverage aggregation with 60% minimum threshold
- **SonarCloud Integration**: Automated quality gates and code analysis
- **Gradle Dependency Verification**: Comprehensive SHA256 checksums for supply chain security

### Security Improvements
- Fixed all SonarCloud Code Analysis issues (hardcoded dispatchers, script injection, cognitive complexity)
- Resolved Security Hotspots through dependency verification and GitHub Actions SHA pinning
- Enhanced CI/CD security with proper permissions and environment variable usage

### New Gradle Tasks
- `testWithCoverage`: Run tests with coverage reports
- `sonarqubeWithCoverage`: Complete quality analysis
- `:coverage-report:testCodeCoverageReport`: Aggregated coverage reporting

This release significantly improves code quality monitoring and security posture.
12 changes: 12 additions & 0 deletions .changeset/jacoco-sonar-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"scopes": minor
---

Add JaCoCo code coverage and SonarCloud integration for continuous quality monitoring

- Integrated JaCoCo plugin for code coverage measurement across all modules
- Added coverage-report module for multi-module coverage aggregation
- Configured SonarQube plugin for SonarCloud analysis
- Created GitHub Actions workflow for automated quality checks
- Added comprehensive documentation and Gradle tasks
- Set up XML coverage reports for SonarCloud consumption
33 changes: 19 additions & 14 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@ jobs:
- name: Extract version from tag
id: version
shell: bash
env:
EVENT_NAME: ${{ github.event_name }}
INPUT_TAG: ${{ inputs.tag }}
REF_NAME: ${{ github.ref_name }}
run: |
set -euo pipefail
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ inputs.tag }}"
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
VERSION="$INPUT_TAG"
else
VERSION="${{ github.ref_name }}"
VERSION="$REF_NAME"
fi
# Remove 'v' prefix for SemVer compatibility (v1.0.0 -> 1.0.0)
CLEAN_VERSION=${VERSION#v}
Expand Down Expand Up @@ -114,7 +118,8 @@ jobs:

# For manually triggered runs, ensure the tag exists on the remote
# This prevents gh release create from accidentally creating a tag
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
EVENT_NAME="${{ github.event_name }}"
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
echo "Checking if tag exists on remote..."

# Use GitHub API to check if tag exists
Expand Down Expand Up @@ -817,21 +822,21 @@ jobs:
find sbom-artifacts -name "sbom-*.xml" -type f -exec gh release upload "${{ needs.resolve-version.outputs.tag_version }}" --clobber {} \;

# Upload distribution packages
find distribution-packages -name "scopes-*-dist.tar.gz" -type f -exec gh release upload "${{ steps.version.outputs.tag_version }}" --clobber {} \;
find distribution-packages -name "scopes-*-dist.zip" -type f -exec gh release upload "${{ steps.version.outputs.tag_version }}" --clobber {} \;
find distribution-packages -name "scopes-*-dist.*.sha256" -type f -exec gh release upload "${{ steps.version.outputs.tag_version }}" --clobber {} \;
find distribution-packages -name "scopes-*-dist.tar.gz" -type f -exec gh release upload "${{ needs.resolve-version.outputs.tag_version }}" --clobber {} \;
find distribution-packages -name "scopes-*-dist.zip" -type f -exec gh release upload "${{ needs.resolve-version.outputs.tag_version }}" --clobber {} \;
find distribution-packages -name "scopes-*-dist.*.sha256" -type f -exec gh release upload "${{ needs.resolve-version.outputs.tag_version }}" --clobber {} \;

# Upload SLSA provenance if available
if [ -d "provenance" ] && [ -n "$(find provenance -name "*.intoto.jsonl" -type f)" ]; then
find provenance -name "*.intoto.jsonl" -type f -exec gh release upload "${{ steps.version.outputs.tag_version }}" --clobber {} \;
find provenance -name "*.intoto.jsonl" -type f -exec gh release upload "${{ needs.resolve-version.outputs.tag_version }}" --clobber {} \;
fi

- name: Enhance release notes with custom content
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Get the auto-generated release notes
AUTO_NOTES=$(gh release view "${{ steps.version.outputs.tag_version }}" --json body --jq '.body')
AUTO_NOTES=$(gh release view "${{ needs.resolve-version.outputs.tag_version }}" --json body --jq '.body')

# Create the combined release notes
cat > combined_notes.md << 'EOF'
Expand All @@ -843,19 +848,19 @@ jobs:

#### Linux/macOS
```bash
curl -sSL https://raw.githubusercontent.com/kamiazya/scopes/${{ steps.version.outputs.tag_version }}/install/install.sh | sh
curl -sSL https://raw.githubusercontent.com/kamiazya/scopes/${{ needs.resolve-version.outputs.tag_version }}/install/install.sh | sh
```

#### Windows PowerShell
```powershell
iwr https://raw.githubusercontent.com/kamiazya/scopes/${{ steps.version.outputs.tag_version }}/install/install.ps1 | iex
iwr https://raw.githubusercontent.com/kamiazya/scopes/${{ needs.resolve-version.outputs.tag_version }}/install/install.ps1 | iex
```

### 📦 Offline Installation

For air-gapped environments or enterprise deployments, download the unified distribution package:

1. Download `scopes-${{ steps.version.outputs.version }}-dist.tar.gz` or `.zip`
1. Download `scopes-${{ needs.resolve-version.outputs.version }}-dist.tar.gz` or `.zip`
2. Extract the package
3. Run `./install.sh` (Unix) or `.\install.ps1` (Windows)

Expand Down Expand Up @@ -888,7 +893,7 @@ jobs:
go install github.com/slsa-framework/slsa-verifier/v2/cli/slsa-verifier@latest

# Verify the binary (example for Linux)
slsa-verifier verify-artifact scopes-${{ steps.version.outputs.version }}-linux-x64 \
slsa-verifier verify-artifact scopes-${{ needs.resolve-version.outputs.version }}-linux-x64 \
--provenance-path multiple.intoto.jsonl \
--source-uri github.com/${{ github.repository }}
```
Expand Down Expand Up @@ -920,4 +925,4 @@ jobs:
echo "$AUTO_NOTES" >> combined_notes.md

# Update the release with combined content
gh release edit "${{ steps.version.outputs.tag_version }}" --notes-file combined_notes.md
gh release edit "${{ needs.resolve-version.outputs.tag_version }}" --notes-file combined_notes.md
2 changes: 2 additions & 0 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ permissions:
contents: write # Required for dependency graph submission
actions: read
id-token: write # Required for OIDC authentication
issues: write # Required for commenting on issues
pull-requests: write # Required for commenting on PRs
Comment on lines +18 to +19
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid granting unnecessary pull-requests: write permission

This workflow only posts issue-style comments via issues.createComment, which already requires issues: write. The additional pull-requests: write grant expands the token’s scope without a functional benefit. Please keep the permissions minimal and drop the extra grant.

   id-token: write # Required for OIDC authentication
-  issues: write # Required for commenting on issues
-  pull-requests: write # Required for commenting on PRs
+  issues: write # Required for commenting on PRs/issues
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
issues: write # Required for commenting on issues
pull-requests: write # Required for commenting on PRs
id-token: write # Required for OIDC authentication
issues: write # Required for commenting on PRs/issues
🤖 Prompt for AI Agents
In .github/workflows/security.yml around lines 18-19 the workflow unnecessarily
grants pull-requests: write; remove the pull-requests: write permission and
leave only issues: write to minimize token scope, then commit the updated
permissions block so the workflow continues posting comments via
issues.createComment without the extra pull-requests permission.


jobs:
dependency-check:
Expand Down
40 changes: 38 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ concurrency:
permissions:
contents: read
actions: read
pull-requests: read # Needed for SonarCloud PR analysis

jobs:
unit-test:
Expand All @@ -28,6 +29,8 @@ jobs:

- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis

- name: Set up GraalVM
uses: graalvm/setup-graalvm@e140024fdc2d95d3c7e10a636887a91090d29990 # v1.4.0
Expand All @@ -36,14 +39,47 @@ jobs:
distribution: 'graalvm'
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Cache SonarCloud packages
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar

- name: Setup Gradle
uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3
with:
validate-wrappers: true
cache-read-only: ${{ github.ref != 'refs/heads/main' }}

- name: Run tests
run: ./gradlew --no-daemon --scan test
- name: Run tests and generate coverage reports
run: ./gradlew --no-daemon test jacocoTestReport :quality-coverage-report:testCodeCoverageReport

- name: Run Detekt static analysis
run: ./gradlew --no-daemon detekt

- name: SonarCloud Analysis
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
if [ -n "$SONAR_TOKEN" ]; then
echo "Running SonarCloud analysis with coverage..."
./gradlew --no-daemon sonar \
-Dsonar.coverage.jacoco.xmlReportPaths=quality/coverage-report/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml
else
echo "::warning::SONAR_TOKEN is not set. Skipping SonarCloud analysis."
fi

- name: Upload coverage reports
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: always()
with:
name: coverage-reports
path: |
**/build/reports/jacoco/
quality/coverage-report/build/reports/jacoco/
if-no-files-found: warn

- name: Upload test results
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ replay_pid*
.gradle/
build/

# Gradle dependency verification temporary files
gradle/verification-keyring.gpg
gradle/verification-metadata.xml.backup
settings-gradle.lockfile

tmp/
.claude/settings.local.json

Expand Down
110 changes: 110 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import org.gradle.api.tasks.testing.Test
import org.gradle.testing.jacoco.tasks.JacocoCoverageVerification
import org.gradle.testing.jacoco.tasks.JacocoReport

plugins {
alias(libs.plugins.kotlin.jvm) apply false
alias(libs.plugins.kotlin.serialization) apply false
Expand All @@ -8,6 +12,8 @@ plugins {
alias(libs.plugins.spotless)
alias(libs.plugins.cyclonedx.bom)
alias(libs.plugins.spdx.sbom)
alias(libs.plugins.sonarqube)
jacoco
}

group = "io.github.kamiazya"
Expand Down Expand Up @@ -40,11 +46,63 @@ subprojects {

// Configure Kotlin compilation when plugin is applied
pluginManager.withPlugin("org.jetbrains.kotlin.jvm") {
// Apply JaCoCo to all modules with Kotlin code
apply(plugin = "jacoco")
// Apply SonarQube plugin to all Kotlin modules
apply(plugin = "org.sonarqube")

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21)
}
}

// Configure JaCoCo
tasks.withType<JacocoReport> {
dependsOn(tasks.named("test"))
reports {
xml.required.set(true)
html.required.set(true)
csv.required.set(false)
}
}

// Configure test task to generate JaCoCo data
tasks.withType<Test> {
finalizedBy(tasks.withType<JacocoReport>())
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
}
}
Comment on lines +71 to +77
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The use of finalizedBy(tasks.withType<JacocoReport>()) is problematic in a multi-project setup. This configuration will cause the test task of any single module to trigger the JacocoReport tasks from all modules, which is inefficient and not the intended behavior. Furthermore, the testWithCoverage task already orchestrates running tests and then generating reports. This finalizedBy is redundant and should be removed to avoid unexpected behavior and performance issues.

        tasks.withType<Test> {
            useJUnitPlatform()
            testLogging {
                events("passed", "skipped", "failed")
            }
        }


// JaCoCo coverage verification
tasks.withType<JacocoCoverageVerification> {
violationRules {
rule {
limit {
minimum = "0.60".toBigDecimal()
}
}
}
}

// Configure SonarQube for each module
sonarqube {
properties {
// Only set sources if the directory exists
if (file("src/main/kotlin").exists()) {
property("sonar.sources", "src/main/kotlin")
property("sonar.java.binaries", "build/classes/kotlin/main")
}
// Only set test sources if the directory exists
if (file("src/test/kotlin").exists()) {
property("sonar.tests", "src/test/kotlin")
}
// Each module should report its own JaCoCo XML report path
property("sonar.coverage.jacoco.xmlReportPaths", "build/reports/jacoco/test/jacocoTestReport.xml")
}
}
}

// Fix circular dependency issue with Kotlin and Java compilation
Expand Down Expand Up @@ -81,6 +139,8 @@ subprojects {

// Custom task to check if GraalVM is available
tasks.register("checkGraalVM") {
description = "Check if GraalVM native-image is available in the current environment"
group = "verification"
doLast {
try {
val isWindows = System.getProperty("os.name").lowercase().contains("windows")
Expand Down Expand Up @@ -147,6 +207,29 @@ tasks.register("konsistTest") {
dependsOn(":quality-konsist:test")
}

// Task to run all tests with coverage
tasks.register("testWithCoverage") {
description = "Run all tests and generate coverage reports"
group = "verification"

// Run all tests
subprojects.forEach { subproject ->
subproject.tasks.findByName("test")?.let {
dependsOn(it)
}
}

// Generate individual coverage reports
subprojects.forEach { subproject ->
subproject.tasks.findByName("jacocoTestReport")?.let {
dependsOn(it)
}
}
Comment on lines +215 to +227
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The testWithCoverage task has a redundant dependency configuration. The jacocoTestReport task, by default, depends on the test task. Therefore, explicitly depending on all test tasks in the first loop is unnecessary. You can simplify this task by only depending on the jacocoTestReport tasks, which will in turn run the test tasks.

    // Run all tests and generate individual coverage reports
    subprojects.forEach { subproject ->
        subproject.tasks.findByName("jacocoTestReport")?.let {
            dependsOn(it)
        }
    }


// Generate aggregated coverage report
finalizedBy(":quality-coverage-report:testCodeCoverageReport")
}

Comment on lines +210 to +232
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Repo-wide clean-up: find lingering references to quality/coverage-report

Search and fix any remaining wrong module references to prevent task resolution errors.


🏁 Script executed:

#!/bin/bash
# Find wrong references
rg -nP 'quality/coverage-report|:quality-coverage-report'
# Confirm correct ones exist
rg -nP 'coverage-report/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport\.xml|:coverage-report:testCodeCoverageReport'

Length of output: 634


Remove lingering references to quality/coverage-report

  • settings.gradle.kts (lines 51, 142): update ":quality-coverage-report" to ":coverage-report"
  • build.gradle.kts (lines 222, 309): update finalizedBy(":quality-coverage-report:testCodeCoverageReport") and report paths under quality/coverage-report/... to reference coverage-report
  • docs/guides/coverage-and-sonarcloud.md (line 119): change :coverage-report:testCodeCoverageReport entry to match the new module path
🤖 Prompt for AI Agents
In build.gradle.kts around lines 202 to 224, update the lingering reference
finalizedBy(":quality-coverage-report:testCodeCoverageReport") to
finalizedBy(":coverage-report:testCodeCoverageReport") and also search this file
for any other occurrences (e.g., around line 309) that reference
quality/coverage-report paths and replace them with coverage-report;
additionally update settings.gradle.kts (around lines 51 and 142) to rename
":quality-coverage-report" to ":coverage-report" and change any report path
references accordingly, and update docs/guides/coverage-and-sonarcloud.md
(around line 119) to use ":coverage-report:testCodeCoverageReport" so all module
names and report paths consistently reference coverage-report.

// Spotless configuration
configure<com.diffplug.gradle.spotless.SpotlessExtension> {
kotlin {
Expand Down Expand Up @@ -205,3 +288,30 @@ configure<com.diffplug.gradle.spotless.SpotlessExtension> {
endWithNewline()
}
}

// SonarQube configuration
sonarqube {
properties {
property("sonar.projectKey", "kamiazya_scopes")
property("sonar.organization", "kamiazya")
property("sonar.host.url", "https://sonarcloud.io")
property("sonar.projectName", "Scopes")
property("sonar.projectVersion", version)

// Language settings
property("sonar.language", "kotlin")
property("sonar.kotlin.detekt.reportPaths", "**/build/reports/detekt/detekt.xml")

Comment on lines +303 to +304
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify glob support for detekt report paths.

Sonar’s detekt property typically expects concrete file paths (comma-separated). Globs may be ignored, leading to missing issues in the analysis.

Run:

As per coding guidelines


🌐 Web query:

Does SonarQube/SonarCloud support glob patterns in the "sonar.kotlin.detekt.reportPaths" Gradle property, or must it be a comma-separated list of concrete file paths?

💡 Result:

Short answer: No — sonar.kotlin.detekt.reportPaths expects a comma-delimited list of report file paths (concrete paths). Wildcards/globs are only supported for properties that explicitly say so; the Detekt reportPaths entry has no wildcard remark. [1][2]

Sources:

  • SonarQube docs, "Importing third‑party issues" (table entry for sonar.kotlin.detekt.reportPaths and note about which properties support wildcards). [1]
  • SonarSource community / example usages showing concrete path usage (Gradle property example). [2]

Use concrete Detekt report paths instead of globs
Sonar’s sonar.kotlin.detekt.reportPaths doesn’t support wildcards—replace the glob with a comma-separated list of actual report XML file paths. (build.gradle.kts:312-313)

🤖 Prompt for AI Agents
In build.gradle.kts around lines 312-313, the sonar.kotlin.detekt.reportPaths
currently uses a glob (**/build/reports/detekt/detekt.xml) which Sonar does not
accept; replace the glob with a concrete, comma-separated list of actual detekt
report XML file paths produced by your modules (e.g.,
moduleA/build/reports/detekt/detekt.xml,moduleB/...); update the property call
to set the full paths for each module (or dynamically resolve module report
paths at configuration time and join them with commas) so Sonar receives
explicit file locations.

// Coverage configuration - use the aggregated report
property(
"sonar.coverage.jacoco.xmlReportPaths",
"quality/coverage-report/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml",
)

// Encoding
property("sonar.sourceEncoding", "UTF-8")

// Duplication detection
property("sonar.cpd.exclusions", "**/*Test.kt,**/*Spec.kt")
}
}
Loading
Loading