From a7bc24886e86f40545a028d4a48ceb35f942291a Mon Sep 17 00:00:00 2001 From: Leo Galambos Date: Tue, 14 Apr 2026 00:36:56 +0200 Subject: [PATCH] feat: GH workflow (init) feat: JaCoCo --- .github/workflows/build.yml | 139 +++++++++++++++++++++++++ .github/workflows/pages.yml | 198 ++++++++++++++++++++++++++++++++++++ build.gradle | 33 ++++++ 3 files changed, 370 insertions(+) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/pages.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..4fcc851 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,139 @@ +name: Build and Release + +on: + push: + branches: + - main + - develop + tags: + - 'release@*' + pull_request: + branches: + - main + - develop + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + quality-gates: + name: Quality gates + runs-on: ubuntu-latest + + steps: + - name: Check out 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: Execute build, tests, PMD, coverage, Javadoc, and distribution packaging + run: ./gradlew --no-daemon clean build pmdMain javadoc jacocoTestReport distZip + + - name: Upload test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-reports + path: | + build/reports/tests/test + build/test-results/test + if-no-files-found: warn + retention-days: 14 + + - name: Upload PMD reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: pmd-reports + path: build/reports/pmd + if-no-files-found: warn + retention-days: 14 + + - name: Upload coverage reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: coverage-reports + path: | + build/reports/jacoco/test/html + build/reports/jacoco/test/jacocoTestReport.xml + if-no-files-found: warn + retention-days: 14 + + - name: Upload Javadoc + if: always() + uses: actions/upload-artifact@v4 + with: + name: javadoc + path: build/docs/javadoc + if-no-files-found: warn + retention-days: 14 + + - name: Upload benchmark reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: benchmark-reports + path: build/reports/jmh + if-no-files-found: ignore + retention-days: 14 + + - name: Upload distribution archives + if: success() + uses: actions/upload-artifact@v4 + with: + name: distributions + path: build/distributions/*.zip + if-no-files-found: error + retention-days: 14 + + release: + name: Publish tagged distribution + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/release@') + runs-on: ubuntu-latest + needs: quality-gates + permissions: + contents: write + + steps: + - name: Check out 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: Build release distribution + run: ./gradlew --no-daemon clean build pmdMain javadoc jacocoTestReport distZip + + - name: Publish GitHub release assets + uses: softprops/action-gh-release@v2 + with: + generate_release_notes: true + files: build/distributions/*.zip diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml new file mode 100644 index 0000000..3ef7723 --- /dev/null +++ b/.github/workflows/pages.yml @@ -0,0 +1,198 @@ +name: Publish Reports to GitHub Pages + +on: + push: + branches: + - main + 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: Build reports for publication + run: ./gradlew --no-daemon clean build pmdMain javadoc jacocoTestReport + + - 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: Stage published reports + shell: bash + run: | + set -euo pipefail + + SITE_DIR=".gh-pages" + RUN_DIR="${SITE_DIR}/builds/${GITHUB_RUN_NUMBER}" + LATEST_DIR="${SITE_DIR}/builds/latest" + + mkdir -p "${RUN_DIR}" + rm -rf "${LATEST_DIR}" + mkdir -p "${LATEST_DIR}" + + cp -R build/docs/javadoc "${RUN_DIR}/javadoc" + cp -R build/docs/javadoc "${LATEST_DIR}/javadoc" + + cp -R build/reports/tests/test "${RUN_DIR}/test" + cp -R build/reports/tests/test "${LATEST_DIR}/test" + + cp -R build/reports/pmd "${RUN_DIR}/pmd" + cp -R build/reports/pmd "${LATEST_DIR}/pmd" + + cp -R build/reports/jacoco/test/html "${RUN_DIR}/coverage" + cp -R build/reports/jacoco/test/html "${LATEST_DIR}/coverage" + + if [ -d "build/reports/jmh" ]; then + cp -R build/reports/jmh "${RUN_DIR}/jmh" + cp -R build/reports/jmh "${LATEST_DIR}/jmh" + HAS_JMH="true" + else + HAS_JMH="false" + fi + + cat > "${RUN_DIR}/index.html" < + + + + + Radixor Reports - Build ${GITHUB_RUN_NUMBER} + + + +

Radixor Reports

+

Build ${GITHUB_RUN_NUMBER} from commit ${GITHUB_SHA}

+ +

Open latest report set

+

Back to report home

+ + + EOF + + cp "${RUN_DIR}/index.html" "${LATEST_DIR}/index.html" + + cat > "${SITE_DIR}/.nojekyll" < + + + + + Radixor Reports + + + +

Radixor Published Reports

+

Durable CI reports published from GitHub Actions to the gh-pages branch.

+ +

Latest

+
    +
  • Latest build summary
  • +
  • Javadoc
  • +
  • Test Report
  • +
  • PMD Report
  • +
  • Coverage Report
  • + EOF + + if [ "${HAS_JMH}" = "true" ]; then + echo '
  • Benchmark Report
  • ' + else + echo '
  • Benchmark Report: not currently available
  • ' + fi + + cat < + +

    Recent historical builds

    +
      + EOF + + for build in ${BUILD_LIST}; do + echo "
    • Build ${build}
    • " + done + + cat < + + + EOF + } > "${SITE_DIR}/index.html" + + - 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 diff --git a/build.gradle b/build.gradle index 4d71ab8..59e6dd7 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,7 @@ plugins { id 'java' id 'application' id 'pmd' + id 'jacoco' id 'com.palantir.git-version' version '4.0.0' } @@ -12,6 +13,10 @@ configurations { mockitoAgent } +jacoco { + toolVersion = '0.8.14' +} + pmd { consoleOutput = true toolVersion = '7.20.0' @@ -43,6 +48,34 @@ dependencies { tasks.withType(Test).configureEach { useJUnitPlatform() jvmArgs += "-javaagent:${configurations.mockitoAgent.singleFile}" + + finalizedBy(tasks.named('jacocoTestReport')) + + reports { + junitXml.required = true + html.required = true + } +} + +tasks.withType(Pmd).configureEach { + reports { + xml.required = true + html.required = true + } +} + +tasks.named('jacocoTestReport', JacocoReport) { + dependsOn(tasks.named('test')) + + reports { + xml.required = true + csv.required = false + html.required = true + } +} + +tasks.named('check') { + dependsOn(tasks.named('jacocoTestReport')) } application {