Skip to content

Introduce JaCoCo Code Coverage Reporting for Eclipse Platform #3678

@carstenartur

Description

@carstenartur

Let's make sure issue is not already fixed in latest builds first.

Suggestion

From a fresh installation and clean workspace:

Motivation

Currently, the Eclipse Platform project does not provide aggregated code coverage reports for its test suites. Without coverage data, it is difficult to:

  • Identify untested code paths – contributors and committers have no visibility into which areas of the platform lack test coverage.
  • Prevent coverage regression – there is no mechanism to detect when a change reduces overall test coverage.
  • Guide test writing efforts – without metrics, it's unclear where new tests would have the highest impact.
  • Build contributor confidence – publicly available coverage reports signal project quality and help new contributors understand the codebase.

Proof of Concept: Working Implementation in Sandbox Project

I have implemented a complete JaCoCo code coverage pipeline in my sandbox project (an Eclipse/Tycho-based project similar in build structure to Eclipse Platform). The coverage reports are automatically generated and deployed to GitHub Pages.

📊 Live Coverage Report

👉 https://carstenartur.github.io/sandbox/coverage/ — Aggregated JaCoCo HTML coverage report, updated daily.

Advantages of Adding Code Coverage

  1. Visibility – Browsable HTML reports with line-level, branch-level, instruction-level, and complexity coverage for every package, class, and method.
  2. Aggregation – A single aggregated report across all test modules, providing a unified project-wide view.
  3. Zero impact on normal builds – Coverage is activated via a Maven profile (-Pjacoco), so regular developer builds remain fast. Coverage collection adds ~10-20% build time only when explicitly enabled.
  4. Separate scheduled workflow – Coverage generation can run on a daily schedule (or manually via workflow_dispatch), keeping the main CI build fast and only computing coverage when useful (e.g., only if there were recent commits).
  5. Publicly accessible – Reports deployed to GitHub Pages are available to everyone—contributors, committers, and users—without needing to run the build locally.
  6. Historical tracking – Over time, coverage trends become visible, allowing the project to set goals and track improvement.

How It Works (Implementation Details)

The implementation consists of 3 components. Below is exactly what was done in the sandbox project, with links to each file:


Component 1: JaCoCo Maven Profile in the Root pom.xml

A jacoco profile is added to the root POM that:

  • Activates the jacoco-maven-plugin with the prepare-agent goal (instruments bytecode for coverage collection during test execution).
  • Conditionally includes a dedicated coverage aggregation module.

Reference file: pom.xml (jacoco profile section)

<profile>
  <id>jacoco</id>
  <activation>
    <activeByDefault>false</activeByDefault>
  </activation>
  <modules>
    <module>sandbox_coverage</module>
  </modules>
  <build>
    <plugins>
      <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>${jacoco-version}</version>
        <executions>
          <execution>
            <id>default-prepare-agent</id>
            <goals>
              <goal>prepare-agent</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</profile>

For Eclipse Platform: Add a similar profile to the root pom.xml of eclipse.platform.releng.aggregator.


Component 2: Coverage Aggregation Module

A dedicated pom packaging module that uses JaCoCo's report-aggregate goal to combine coverage data from all test modules into one report. This module declares dependencies on:

  • All implementation modules (scope compile) — so JaCoCo can map coverage to source code.
  • All test modules (scope test) — so JaCoCo can collect the jacoco.exec data files.

Reference file: sandbox_coverage/pom.xml

<project>
  <artifactId>sandbox_coverage</artifactId>
  <packaging>pom</packaging>
  <profiles>
    <profile>
      <id>jacoco</id>
      <build>
        <plugins>
          <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>${jacoco-version}</version>
            <executions>
              <execution>
                <phase>verify</phase>
                <goals>
                  <goal>report-aggregate</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>
  <dependencies>
    <!-- For each module pair: implementation (compile) + test (test) -->
    <dependency>
      <groupId>org.sandbox</groupId>
      <artifactId>sandbox_encoding_quickfix</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.sandbox</groupId>
      <artifactId>sandbox_encoding_quickfix_test</artifactId>
      <scope>test</scope>
    </dependency>
    <!-- ... repeat for all modules ... -->
  </dependencies>
</project>

For Eclipse Platform: Create a similar eclipse_coverage module that lists all platform bundles and their corresponding test bundles as dependencies.


Component 3: GitHub Actions Workflow for Coverage Generation & Deployment

A separate GitHub Actions workflow (not the main CI build) that:

  1. Runs on a daily schedule (cron: 0 0 * * *) and/or via manual trigger (workflow_dispatch).
  2. Skips execution if there were no commits in the last 24 hours (to save CI resources).
  3. Builds the project with -Pjacoco to generate coverage data.
  4. Deploys the aggregated HTML report to GitHub Pages using peaceiris/actions-gh-pages.

Reference file: .github/workflows/coverage.yml

Key sections:

name: Code Coverage Report

on:
  schedule:
    - cron: '0 0 * * *'  # Daily at midnight UTC
  workflow_dispatch:      # Allow manual trigger

jobs:
  coverage:
    runs-on: ubuntu-latest
    permissions:
      contents: write     # Required for gh-pages deployment
    steps:
    - uses: actions/checkout@v6

    - name: Check for recent commits (schedule only)
      if: github.event_name == 'schedule'
      run: |
        if git log --since="24 hours ago" --oneline | grep -q .; then
          echo "has_commits=true" >> $GITHUB_OUTPUT
        else
          echo "has_commits=false" >> $GITHUB_OUTPUT
        fi

    - name: Build with Coverage
      run: xvfb-run --auto-servernum mvn -e -V -T 1C --batch-mode -Pjacoco clean verify

    - name: Deploy Coverage to GitHub Pages
      uses: peaceiris/actions-gh-pages@v4
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_dir: ./sandbox_coverage/target/site/jacoco-aggregate
        destination_dir: coverage
        keep_files: true

For Eclipse Platform: Create a similar .github/workflows/coverage.yml. The build command would need to be adapted to the Eclipse Platform's build invocation (potentially including the relevant Tycho profiles). The publish_dir would point to the Eclipse coverage module's output directory.


Additional Documentation (Optional but Recommended)

GitHub Pages Setup (One-Time)

In the repository Settings → Pages:

  1. Select Deploy from a branch
  2. Select the gh-pages branch, / (root) folder
  3. Click Save

The workflow handles publishing automatically from there.

Implementation Options for Eclipse Platform

Option Description Impact on CI
A) Separate scheduled workflow (recommended) Daily or weekly coverage build, deployed to GitHub Pages Zero impact on main CI
B) As part of PR builds Generate coverage on every PR Adds ~10-20% build time to every PR
C) Hybrid Scheduled full coverage + lightweight per-PR delta Minimal impact + PR-level feedback

I recommend Option A to start, as it provides maximum value with zero risk to existing CI performance.

Summary

This is a proven, working approach that I've been running in production on my sandbox project. All configuration files are linked above and can serve as a blueprint.

Community

Discussed in community call on 26.02.2026

  • I understand suggesting an enhancement doesn't mandate anyone to implement it. Other contributors may consider this suggestion, or not, at their own convenience. The most efficient way to get it fixed is that I implement it myself and contribute it back as a good quality patch to the project.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions