Files
Radixor/.github/workflows/pages.yml
Leo Galambos e7800b29c9 feat!: modularize stemmer models and release infrastructure
Move bundled stemmer dictionaries from the core artifact into independently
versioned model modules. Add model discovery and explicit model-loading APIs,
a standard model aggregate, a model BOM, and dedicated model and catalog
release workflows.

Add full PoliMorf integration, model provenance and licensing validation,
streaming model-input verification, strict dependency verification, consumer
resolution tests, Configuration Cache compatibility, and expanded JMH,
quality, documentation, and release checks.

Upgrade the CycloneDX and JMH Gradle plugins and remove Gradle 10 and Java
compiler deprecations.

BREAKING CHANGE: The core Radixor artifact no longer contains bundled stemmer
dictionaries. Applications must add the required model artifacts, the standard
model aggregate, or model dependencies managed through the Radixor model BOM.
2026-07-22 23:33:28 +02:00

352 lines
15 KiB
YAML

name: Publish Reports to GitHub Pages
on:
push:
branches:
- main
paths:
- 'docs/**'
- 'mkdocs.yml'
- 'src/main/**'
- 'src/test/**'
- 'src/jmh/**'
- 'models/**'
- 'build-logic/**'
- 'build.gradle'
- 'gradle.properties'
- 'gradle.lockfile'
- 'settings.gradle'
- 'gradle/**'
- 'dependency-suppression.xml'
- 'gradlew'
- 'gradlew.bat'
- '.github/workflows/pages.yml'
- '.github/workflows/benchmarks.yml'
- 'tools/generate-pages-badges.py'
workflow_dispatch:
permissions:
contents: write
concurrency:
group: pages-${{ github.ref }}
cancel-in-progress: true
jobs:
publish-pages:
name: Publish static reports
runs-on: ubuntu-latest
steps:
- name: Check out source repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Validate Gradle wrapper
uses: gradle/actions/wrapper-validation@v4
- name: Set up Temurin JDK 21
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
- name: Set up Gradle caching and instrumentation
uses: gradle/actions/setup-gradle@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install MkDocs Material
run: python -m pip install --upgrade pip mkdocs-material
- name: Verify reproducibility inputs
shell: bash
run: |
set -euo pipefail
test -f gradle.lockfile
test -f gradle.properties
test -f gradle/verification-metadata.xml
- name: Build reports for publication
run: ./gradlew --no-daemon clean ciRelease pmdMain javadoc jacocoCiReleaseReport pitest jmh -Pjmh.includes='.*EnglishStemmerComparisonBenchmark.*' :cyclonedxDirectBom
- name: Prepare gh-pages worktree
shell: bash
run: |
set -euo pipefail
if git ls-remote --exit-code --heads origin gh-pages > /dev/null 2>&1; then
git fetch origin gh-pages:gh-pages
git worktree add .gh-pages gh-pages
else
git worktree add --detach .gh-pages
cd .gh-pages
git checkout --orphan gh-pages
git rm -rf . > /dev/null 2>&1 || true
cd ..
fi
- name: Prepare staged MkDocs source
run: ./gradlew --no-daemon prepareMkDocsSource verifyModelCatalogDocumentation
- name: Stage published reports
shell: bash
run: |
set -euo pipefail
TEST_REPORT_DIR="build/reports/tests/ciRelease"
JACOCO_REPORT_DIR="build/reports/jacoco/jacocoCiReleaseReport"
SITE_DIR=".gh-pages"
RUN_DIR="${SITE_DIR}/builds/${GITHUB_RUN_NUMBER}"
RUN_METRICS_DIR="${RUN_DIR}/metrics"
LATEST_DIR="${SITE_DIR}/builds/latest"
LATEST_METRICS_DIR="${LATEST_DIR}/metrics"
mkdir -p "${RUN_DIR}"
rm -rf "${LATEST_DIR}"
mkdir -p "${LATEST_DIR}" "${RUN_METRICS_DIR}" "${LATEST_METRICS_DIR}"
cp -R build/docs/javadoc "${RUN_DIR}/javadoc"
cp -R build/docs/javadoc "${LATEST_DIR}/javadoc"
cp -R "${TEST_REPORT_DIR}" "${RUN_DIR}/test"
cp -R "${TEST_REPORT_DIR}" "${LATEST_DIR}/test"
cp -R build/reports/pmd "${RUN_DIR}/pmd"
cp -R build/reports/pmd "${LATEST_DIR}/pmd"
cp -R "${JACOCO_REPORT_DIR}/html" "${RUN_DIR}/coverage"
cp -R "${JACOCO_REPORT_DIR}/html" "${LATEST_DIR}/coverage"
cp -R build/reports/pitest "${RUN_DIR}/pitest"
cp -R build/reports/pitest "${LATEST_DIR}/pitest"
JMH_TXT_LINK=''
JMH_CSV_LINK=''
JMH_TXT_LATEST_LINK=''
JMH_CSV_LATEST_LINK=''
JMH_TXT_REPORT_MD='- Benchmark results (TXT): not currently available'
JMH_CSV_REPORT_MD='- Benchmark results (CSV): not currently available'
DEPENDENCY_CHECK_LINK=''
DEPENDENCY_CHECK_LATEST_LINK=''
DEPENDENCY_CHECK_REPORT_MD='- Dependency vulnerability report: not currently available'
SBOM_JSON_LINK=''
SBOM_XML_LINK=''
SBOM_JSON_LATEST_LINK=''
SBOM_XML_LATEST_LINK=''
SBOM_JSON_REPORT_MD='- SBOM (JSON): not currently available'
SBOM_XML_REPORT_MD='- SBOM (XML): not currently available'
if [ -d "build/reports/jmh" ]; then
cp -R build/reports/jmh "${RUN_DIR}/jmh"
cp -R build/reports/jmh "${LATEST_DIR}/jmh"
if [ -f "${RUN_DIR}/jmh/jmh-results.txt" ]; then
JMH_TXT_LINK='<li><a href="./jmh/jmh-results.txt">Benchmark Results (TXT)</a></li>'
JMH_TXT_LATEST_LINK='<li><a href="./builds/latest/jmh/jmh-results.txt">Benchmark Results (TXT)</a></li>'
JMH_TXT_REPORT_MD='- [JMH benchmark results (TXT)](https://leogalambos.github.io/Radixor/builds/latest/jmh/jmh-results.txt)'
fi
if [ -f "${RUN_DIR}/jmh/jmh-results.csv" ]; then
JMH_CSV_LINK='<li><a href="./jmh/jmh-results.csv">Benchmark Results (CSV)</a></li>'
JMH_CSV_LATEST_LINK='<li><a href="./builds/latest/jmh/jmh-results.csv">Benchmark Results (CSV)</a></li>'
JMH_CSV_REPORT_MD='- [JMH benchmark results (CSV)](https://leogalambos.github.io/Radixor/builds/latest/jmh/jmh-results.csv)'
fi
HAS_JMH="true"
else
HAS_JMH="false"
fi
if [ -d "build/reports/dependency-check" ]; then
cp -R build/reports/dependency-check "${RUN_DIR}/dependency-check"
cp -R build/reports/dependency-check "${LATEST_DIR}/dependency-check"
if [ -f "${RUN_DIR}/dependency-check/dependency-check-report.html" ]; then
DEPENDENCY_CHECK_LINK='<li><a href="./dependency-check/dependency-check-report.html">Dependency Vulnerability Report</a></li>'
DEPENDENCY_CHECK_LATEST_LINK='<li><a href="./builds/latest/dependency-check/dependency-check-report.html">Dependency Vulnerability Report</a></li>'
DEPENDENCY_CHECK_REPORT_MD='- [Dependency vulnerability report](https://leogalambos.github.io/Radixor/builds/latest/dependency-check/dependency-check-report.html)'
fi
fi
if [ -d "build/reports/sbom" ]; then
cp -R build/reports/sbom "${RUN_DIR}/sbom"
cp -R build/reports/sbom "${LATEST_DIR}/sbom"
SBOM_JSON_LINK='<li><a href="./sbom/radixor-sbom.json">SBOM (JSON)</a></li>'
SBOM_XML_LINK='<li><a href="./sbom/radixor-sbom.xml">SBOM (XML)</a></li>'
SBOM_JSON_LATEST_LINK='<li><a href="./builds/latest/sbom/radixor-sbom.json">SBOM (JSON)</a></li>'
SBOM_XML_LATEST_LINK='<li><a href="./builds/latest/sbom/radixor-sbom.xml">SBOM (XML)</a></li>'
SBOM_JSON_REPORT_MD='- [SBOM (JSON)](https://leogalambos.github.io/Radixor/builds/latest/sbom/radixor-sbom.json)'
SBOM_XML_REPORT_MD='- [SBOM (XML)](https://leogalambos.github.io/Radixor/builds/latest/sbom/radixor-sbom.xml)'
fi
python3 \
./tools/generate-pages-badges.py \
--jacoco-xml "${JACOCO_REPORT_DIR}/jacocoCiReleaseReport.xml" \
--pit-xml build/reports/pitest/mutations.xml \
--jmh-csv build/reports/jmh/jmh-results.csv \
--run-metrics-dir "${RUN_METRICS_DIR}" \
--latest-metrics-dir "${LATEST_METRICS_DIR}"
COVERAGE_BADGE_LINK='<li><a href="./metrics/coverage-badge.json">Coverage Badge Metadata</a></li>'
COVERAGE_BADGE_LATEST_LINK='<li><a href="./builds/latest/metrics/coverage-badge.json">Coverage Badge Metadata</a></li>'
MUTATION_BADGE_LINK='<li><a href="./metrics/pitest-badge.json">Mutation Badge Metadata</a></li>'
MUTATION_BADGE_LATEST_LINK='<li><a href="./builds/latest/metrics/pitest-badge.json">Mutation Badge Metadata</a></li>'
COVERAGE_BADGE_REPORT_MD='- [Coverage badge metadata](https://leogalambos.github.io/Radixor/builds/latest/metrics/coverage-badge.json)'
MUTATION_BADGE_REPORT_MD='- [Mutation badge metadata](https://leogalambos.github.io/Radixor/builds/latest/metrics/pitest-badge.json)'
if [ ! -f "${RUN_METRICS_DIR}/coverage-badge.json" ]; then
COVERAGE_BADGE_LINK='<li>Coverage Badge Metadata: not available</li>'
COVERAGE_BADGE_LATEST_LINK='<li>Coverage Badge Metadata: not available</li>'
COVERAGE_BADGE_REPORT_MD='- Coverage badge metadata: not currently available'
fi
if [ ! -f "${RUN_METRICS_DIR}/pitest-badge.json" ]; then
MUTATION_BADGE_REPORT_MD='- Mutation badge metadata: not currently available'
fi
cat > "${RUN_DIR}/index.html" <<EOF
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Radixor Reports - Build ${GITHUB_RUN_NUMBER}</title>
<style>
body { font-family: Arial, sans-serif; max-width: 900px; margin: 2rem auto; padding: 0 1rem; line-height: 1.5; }
h1, h2 { margin-bottom: 0.5rem; }
ul { padding-left: 1.25rem; }
code { background: #f4f4f4; padding: 0.1rem 0.3rem; }
.meta { color: #555; }
</style>
</head>
<body>
<h1>Radixor Reports</h1>
<p class="meta">Build ${GITHUB_RUN_NUMBER} from commit ${GITHUB_SHA}</p>
<ul>
<li><a href="./javadoc/">Javadoc</a></li>
<li><a href="./test/">Release Verification Test Report (ciRelease)</a></li>
<li><a href="./pmd/main.html">PMD Report</a></li>
<li><a href="./coverage/">Coverage Report</a></li>
${DEPENDENCY_CHECK_LINK:-<li>Dependency Vulnerability Report: not available</li>}
${SBOM_JSON_LINK:-<li>SBOM (JSON): not available</li>}
${SBOM_XML_LINK:-<li>SBOM (XML): not available</li>}
${COVERAGE_BADGE_LINK}
${MUTATION_BADGE_LINK}
<li><a href="./pitest/">Mutation Testing Report</a></li>
$(
[ "${HAS_JMH}" = "true" ] && { echo "${JMH_TXT_LINK:-<li>Benchmark Results (TXT): not available</li>}"; echo "${JMH_CSV_LINK:-<li>Benchmark Results (CSV): not available</li>}"; } \
|| echo '<li>Benchmark results: not available in this build</li>'
)
</ul>
<p><a href="../latest/">Open latest report set</a></p>
<p><a href="../../">Back to report home</a></p>
</body>
</html>
EOF
cp "${RUN_DIR}/index.html" "${LATEST_DIR}/index.html"
cat > build/mkdocs-source/reports.md <<EOF
# CI Reports
Radixor publishes durable CI artifacts to GitHub Pages on every qualifying run of \`.github/workflows/pages.yml\`.
## Primary report entry points
- [Latest build summary](https://leogalambos.github.io/Radixor/builds/latest/)
- [Javadoc](https://leogalambos.github.io/Radixor/builds/latest/javadoc/)
- [Release verification test report (ciRelease)](https://leogalambos.github.io/Radixor/builds/latest/test/)
- [PMD report](https://leogalambos.github.io/Radixor/builds/latest/pmd/main.html)
- [JaCoCo coverage report](https://leogalambos.github.io/Radixor/builds/latest/coverage/)
- [PIT mutation testing report](https://leogalambos.github.io/Radixor/builds/latest/pitest/)
${DEPENDENCY_CHECK_REPORT_MD}
${SBOM_JSON_REPORT_MD}
${SBOM_XML_REPORT_MD}
## Benchmark reports and badge metadata
${JMH_TXT_REPORT_MD}
${JMH_CSV_REPORT_MD}
${COVERAGE_BADGE_REPORT_MD}
${MUTATION_BADGE_REPORT_MD}
## Historical runs
- [Browse historical build reports](https://leogalambos.github.io/Radixor/builds/)
EOF
# Retain only the 10 most recent numbered builds to stay within
# GitHub Pages capacity limits. The "latest" alias is kept separately.
mapfile -t EXPIRED_BUILDS < <(
find "${SITE_DIR}/builds" -mindepth 1 -maxdepth 1 -type d -printf '%P\n' \
| grep -E '^[0-9]+$' \
| sort -r -n \
| tail -n +11
)
for build in "${EXPIRED_BUILDS[@]}"; do
rm -rf "${SITE_DIR}/builds/${build}"
done
{
echo "# Historical Build Reports"
echo
echo "The following build report sets are currently published on GitHub Pages."
echo
echo "To stay within GitHub Pages capacity limits, only the 10 most recent build report sets are retained."
echo
echo "| Build | Published | Link |"
echo "|---:|---|---|"
find "${SITE_DIR}/builds" -mindepth 1 -maxdepth 1 -type d ! -name latest -printf '%P\n' \
| grep -E '^[0-9]+$' \
| while read -r build; do
ts="$(git -C "${SITE_DIR}" log --diff-filter=A --format='%ct' --reverse -- "builds/${build}/index.html" | head -n 1)"
if [ -n "${ts}" ]; then
published="$(date -u -d "@${ts}" '+%Y-%m-%d %H:%M')"
else
published="unknown"
ts="0"
fi
printf '%s\t%s\t%s\n' "${ts}" "${build}" "${published}"
done \
| sort -r -n -k1,1 \
| while IFS=$'\t' read -r _ts build published; do
echo "| ${build} | ${published} | [Open](../builds/${build}/) |"
done
} > build/mkdocs-source/builds.md
- name: Build documentation site (MkDocs Material)
shell: bash
run: |
set -euo pipefail
mkdocs build --strict --config-file build/mkdocs/mkdocs.yml
rsync -a --delete --exclude '.git' --exclude '.git/' --exclude 'builds/' build/mkdocs-site/ .gh-pages/
mkdir -p .gh-pages/builds
cp build/mkdocs-site/builds/index.html .gh-pages/builds/index.html
cat > .gh-pages/.nojekyll <<EOF
EOF
- name: Commit and push gh-pages
shell: bash
run: |
set -euo pipefail
cd .gh-pages
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add .
if git diff --cached --quiet; then
echo "No changes to publish."
exit 0
fi
git commit -m "Publish reports for run ${GITHUB_RUN_NUMBER}"
git push origin gh-pages