Skip to content

Add code coverage measurement to project#66

Closed
Whale0928 wants to merge 11 commits intomainfrom
claude/add-code-coverage-01SGcbrNENP634AsAK7Mfwmi
Closed

Add code coverage measurement to project#66
Whale0928 wants to merge 11 commits intomainfrom
claude/add-code-coverage-01SGcbrNENP634AsAK7Mfwmi

Conversation

@Whale0928
Copy link
Copy Markdown
Owner

…gets

  • Add JaCoCo plugin to root and all submodules
  • Configure coverage report generation (XML, HTML, CSV)
  • Set module-specific coverage targets without enforcing build failure
    • profanity-api: 70% line, 65% branch, 70% instruction
    • profanity-domain: 80% line, 75% branch, 80% instruction
    • profanity-shared: 60% line, 55% branch, 60% instruction
    • profanity-storage:rdb: 70% line, 65% branch, 70% instruction
    • profanity-storage:redis: 70% line, 65% branch, 70% instruction
    • Overall project: 75% line, 70% branch, 75% instruction
  • Add checkCoverageTargets task for each module to display target achievement
  • Add jacocoRootReport task for unified multi-module coverage report
  • Add checkOverallCoverageTarget task for overall project coverage check
  • Update GitHub Actions workflow to generate coverage reports and add PR comments
  • Add coverage badge generation for main branch
  • Update CLAUDE.md with coverage commands and targets
  • Add coverage badges to README.md

The coverage targets are informational only and do not fail the build, allowing gradual improvement while tracking progress toward goals.

…gets

- Add JaCoCo plugin to root and all submodules
- Configure coverage report generation (XML, HTML, CSV)
- Set module-specific coverage targets without enforcing build failure
  * profanity-api: 70% line, 65% branch, 70% instruction
  * profanity-domain: 80% line, 75% branch, 80% instruction
  * profanity-shared: 60% line, 55% branch, 60% instruction
  * profanity-storage:rdb: 70% line, 65% branch, 70% instruction
  * profanity-storage:redis: 70% line, 65% branch, 70% instruction
  * Overall project: 75% line, 70% branch, 75% instruction
- Add checkCoverageTargets task for each module to display target achievement
- Add jacocoRootReport task for unified multi-module coverage report
- Add checkOverallCoverageTarget task for overall project coverage check
- Update GitHub Actions workflow to generate coverage reports and add PR comments
- Add coverage badge generation for main branch
- Update CLAUDE.md with coverage commands and targets
- Add coverage badges to README.md

The coverage targets are informational only and do not fail the build,
allowing gradual improvement while tracking progress toward goals.
Copilot AI review requested due to automatic review settings November 20, 2025 17:10
- Create dedicated coverage.yml workflow for code coverage reporting
- Remove coverage steps from build_and_health_check.yml to keep it focused on testing
- Update README.md badge links to point to the new coverage workflow

Benefits:
- Cleaner separation of concerns (testing vs coverage reporting)
- Coverage workflow can be run independently
- Faster test workflow execution
- Better maintainability and reusability

Coverage workflow includes:
- JaCoCo report generation with module-specific and overall targets
- PR comments with coverage changes (madrapps/jacoco-report)
- Coverage badge generation for main branch (cicirello/jacoco-badge-generator)
- Artifact upload for coverage reports
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds comprehensive code coverage measurement to the project using JaCoCo, with module-specific coverage targets and GitHub Actions integration for automated reporting and badge generation. The coverage targets are informational and don't enforce build failures, allowing gradual improvement while tracking progress.

Key Changes

  • Configured JaCoCo plugin (v0.8.11) across all modules with XML, HTML, and CSV report generation
  • Implemented module-specific coverage targets (60-80% depending on module) with custom tasks to display achievement status
  • Integrated coverage reporting into CI/CD pipeline with PR comments and badge generation for the main branch

Reviewed Changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated no comments.

File Description
build.gradle Added JaCoCo plugin configuration, coverage report tasks, module-specific targets, and unified reporting functionality
.github/workflows/build_and_health_check.yml Added coverage report generation, PR comment action, and automated badge updates
README.md Added coverage and branch badges linking to workflow results
CLAUDE.md Documented coverage commands, report locations, and target specifications

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

claude and others added 9 commits November 20, 2025 17:16
- Change afterEvaluate to doFirst in jacocoTestReport for subprojects
- Change afterEvaluate to doFirst in jacocoRootReport task
- This fixes the Gradle configuration error where afterEvaluate cannot be
  executed in the current context within tasks.register

The doFirst approach achieves the same result by applying filters just
before task execution, which is compatible with tasks.register lazy
configuration.

Resolves the build failure:
"Project#afterEvaluate(Closure) on root project cannot be executed
in the current context"
Root Causes Identified:
1. tasks.register() cannot use afterEvaluate internally (Gradle 8.x Configuration Avoidance API)
2. test.finalizedBy checkCoverageTargets was causing test failures
3. Missing error handling in coverage check tasks

Changes Made:
- Revert subprojects jacocoTestReport to use afterEvaluate (works for existing tasks)
- Move jacocoRootReport configuration to project.afterEvaluate with tasks.named()
- Remove test.finalizedBy checkCoverageTargets (run coverage checks separately)
- Add try-catch error handling in checkCoverageTargets tasks
- Add try-catch error handling in checkOverallCoverageTarget task

This ensures:
- Tests run successfully without coverage interference
- Coverage reports are generated correctly
- Build doesn't fail if coverage XML parsing fails
- Gradle 8.8 Configuration Avoidance API is properly respected

Reference:
- Gradle docs: Configuration Avoidance API
- Issue: Project#afterEvaluate cannot be executed in tasks.register context
Problem:
- Gradle wrapper download failing with 503 Service Unavailable error
- setup-java with cache: gradle only caches dependencies, not wrapper
- First-time builds fail when GitHub's Gradle distribution CDN has issues

Solution:
- Add gradle/actions/setup-gradle@v3 action to both workflows
- This action provides:
  * Automatic Gradle wrapper caching and downloading
  * Build cache management
  * Better reliability with built-in retry logic
  * Faster subsequent builds

Changed workflows:
- .github/workflows/coverage.yml
- .github/workflows/build_and_health_check.yml

References:
- https://github.com/gradle/actions/tree/main/setup-gradle
- Gradle wrapper version: 8.8 (from gradle-wrapper.properties)
Problem:
- 1Password service returning 502 Bad Gateway errors intermittently
- Test and coverage workflows failing completely when 1Password unavailable
- Tests don't actually require .env secrets to run (only health-check does)

Solution:
- Add continue-on-error: true to 1Password steps in test and coverage jobs
- Create empty .env file as fallback when secrets unavailable
- Tests use @WebMvcTest with mocked dependencies, don't need real DB/mail config

Changes:
1. coverage.yml:
   - Make 1Password steps optional with continue-on-error
   - Create empty .env if secrets load fails
   - Tests can run without actual environment variables

2. build_and_health_check.yml (test job only):
   - Make 1Password steps optional for test job
   - health-check job still requires secrets (needs to run actual app)

Benefits:
- Tests run even when 1Password has temporary outages
- Coverage reports generated regardless of secret service status
- Health check properly validates with real environment (still requires secrets)
- Reduces dependency on external service availability for CI

This approach prioritizes test execution reliability while maintaining
proper integration testing with real secrets in health-check job.
Problem:
Gradle 8.8 detected implicit dependencies without explicit declarations:
- Task ':jacocoRootReport' uses outputs from ':test' and various
  ':jacocoTestReport' tasks without declaring dependencies
- This violates Gradle's task dependency validation rules

Solution:
- Move dependsOn declarations into project.afterEvaluate block
- Add explicit dependencies on all subproject Test tasks
- Add explicit dependencies on all subproject jacocoTestReport tasks
- Use tasks.withType(Test) and tasks.named('jacocoTestReport')
  for proper task collection

Changes:
```groovy
project.afterEvaluate {
    tasks.named('jacocoRootReport').configure {
        dependsOn subprojects.collect { it.tasks.withType(Test) }
        dependsOn subprojects.collect { it.tasks.named('jacocoTestReport') }
        ...
    }
}
```

This ensures proper task execution order and satisfies Gradle 8.8's
validation requirements for task output dependencies.

Reference: https://docs.gradle.org/8.8/userguide/validation_problems.html#implicit_dependency
…s.jacocoTestReport

Problem:
Previous approach using tasks.withType(Test) and tasks.named() was still
missing the root project's :test task dependency, causing the same error.

Solution:
Use simpler and more direct approach:
- dependsOn subprojects.test (all subproject test tasks)
- dependsOn subprojects.jacocoTestReport (all subproject report tasks)

This is more idiomatic Gradle code and ensures all necessary task
dependencies are properly declared without needing collect() operations.

Benefits:
- Cleaner, more readable code
- Gradle automatically resolves all subproject tasks
- No missing dependencies
- Works with Gradle 8.8's strict validation
Problem:
- Using outdated @V3 version of setup-gradle action
- Added unnecessary wrapper validation retry logic
- 503 errors from services.gradle.org during wrapper download

Solution:
- Upgrade to official latest version @v5
- Remove custom retry logic (not needed with v5)
- Use official recommended configuration from Gradle team

Benefits of @v5:
- Improved caching of wrapper distributions
- Better stability and reliability
- Official support and updates
- Automatic wrapper distribution caching (default behavior)

Reference:
- https://github.com/gradle/actions/tree/main/setup-gradle
- Official Gradle documentation for GitHub Actions
@Whale0928 Whale0928 closed this Jan 8, 2026
@Whale0928 Whale0928 deleted the claude/add-code-coverage-01SGcbrNENP634AsAK7Mfwmi branch January 28, 2026 08:30
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.

3 participants