Skip to content

Merge pull request #121 from bernardladenthin/claude/maven-deps-audit… #194

Merge pull request #121 from bernardladenthin/claude/maven-deps-audit…

Merge pull request #121 from bernardladenthin/claude/maven-deps-audit… #194

Workflow file for this run

# SPDX-FileCopyrightText: 2014-2026 Bernard Ladenthin <bernard.ladenthin@gmail.com>
#
# SPDX-License-Identifier: Apache-2.0
name: Publish
on:
push:
branches: [main]
tags: ['v*']
pull_request:
workflow_dispatch:
inputs:
publish_to_central:
description: "Deploy to Maven Central (snapshot if -SNAPSHOT, release if a vX.Y.Z tag)"
type: boolean
default: false
permissions:
contents: read
jobs:
# ---------------------------------------------------------------------------
# Start gate — single cancellable abort window before the pipeline starts.
# The wait duration lives in the `startgate` GitHub Environment (Settings →
# Environments → startgate → Wait timer).
# ---------------------------------------------------------------------------
startgate:
name: Start gate (abort window)
runs-on: ubuntu-latest
environment: startgate
steps:
- run: echo "Start gate elapsed — proceeding with pipeline."
code-style:
name: Code style (spotless) + package graph
needs: startgate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
java-version: '21'
distribution: temurin
- name: Spotless check (fail fast on format violations)
run: mvn -B --no-transfer-progress spotless:check
- name: SpotBugs check (fail fast on static-analysis findings)
run: mvn -B --no-transfer-progress -DskipTests -Denforcer.skip=true compile spotbugs:check
- name: Print internal package dependency graph (jdeps, informational)
continue-on-error: true
run: |
mvn -B --no-transfer-progress -DskipTests -Denforcer.skip=true compile
echo "=== internal package dependency graph (jdeps, bytecode) ==="
jdeps -verbose:package target/classes | grep 'net.ladenthin.streambuffer' || true
build:
name: Build
needs: startgate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
java-version: '21'
distribution: temurin
cache: maven
- name: Build
run: mvn --batch-mode --no-transfer-progress -DskipTests package
- uses: actions/upload-artifact@v7
with: { name: jars, path: target/*.jar }
test:
name: Test (JDK ${{ matrix.java-version }})
needs: [build]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
java-version: ['21']
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
java-version: ${{ matrix.java-version }}
distribution: temurin
cache: maven
- name: Memory before tests
run: free -h
- name: Test
run: mvn -e --batch-mode --no-transfer-progress -P jcstress verify
- uses: actions/upload-artifact@v7
if: matrix.java-version == '21'
with:
name: jacoco-report
path: target/site/jacoco/jacoco.xml
if-no-files-found: ignore
- name: Memory after tests
if: always()
run: free -h
- name: Upload crash & surefire dumps
if: failure()
uses: actions/upload-artifact@v7
with:
name: crash-dumps-jdk${{ matrix.java-version }}
path: |
${{ github.workspace }}/hs_err_pid*.log
${{ github.workspace }}/*.hprof
${{ github.workspace }}/target/surefire-reports/*.dump
${{ github.workspace }}/target/surefire-reports/*.dumpstream
${{ github.workspace }}/target/surefire-reports/*.txt
${{ github.workspace }}/target/surefire-reports/TEST-*.xml
if-no-files-found: ignore
vmlens:
name: Test (vmlens interleavings)
needs: [build]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with: { java-version: '21', distribution: temurin, cache: maven }
- name: Test under vmlens
run: mvn --batch-mode --no-transfer-progress -Pvmlens test
- uses: actions/upload-artifact@v7
if: always()
with:
name: vmlens-report
path: target/vmlens-report/
if-no-files-found: ignore
report:
name: Report
needs: [test]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with: { java-version: '21', distribution: temurin, cache: maven }
- uses: actions/download-artifact@v8
with: { name: jacoco-report, path: target/site/jacoco/ }
continue-on-error: true
- uses: advanced-security/maven-dependency-submission-action@v5
- name: Coveralls
uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
file: target/site/jacoco/jacoco.xml
format: jacoco
continue-on-error: true
- name: Codecov
uses: codecov/codecov-action@v7
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: target/site/jacoco/jacoco.xml
continue-on-error: true
- name: Run PIT mutation tests
run: mvn --batch-mode --no-transfer-progress test-compile org.pitest:pitest-maven:mutationCoverage
- name: Extract PIT survivors
if: always()
run: |
echo "=== PIT Survived Mutations ==="
for html_file in $(find target/pit-reports -name "*.html" -type f | sort); do
if grep -q "SURVIVED" "$html_file"; then
echo "Found survivors in $html_file:"
grep -B 2 -A 3 "SURVIVED" "$html_file"
echo ""
fi
done
- uses: actions/upload-artifact@v7
if: always()
with: { name: pit-reports, path: target/pit-reports/ }
- name: Run JMH benchmarks
run: >
mvn --batch-mode --no-transfer-progress exec:java
-Dexec.mainClass=org.openjdk.jmh.Main
-Dexec.classpathScope=test
-Dexec.args="StreamBufferThroughputBenchmark -wi 2 -i 3 -f 0 -rf json -rff target/jmh-results.json"
continue-on-error: true
- uses: actions/upload-artifact@v7
if: always()
with: { name: jmh-results, path: target/jmh-results.json }
check-snapshot:
name: "Check: main branch / SNAPSHOT"
needs: [report]
runs-on: ubuntu-latest
if: >-
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
(github.event_name == 'workflow_dispatch' && !startsWith(github.ref, 'refs/tags/v'))
steps:
- name: Confirm snapshot ref
run: echo "Confirmed on snapshot ref ${{ github.ref }}"
check-tag:
name: "Check: v* tag"
needs: [report]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Confirm tag ref
run: echo "Confirmed on tag ${{ github.ref }}"
publish-snapshot:
name: Publish Snapshot to Central
needs: [check-snapshot, code-style]
if: needs.check-snapshot.result == 'success' && inputs.publish_to_central
runs-on: ubuntu-latest
environment: maven-central
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
java-version: '21'
distribution: temurin
cache: maven
server-id: central
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
gpg-passphrase: MAVEN_GPG_PASSPHRASE
- name: Guard - require a -SNAPSHOT version
shell: bash
run: |
VERSION=$(mvn -q -DforceStdout help:evaluate -Dexpression=project.version | tail -n1)
echo "Resolved project version: $VERSION"
case "$VERSION" in
*-SNAPSHOT) echo "OK: -SNAPSHOT version, continuing snapshot deploy." ;;
*) echo "::error::Refusing to publish non-SNAPSHOT version '$VERSION' from the snapshot job. Snapshot publishing requires a -SNAPSHOT version; releases go through the v* tag path."; exit 1 ;;
esac
- name: Deploy snapshot
run: mvn --batch-mode --no-transfer-progress -P release deploy -DskipTests
env:
MAVEN_USERNAME: ${{ secrets.CENTRAL_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.CENTRAL_TOKEN }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
- name: Collect signed artifacts
run: |
mkdir -p signed-snapshot-assets
cp target/*.jar signed-snapshot-assets/ 2>/dev/null || true
cp target/*.jar.asc signed-snapshot-assets/ 2>/dev/null || true
- uses: actions/upload-artifact@v7
with:
name: signed-snapshot-assets
path: signed-snapshot-assets/
github-snapshot:
name: Update Snapshot Pre-release on GitHub
needs: [publish-snapshot]
if: needs.publish-snapshot.result == 'success'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/download-artifact@v8
with:
name: signed-snapshot-assets
path: snapshot-assets/
- name: Update snapshot pre-release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release view snapshot --repo ${{ github.repository }} 2>/dev/null \
|| gh release create snapshot \
--repo ${{ github.repository }} \
--prerelease \
--title "Snapshot (latest)" \
--notes "Latest snapshot build from the main branch."
gh release upload snapshot snapshot-assets/* \
--repo ${{ github.repository }} \
--clobber
publish-release:
name: Publish Release to Central
needs: [check-tag, code-style]
if: needs.check-tag.result == 'success' && inputs.publish_to_central
runs-on: ubuntu-latest
environment: maven-central
permissions:
contents: write
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
java-version: '21'
distribution: temurin
cache: maven
server-id: central
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
gpg-passphrase: MAVEN_GPG_PASSPHRASE
- name: Deploy release
run: mvn --batch-mode --no-transfer-progress -P release deploy -DskipTests
env:
MAVEN_USERNAME: ${{ secrets.CENTRAL_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.CENTRAL_TOKEN }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
- name: Collect signed artifacts
run: |
mkdir -p signed-release-assets
cp target/*.jar signed-release-assets/ 2>/dev/null || true
cp target/*.jar.asc signed-release-assets/ 2>/dev/null || true
- uses: actions/upload-artifact@v7
with:
name: signed-release-assets
path: signed-release-assets/
github-release:
name: Attach Binaries to GitHub Release
needs: [publish-release]
if: needs.publish-release.result == 'success'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/download-artifact@v8
with:
name: signed-release-assets
path: release-assets/
- name: Upload release assets
uses: softprops/action-gh-release@v3
with:
files: release-assets/*