diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4273ccf..ff57bc5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,3 +32,12 @@ jobs: with: name: jacoco-coverage-report path: target/site/jacoco/ + # Publish coverage to Codecov (ADR-0012). Advisory: codecov.yml sets + # informational statuses, and an upload failure does not fail CI. + - name: Upload coverage to Codecov + # Third-party action, pinned to the commit SHA of v7.0.0 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: target/site/jacoco/jacoco.xml + fail_ci_if_error: false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 95e1512..ea5073a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -914,6 +914,12 @@ coverage is reported, not yet enforced as a threshold). uploads the report as the **`jacoco-coverage-report`** artifact. Open a run, scroll to its **Artifacts** section, download the archive, and open `index.html` inside it. +- **On Codecov**: CI also uploads the report to the + [Codecov dashboard](https://app.codecov.io/gh/ebouchut/learn-dev) + (see [ADR-0012](docs/adr/0012-publish-test-coverage-to-codecov.md)), + which powers the README coverage badge and comments on every PR with the + project and patch coverage. The Codecov statuses are **informational** + (configured in `codecov.yml`): they report, they never block a merge. ### Generating the Documentation diff --git a/GLOSSAIRE.md b/GLOSSAIRE.md index 00d7073..77745d2 100644 --- a/GLOSSAIRE.md +++ b/GLOSSAIRE.md @@ -107,8 +107,13 @@ pour la justification des décisions de conception, voir les [ADR](docs/adr/READ fourni (`google_checks.xml`) en mode rapport seul (voir [ADR-0011](docs/adr/0011-start-ci-quality-checks-as-advisory-reports.md)). - **Code coverage (couverture de code)** — Le pourcentage de code exercé par - la suite de tests. Mesuré ici par JaCoCo ; rapporté, sans seuil imposé pour - l'instant. + la suite de tests. Mesuré ici par JaCoCo et publié sur Codecov ; rapporté, + sans seuil imposé pour l'instant. +- **Codecov** — Un service hébergé qui reçoit les rapports de couverture + depuis la CI, fournit un tableau de bord et un badge pour le README, et + commente chaque PR avec la couverture du projet et du patch. Les statuts + sont informatifs ici (voir + [ADR-0012](docs/adr/0012-publish-test-coverage-to-codecov.md)). - **DTO (Data Transfer Object)** — Un objet qui transporte des données à travers une frontière, volontairement distinct des entités. Un DTO `...Form` porte un formulaire HTML. diff --git a/GLOSSARY.md b/GLOSSARY.md index 96d7fe2..10cb237 100644 --- a/GLOSSARY.md +++ b/GLOSSARY.md @@ -89,7 +89,12 @@ rationale behind design decisions, see the [ADRs](docs/adr/README.md). style ruleset. Runs here with the bundled Google ruleset (`google_checks.xml`) in report-only mode (see [ADR-0011](docs/adr/0011-start-ci-quality-checks-as-advisory-reports.md)). - **Code coverage** — The percentage of code exercised by the test suite. - Measured here by JaCoCo; reported, not yet enforced as a threshold. + Measured here by JaCoCo and published to Codecov; reported, not yet + enforced as a threshold. +- **Codecov** — A hosted service that ingests coverage reports from CI, + renders a dashboard and a README badge, and comments on PRs with the + project and patch coverage. Statuses are informational here (see + [ADR-0012](docs/adr/0012-publish-test-coverage-to-codecov.md)). - **DTO (Data Transfer Object)** — An object carrying data across a boundary, deliberately separate from entities. A `...Form` DTO backs an HTML form. - **Failsafe** — The Maven plugin that runs `*IT` integration tests in the `verify` diff --git a/README.md b/README.md index c90d64e..9fc9c1c 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![build status][build-image]][build-url] [![test status][test-image]][test-url] +[![code coverage][coverage-image]][coverage-url] [![lint status][lint-image]][lint-url] [![schema drift status][schema-drift-image]][schema-drift-url] [![github issues][github-issues-image]][github-issues-url] @@ -378,9 +379,12 @@ visit [this link](https://github.com/users/ebouchut/projects/7/views/3). - [GLOSSARY.md](GLOSSARY.md) — definitions of the domain and technical terms used across the project (🇫🇷 French version: [GLOSSAIRE.md](GLOSSAIRE.md)). - [Architecture Decision Records](docs/adr/README.md) — A list of design decisions and their trade-offs. -- [Test coverage reports (JaCoCo)](https://github.com/ebouchut/learn-dev/actions/workflows/test.yml) — - published as the `jacoco-coverage-report` artifact of each Tests workflow run; - locally, `make test` writes the same report to `target/site/jacoco/index.html` +- [Test coverage (Codecov)](https://app.codecov.io/gh/ebouchut/learn-dev) — + live coverage dashboard fed by CI + (see [ADR-0012](docs/adr/0012-publish-test-coverage-to-codecov.md)); + the raw JaCoCo report is also published as the `jacoco-coverage-report` + artifact of each [Tests workflow run](https://github.com/ebouchut/learn-dev/actions/workflows/test.yml), + and locally `make test` writes it to `target/site/jacoco/index.html` (see [CONTRIBUTING](CONTRIBUTING.md#test-coverage-report-jacoco) for details). @@ -450,6 +454,8 @@ See [LICENSE](LICENSE) for details. [build-url]: https://github.com/ebouchut/learn-dev/actions/workflows/build.yml [test-image]: https://github.com/ebouchut/learn-dev/actions/workflows/test.yml/badge.svg?branch=dev&event=push [test-url]: https://github.com/ebouchut/learn-dev/actions/workflows/test.yml +[coverage-image]: https://codecov.io/gh/ebouchut/learn-dev/branch/dev/graph/badge.svg +[coverage-url]: https://app.codecov.io/gh/ebouchut/learn-dev [lint-image]: https://github.com/ebouchut/learn-dev/actions/workflows/lint.yml/badge.svg?branch=dev&event=push [lint-url]: https://github.com/ebouchut/learn-dev/actions/workflows/lint.yml [schema-drift-image]: https://github.com/ebouchut/learn-dev/actions/workflows/schema-drift.yml/badge.svg?branch=dev&event=push diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..bfc7c2c --- /dev/null +++ b/codecov.yml @@ -0,0 +1,12 @@ +# Codecov configuration (see docs/adr/0012-publish-test-coverage-to-codecov.md). +# Coverage is advisory: both statuses are informational, so Codecov reports +# but never fails a check. Tighten later by removing "informational" and +# setting coverage targets. +coverage: + status: + project: + default: + informational: true + patch: + default: + informational: true diff --git a/docs/adr/0011-start-ci-quality-checks-as-advisory-reports.md b/docs/adr/0011-start-ci-quality-checks-as-advisory-reports.md index 8f73c69..5563d17 100644 --- a/docs/adr/0011-start-ci-quality-checks-as-advisory-reports.md +++ b/docs/adr/0011-start-ci-quality-checks-as-advisory-reports.md @@ -1,6 +1,6 @@ # Start CI quality checks as advisory reports -- Status: accepted +- Status: superseded by [ADR-0012](0012-publish-test-coverage-to-codecov.md) - Date: 2026-07-06 - Deciders: Eric Bouchut diff --git a/docs/adr/0012-publish-test-coverage-to-codecov.md b/docs/adr/0012-publish-test-coverage-to-codecov.md new file mode 100644 index 0000000..2ccf87a --- /dev/null +++ b/docs/adr/0012-publish-test-coverage-to-codecov.md @@ -0,0 +1,72 @@ +# Publish test coverage to Codecov + +- Status: accepted +- Date: 2026-07-07 +- Deciders: Eric Bouchut + +## Context and Problem Statement + +[ADR-0011](0011-start-ci-quality-checks-as-advisory-reports.md) kept +coverage local: a JaCoCo report uploaded as a workflow artifact, no +external service. Living with it showed the limits: there is no +stable link to the latest coverage (artifact URLs are per-run), no coverage +percentage badge is possible without CI committing a generated SVG back to +dev (tried and reverted: CI must not add commits), and PRs get no coverage +feedback. How do we get a live badge and PR-level coverage insight without +CI commits? + +## Decision Drivers + +- A live coverage badge in the README, without CI pushing commits +- Coverage feedback on every PR (project and patch coverage) +- Keep quality checks advisory: coverage must not block merges + (the spirit of [ADR-0011](0011-start-ci-quality-checks-as-advisory-reports.md)) +- Minimal setup and cost (free for public repositories) + +## Considered Options + +- Keep artifacts only (the status quo of + [ADR-0011](0011-start-ci-quality-checks-as-advisory-reports.md)) +- A badge SVG generated and committed by CI (rejected: CI commits on dev) +- Codecov (external coverage service) + +## Decision Outcome + +Chosen: "Codecov", because it provides the badge and PR feedback from the +JaCoCo XML that CI already produces, with one upload step and zero commits. +The advisory stance is preserved: `codecov.yml` sets the project and patch +statuses to informational, so Codecov never fails a check. + +This ADR supersedes [ADR-0011](0011-start-ci-quality-checks-as-advisory-reports.md). +The other half of ADR-0011 is unchanged and restated here: **Checkstyle +stays advisory** (report-only goal, `continue-on-error`, report artifact), +until the remaining warnings are fixed and the gate is switched on. + +### Consequences + +- Good: Live coverage badge in the README and a browsable dashboard + (https://app.codecov.io/gh/ebouchut/learn-dev). +- Good: Every PR gets a coverage comment (project delta and patch coverage). +- Trade-off: An external service and an account; uploads use a + `CODECOV_TOKEN` repository secret (public-repo uploads can run tokenless + but are rate-limited). +- Trade-off: The Tests workflow gains a third-party action + (codecov/codecov-action, pinned to a commit SHA). +- The JaCoCo artifact upload is kept as an offline fallback. + +## Pros and Cons of the Options + +### Keep artifacts only + +- 👍 No external dependency +- 👎 No badge, no stable latest-coverage link, no PR feedback + +### CI-committed badge SVG + +- 👍 No external service +- 👎 CI pushes commits to dev (rejected by the maintainer) + +### Codecov + +- 👍 Badge, dashboard, PR comments; free for public repos; one workflow step +- 👎 External service, account, and upload token to manage diff --git a/docs/adr/README.md b/docs/adr/README.md index ca5a3fb..d55bf09 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -41,4 +41,5 @@ NNNN-short-title-in-kebab-case.md | [0008](0008-share-singleton-testcontainers-postgres.md) | Share one Testcontainers PostgreSQL as a static singleton, not @Container | accepted | | [0009](0009-run-tests-under-surefire-not-failsafe.md) | Run all tests under Surefire with the *Test suffix, not Failsafe/*IT | accepted | | [0010](0010-structure-ci-as-focused-workflows-per-concern.md) | Structure CI as focused workflows per concern, not a monolithic ci.yml | accepted | -| [0011](0011-start-ci-quality-checks-as-advisory-reports.md) | Start CI quality checks as advisory reports, gates come later | accepted | \ No newline at end of file +| [0011](0011-start-ci-quality-checks-as-advisory-reports.md) | Start CI quality checks as advisory reports, gates come later | superseded by ADR-0012 | +| [0012](0012-publish-test-coverage-to-codecov.md) | Publish test coverage to Codecov | accepted | \ No newline at end of file diff --git a/docs/plans/2026-07-07-codecov-coverage.md b/docs/plans/2026-07-07-codecov-coverage.md new file mode 100644 index 0000000..da0c590 --- /dev/null +++ b/docs/plans/2026-07-07-codecov-coverage.md @@ -0,0 +1,44 @@ +# Codecov Coverage Reporting Implementation Plan + +> **Status: executed** on 2026-07-07, branch `docs-link-coverage-reports`. +> Retrospective record; the CI-side checks at the bottom complete after the +> PR runs and the Codecov account is wired. + +**Goal:** A live code coverage badge in the README and coverage feedback on +every PR, without CI pushing commits. A CI-committed badge SVG was tried and +reverted for that exact reason; Codecov replaces it (see +[ADR-0012](../adr/0012-publish-test-coverage-to-codecov.md), which +supersedes [ADR-0011](../adr/0011-start-ci-quality-checks-as-advisory-reports.md) +while keeping Checkstyle advisory). + +## Tasks + +- [x] [ADR-0012](../adr/0012-publish-test-coverage-to-codecov.md): decision + record; mark ADR-0011 superseded; update the ADR index + => commit `docs(adr): Adopt Codecov for coverage reporting` +- [x] Tests workflow: upload `target/site/jacoco/jacoco.xml` with + codecov-action (pinned to the commit SHA of v7.0.0), + `fail_ci_if_error: false`; add root `codecov.yml` with informational + project and patch statuses (coverage never blocks a merge) + => commit `ci(coverage): Upload the JaCoCo report to Codecov` +- [x] Docs: README badge (`codecov.io/gh/ebouchut/learn-dev/branch/dev`) + linking to the dashboard; README documentation entry; CONTRIBUTING + "On Codecov" bullet; Codecov entries in GLOSSARY.md and GLOSSAIRE.md + (kept in sync); CI and quality table in docs/tech-stacks.md + => commit `docs(coverage): Add the Codecov badge and links` + +## User prerequisites (manual) + +- [ ] Sign in at https://about.codecov.io/ with GitHub and activate the + `ebouchut/learn-dev` repository +- [ ] Store the repository upload token as the `CODECOV_TOKEN` Actions + secret (`gh secret set CODECOV_TOKEN`); until then, uploads from this + public repository run tokenless (rate-limited) + +## Verification + +- [x] `test.yml` and `codecov.yml` parse as valid YAML +- [x] README badge reference labels each appear exactly twice (use + definition) +- [ ] The PR's Tests run shows the "Upload coverage to Codecov" step green +- [ ] The PR receives a Codecov comment (project delta and patch coverage) +- [ ] The README badge renders a percentage once dev has its first upload diff --git a/docs/tech-stacks.md b/docs/tech-stacks.md index 207a993..3a93e82 100644 --- a/docs/tech-stacks.md +++ b/docs/tech-stacks.md @@ -75,6 +75,15 @@ definitions see [GLOSSARY.md](../GLOSSARY.md). All tests run under the Maven Surefire plugin (no Failsafe); see [ADR-0009](adr/0009-run-tests-under-surefire-not-failsafe.md). +## Continuous integration and code quality + +| Technology | Version | Why here | +|------------|---------|----------| +| GitHub Actions | — | CI: one focused workflow per concern (build, test, lint, schema drift). See [ADR-0010](adr/0010-structure-ci-as-focused-workflows-per-concern.md). | +| Checkstyle (maven-checkstyle-plugin) | 3.6.0 | Advisory linting against the project ruleset (`config/checkstyle/checkstyle.xml`). See [ADR-0011](adr/0011-start-ci-quality-checks-as-advisory-reports.md). | +| JaCoCo | 0.8.15 | Test coverage measurement; report produced by every `mvn test`. | +| Codecov | — | Hosts the coverage reports: README badge, dashboard, PR comments (informational statuses). See [ADR-0012](adr/0012-publish-test-coverage-to-codecov.md). | + ## Containers and local infrastructure | Technology | Version | Why here |