#68: Jenkins-Build mit -Drevision-Übergabe und robuster Shade-JAR-Archivierung

- Neues Jenkinsfile mit pipeline-Struktur (Checkout, Version bestimmen,
  Maven Build, Archive JAR, Berichte, Artefakt ablegen, Aufräumen)
- Maven-Build übergibt -Drevision=MAJOR.MINOR.BUILD_NUMBER
- Archive-Stage: Bash explizit via #!/usr/bin/env bash + set -euo pipefail,
  mapfile-Prüfung bricht bei 0 oder mehr als 1 Shade-JAR mit Fehlermeldung ab
- MSI-Build als bewusst manuell dokumentiert (Kommentar im Jenkinsfile)
- MAJOR/MINOR via Jenkins-Parameter, EFFECTIVE_MAJOR/MINOR-Stub für State-Datei
- docs/betrieb.md: CI-Hinweis zum manuellen MSI-Build ergänzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-30 10:43:48 +02:00
parent c6379c04f6
commit 500a8c5340
2 changed files with 155 additions and 0 deletions
Vendored
+151
View File
@@ -0,0 +1,151 @@
// Jenkins-Pipeline für den PDF KI Renamer
// Läuft auf einem Linux-Container (Synology NAS).
// Der MSI-Build ist Windows-only (jpackage + WiX Toolset 3.x). Jenkins läuft im
// Linux-Container auf Synology NAS und kann kein MSI erzeugen. Der MSI-Build
// wird bewusst manuell auf der Windows-Entwicklungsmaschine ausgeführt:
// .\mvnw.cmd clean package -P release -pl pdf-umbenenner-packaging --also-make -DskipTests
pipeline {
agent any
// MAJOR und MINOR werden manuell als Jenkins-Parameter gepflegt.
// BUILD_NUMBER wird automatisch durch Jenkins vergeben.
// Die resultierende Versionsnummer lautet: MAJOR.MINOR.BUILD_NUMBER
parameters {
string(
name: 'MAJOR',
defaultValue: '3',
description: 'Hauptversionsnummer (manuell pflegen)'
)
string(
name: 'MINOR',
defaultValue: '0',
description: 'Nebenversionsnummer (manuell pflegen)'
)
}
environment {
// Effektive Versionsteile übernommen aus Parametern oder State-Datei.
// Hinweis: Wenn MAJOR/MINOR aus einer persistierten State-Datei gelesen
// werden sollen (z. B. /builds/version.state), muss die Logik unten in
// der Stage 'Version bestimmen' entsprechend ergänzt werden.
// Im Minimalbetrieb werden die Parameter direkt übernommen.
EFFECTIVE_MAJOR = "${params.MAJOR}"
EFFECTIVE_MINOR = "${params.MINOR}"
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
// Optionaler Stub: MAJOR/MINOR aus persistierter State-Datei laden.
// Wenn das bestehende Jenkins-Setup die Versionsnummern in einer
// State-Datei unter /builds/version.state persistiert, kann diese
// Stage die Umgebungsvariablen EFFECTIVE_MAJOR und EFFECTIVE_MINOR
// vor dem Build überschreiben. Ansonsten gelten die Parameter-Werte.
stage('Version bestimmen') {
steps {
script {
// Platzhalter: hier bei Bedarf State-Datei einlesen,
// z. B.:
// def state = readFile('/builds/version.state').trim()
// env.EFFECTIVE_MAJOR = state.split('\\.')[0]
// env.EFFECTIVE_MINOR = state.split('\\.')[1]
//
// Im Minimalbetrieb werden die Parameter-Werte verwendet:
echo "Buildversion: ${env.EFFECTIVE_MAJOR}.${env.EFFECTIVE_MINOR}.${env.BUILD_NUMBER}"
}
}
}
stage('Maven Build') {
steps {
// -Drevision übergibt die vollständige Versionsnummer an Maven.
// Das flatten-maven-plugin im Parent-POM löst ${revision} in
// allen installierten POMs auf, sodass kein unaufgelöstes
// ${revision} in ~/.m2 verbleibt.
sh "mvn clean verify -Drevision=${env.EFFECTIVE_MAJOR}.${env.EFFECTIVE_MINOR}.${env.BUILD_NUMBER}"
}
}
stage('Archive JAR') {
steps {
// Bash wird explizit erzwungen (#!/usr/bin/env bash, set -euo pipefail),
// weil Jenkins-Agenten standardmäßig sh (dash) verwenden, das kein
// mapfile kennt. mapfile zählt exakt die gefundenen Shade-JARs und
// bricht den Build ab, wenn nicht genau eines vorhanden ist.
sh '''#!/usr/bin/env bash
set -euo pipefail
mapfile -t JARS < <(find pdf-umbenenner-bootstrap/target \
-maxdepth 1 -name "pdf-umbenenner-bootstrap-*.jar" \
! -name "*-sources.jar" ! -name "*-javadoc.jar")
test "${#JARS[@]}" -eq 1 \
|| { echo "FEHLER: Erwartet genau 1 Shade-JAR, gefunden: ${#JARS[@]}"; exit 1; }
JAR_NAME="pdf-ki-renamer-${EFFECTIVE_MAJOR}.${EFFECTIVE_MINOR}.${BUILD_NUMBER}.jar"
cp "${JARS[0]}" "$JAR_NAME"
echo "Shade-JAR archiviert als: $JAR_NAME"
'''
archiveArtifacts artifacts: 'pdf-ki-renamer-*.jar', fingerprint: true
}
}
stage('Berichte') {
steps {
// JUnit-Testergebnisse einlesen
junit testResults: '**/target/surefire-reports/*.xml', allowEmptyResults: true
// JaCoCo-Coverage (falls im Build erzeugt)
// jacoco execPattern: '**/target/jacoco.exec'
// PIT-Mutationstest-Bericht (falls im Build erzeugt)
// publishHTML(target: [reportDir: 'target/pit-reports', ...])
}
}
stage('Artefakt ablegen') {
steps {
// JAR-Kopie in zentrales Build-Verzeichnis ablegen.
// Pfad /builds/ muss auf dem Jenkins-Agent gemountet sein.
sh '''#!/usr/bin/env bash
set -euo pipefail
BUILD_DIR="/builds/${EFFECTIVE_MAJOR}.${EFFECTIVE_MINOR}.${BUILD_NUMBER}"
mkdir -p "$BUILD_DIR"
cp pdf-ki-renamer-*.jar "$BUILD_DIR/"
echo "Artefakt abgelegt unter: $BUILD_DIR"
'''
}
}
stage('Aufräumen') {
steps {
// Lokale JAR-Kopie im Workspace entfernen (Artefakt ist archiviert)
sh '''#!/usr/bin/env bash
set -euo pipefail
rm -f pdf-ki-renamer-*.jar
echo "Aufräumen abgeschlossen."
'''
}
}
}
post {
success {
echo "Build ${env.EFFECTIVE_MAJOR}.${env.EFFECTIVE_MINOR}.${env.BUILD_NUMBER} erfolgreich abgeschlossen."
}
failure {
echo "Build ${env.EFFECTIVE_MAJOR}.${env.EFFECTIVE_MINOR}.${env.BUILD_NUMBER} fehlgeschlagen."
}
always {
// Workspace nach Abschluss bereinigen
cleanWs()
}
}
}
+4
View File
@@ -451,6 +451,10 @@ benötigt keine separate Java-Installation auf dem Zielsystem. Das Shade-JAR ble
primäre Distributionsartefakt; der MSI ist eine zusätzliche Option für Systeme ohne primäre Distributionsartefakt; der MSI ist eine zusätzliche Option für Systeme ohne
Java-Installation und für den Standard-Installationspfad nach `C:\Program Files\`. Java-Installation und für den Standard-Installationspfad nach `C:\Program Files\`.
> **Hinweis zur CI-Umgebung:** Der MSI-Build ist Windows-only (`jpackage` + WiX Toolset 3.x).
> Jenkins läuft im Linux-Container auf dem Synology NAS und kann kein MSI erzeugen.
> Der MSI-Build wird bewusst manuell auf der Windows-Entwicklungsmaschine ausgeführt.
**Voraussetzungen für den Installer-Build (nur auf der Entwicklungsmaschine):** **Voraussetzungen für den Installer-Build (nur auf der Entwicklungsmaschine):**
- Windows x64 - Windows x64
- JDK 21 im PATH - JDK 21 im PATH