diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index afec9a16..b1c4c20f 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -24,13 +24,28 @@ jobs: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: + submodules: true fetch-depth: 0 + - name: Setup Zulu JDK 7 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 + with: + distribution: zulu + java-version: '7' - name: Setup Temurin JDK 25 uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 with: distribution: temurin java-version: '25' cache: maven + # JaCoCo report for the coverage badge, published by `just all` under current/coverage + - name: Run tests with coverage + run: | + ./mvnw -B -C -ntp -V \ + -Darch.id=amd64 \ + -Dnative.cc=gcc \ + -Dsurefire.reportFormat=plain \ + -Pcoverage \ + verify - name: Install uv uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0 - name: Install just diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ec021c17..5d1aeea9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,10 +13,6 @@ jobs: linux: name: Linux test runs-on: ${{ matrix.runs-on }} - permissions: - contents: read - # Codecov upload via OIDC - id-token: write strategy: fail-fast: false matrix: @@ -66,13 +62,6 @@ jobs: -Dsurefire.reportFormat=plain \ ${{ matrix.maven-flags }} \ verify - - name: Upload coverage to Codecov + - name: Summarize coverage if: matrix.coverage - uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 - with: - files: target/site/jacoco/jacoco.xml - disable_search: true - # OIDC tokens are not available to pull requests from other repositories, which use tokenless upload instead. - # Don't use head.repo.fork here: this repository is itself a fork, so that is always true. - use_oidc: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} - fail_ci_if_error: false + run: python3 scripts/jacoco_summary.py target/site/jacoco/jacoco.csv >> "$GITHUB_STEP_SUMMARY" diff --git a/README.md b/README.md index d234a929..1aa5187f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # LZ4 Java [![Maven Central](https://img.shields.io/maven-central/v/at.yawk.lz4/lz4-java)](https://central.sonatype.com/artifact/at.yawk.lz4/lz4-java) -[![codecov](https://codecov.io/gh/yawkat/lz4-java/graph/badge.svg)](https://codecov.io/gh/yawkat/lz4-java) +[![Coverage](https://img.shields.io/endpoint?url=https%3A%2F%2Flz4-java.yawk.at%2Fcurrent%2Fcoverage%2Fbadge.json)](https://lz4-java.yawk.at/current/coverage/) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/14930/badge)](https://www.bestpractices.dev/projects/14930) [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/yawkat/lz4-java/badge)](https://scorecard.dev/viewer/?uri=github.com/yawkat/lz4-java) diff --git a/docs/justfile b/docs/justfile index 87763d1b..48a97b08 100644 --- a/docs/justfile +++ b/docs/justfile @@ -26,6 +26,7 @@ template NAME TAG: (repo TAG) import semver import mistune import os + import re import pygments import pygments.lexers import pygments.formatters @@ -37,6 +38,20 @@ template NAME TAG: (repo TAG) selected_version_actual = '{{TAG}}' if '{{TAG}}' != '{{latest_version_name}}' else '{{latest_version}}' + def readme_source(): + text = open('{{build}}/repo/lz4-java-{{TAG}}/README.md').read() + if '{{TAG}}' != '{{latest_version_name}}': + # The README badges show the state of the main branch. On pages for older versions, pin the Maven Central badge to + # that version and drop the others. + version = '{{TAG}}'[1:] + text = re.sub( + r'^\[!\[Maven Central\]\(https://img\.shields\.io/maven-central/v/([^/)]+)/([^/)]+)\)\]\([^)]*\)$', + lambda m: f'[![Maven Central](https://img.shields.io/badge/maven--central-v{version}-blue)]' + f'(https://central.sonatype.com/artifact/{m[1]}/{m[2]}/{version})', + text, flags=re.M) + text = re.sub(r'^\[!\[(?!Maven Central\]).*\n', '', text, flags=re.M) + return text + html_formatter = pygments.formatters.HtmlFormatter() class PygmentsRenderer(mistune.HTMLRenderer): def block_code(self, code, info=None): @@ -61,7 +76,7 @@ template NAME TAG: (repo TAG) selected_version='{{TAG}}', selected_version_actual=selected_version_actual, path_javadoc='{{path_javadoc}}', - readme=lambda: mistune.create_markdown(renderer=PygmentsRenderer(), plugins=['table'])(open('{{build}}/repo/lz4-java-{{TAG}}/README.md').read()), + readme=lambda: mistune.create_markdown(renderer=PygmentsRenderer(), plugins=['table'])(readme_source()), pygments_style=lambda: html_formatter.get_style_defs() )) @@ -96,6 +111,13 @@ rewrite-version-links: html = html.replace('', '') p.write_text(html) +# Publish the JaCoCo report of the working tree, if it was built with `./mvnw -Pcoverage verify` +coverage: + if [ -f ../target/site/jacoco/jacoco.csv ]; then \ + cp -r ../target/site/jacoco '{{build}}/site/{{latest_version_name}}/coverage' && \ + python3 ../scripts/jacoco_summary.py ../target/site/jacoco/jacoco.csv --badge '{{build}}/site/{{latest_version_name}}/coverage/badge.json'; \ + fi + prepare: rm -rf '{{build}}/site' mkdir -p '{{build}}/site' @@ -105,5 +127,5 @@ log: @echo "Available tags: {{all_versions}}" @echo "Current tag: {{latest_version}}" -all: log prepare (version latest_version_name) && rewrite-version-links +all: log prepare (version latest_version_name) && coverage rewrite-version-links set -e; for v in {{all_versions}}; do just 'all_versions={{all_versions}}' 'latest_version={{latest_version}}' version "$v"; done diff --git a/pom.xml b/pom.xml index bac1faaf..e53f4544 100644 --- a/pom.xml +++ b/pom.xml @@ -342,7 +342,7 @@ - + coverage diff --git a/scripts/jacoco_summary.py b/scripts/jacoco_summary.py new file mode 100644 index 00000000..672e7232 --- /dev/null +++ b/scripts/jacoco_summary.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +"""Summarize line coverage from a JaCoCo CSV report. + +Prints a Markdown summary line, and with --badge also writes a shields.io endpoint badge JSON file. +""" +import argparse +import csv +import json + +parser = argparse.ArgumentParser(description=__doc__) +parser.add_argument("csv", help="JaCoCo CSV report, e.g. target/site/jacoco/jacoco.csv") +parser.add_argument("--badge", help="write shields.io endpoint badge JSON to this file") +args = parser.parse_args() + +missed = covered = 0 +with open(args.csv, newline="") as f: + for row in csv.DictReader(f): + missed += int(row["LINE_MISSED"]) + covered += int(row["LINE_COVERED"]) +total = missed + covered +pct = 100 * covered / total + +print(f"Line coverage: **{pct:.1f}%** ({covered} of {total} lines)") + +if args.badge: + color = "brightgreen" if pct >= 80 else "yellow" if pct >= 60 else "red" + with open(args.badge, "w") as f: + json.dump({"schemaVersion": 1, "label": "coverage", "message": f"{pct:.1f}%", "color": color}, f)