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: Verify reproducibility inputs shell: bash run: | set -euo pipefail test -f gradle.lockfile test -f gradle.properties test -f gradle/verification-metadata.xml - name: Execute build, tests, PMD, coverage, Javadoc, distribution packaging, and SBOM generation run: ./gradlew --no-daemon clean build pmdMain javadoc jacocoTestReport distZip cyclonedxBom - name: Upload SBOM if: always() uses: actions/upload-artifact@v4 with: name: sbom path: | build/reports/sbom/radixor-sbom.json build/reports/sbom/radixor-sbom.xml if-no-files-found: error retention-days: 14 - 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: Verify reproducibility inputs shell: bash run: | set -euo pipefail test -f gradle.lockfile test -f gradle.properties test -f gradle/verification-metadata.xml - name: Generate release changelog for tagged builds if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/release@') shell: bash run: | set -euo pipefail chmod +x ./tools/generate-release-notes.sh mkdir -p build/generated/release-notes ./tools/generate-release-notes.sh "${GITHUB_REF_NAME}" > build/generated/release-notes/CHANGELOG.md - name: Build release inputs, signed Maven bundle, and SBOM env: SIGNING_KEY: ${{ secrets.SIGNING_KEY }} SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} run: ./gradlew --no-daemon clean build pmdMain javadoc jacocoTestReport cyclonedxBom centralBundle - name: Generate release changelog shell: bash run: | set -euo pipefail chmod +x ./tools/generate-release-notes.sh mkdir -p build/generated/release-notes ./tools/generate-release-notes.sh "${GITHUB_REF_NAME}" > build/generated/release-notes/CHANGELOG.md - name: Package release distribution run: ./gradlew --no-daemon distZip - name: Publish bundle to Maven Central shell: bash env: CENTRAL_BEARER_TOKEN: ${{ secrets.CENTRAL_BEARER_TOKEN }} run: | set -euo pipefail echo "::add-mask::$CENTRAL_BEARER_TOKEN" BUNDLE="$(ls build/central-bundle/*.zip)" HEADER_FILE="$(mktemp)" trap 'rm -f "$HEADER_FILE"' EXIT printf 'Authorization: Bearer %s\n' "$CENTRAL_BEARER_TOKEN" > "$HEADER_FILE" curl \ --fail \ --silent \ --show-error \ --request POST \ --header @"$HEADER_FILE" \ --form "bundle=@${BUNDLE}" \ --form "name=org.egothor:radixor:${GITHUB_REF_NAME#release@}" \ "https://central.sonatype.com/api/v1/publisher/upload?publishingType=AUTOMATIC" - name: Publish GitHub release assets uses: softprops/action-gh-release@v2 with: body_path: build/generated/release-notes/CHANGELOG.md files: | build/distributions/*.zip build/reports/sbom/radixor-sbom.json build/reports/sbom/radixor-sbom.xml build/central-bundle/*.zip