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.
352 lines
15 KiB
YAML
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
|