1. Project Objective
The objective of this project is to design and implement an automated, scalable CI/CD pipeline using AWS managed services. The pipeline is triggered automatically on every code change and performs the following tasks:
- Source code version control and management
- Centralized dependency management
- Automated static code analysis using SonarCloud
- Build artifact generation
- Secure storage of configuration parameters
- Pipeline status notifications
This approach ensures high code quality, reliability, and full transparency throughout the development lifecycle.
2. Architecture
The architecture is fully based on AWS managed services and follows a modular, cloud-native pipeline design.
Pipeline Process Flow
- Developer Commit: Developer writes code in local editor and commits to Git repository
- Push to Bitbucket: Code is pushed to Bitbucket (AWS Codepipeline trigger)
- Pipeline Trigger: AWS CodePipeline detects the change and starts automatically
- Source Stage: Pipeline fetches the latest code from Bitbucket repository
- Review Stage: AWS CodeBuild runs tests, SonarCloud performs code quality analysis
- Quality Gate: Code must pass quality requirements before proceeding
- Build Stage: AWS CodeBuild compiles code, runs tests, and creates artifacts
- Artifact Storage: Built artifacts are stored in S3 for deployment
- Dependencies: AWS CodeArtifact manages and caches all project dependencies
3. Practical Implementation
In the practical section, the CI/CD pipeline is implemented step by step. Each stage builds logically on the previous one and represents a functional component of the overall architecture.
3.1) – AWS CodeCommit Setup
In diesem Schritt wird die komplette AWS EC2 Infrastruktur für das CI-Projekt vorbereitet. Dazu gehören AWS-Zugang, Key Pair, Security Groups sowie die Erstellung der EC2-Instanzen mit passendem Betriebssystem und User Data.
- EC2 → Key Pairs → Create key pair
- Name: profile-ci-key
- Typ: RSA
- Format: .pem
- Key wird für alle drei EC2 Instanzen verwendet
- SSH – Port 22 (My IP)
- HTTP – Port 80
- Jenkins – Port 8080(IPv4, IPv6)
- Port 8080(sonar-sg)
- SSH – Port 22 (My IP)
- Nexus UI – Port 8081
- Port 8081 (from jenkins-sg)
- SSH – Port 22 (My IP)
- HTTP – Port 80 (Nginx)
- SonarQube – Port 80 (jenkins-sg)
- EC2 → Launch Instance
- Key Pair: profile-ci-key
- Security Group je nach Tool auswählen
- User Data wird beim Erstellen der Instanz hinterlegt
- OS: Ubuntu 24.04
- Security Group: jenkins-sg
- User Data:
– Java installieren
– Jenkins installieren & starten - Standard User: ubuntu
- http://JENKINS_PUBLIC_IP:8080
- OS: Amazon Linux 2023
- Security Group: nexus-sg
- User Data:
– Java installieren
– Nexus herunterladen & konfigurieren - Standard User: ec2-user
- http://NEXUS_PUBLIC_IP:8081
- OS: Ubuntu 24.04
- Security Group: sonar-sg
- User Data:
– Java + PostgreSQL
– SonarQube Installation
– Nginx als Reverse Proxy - Standard User: ubuntu
- http://SONAR_PUBLIC_IP
- Jenkins Zugriff via: http://SONAR_PRIVATE_IP:8080
1. Anmeldung im AWS Account
2. Key Pair erstellen
3. Security Groups erstellen
4. EC2 Instanzen mit User Data erstellen
3.2) Post-Installation – Jenkins, Nexus & SonarQube Setup
Nach der Erstellung der EC2-Instanzen folgt die Post-Installation. In diesem Schritt werden Jenkins, Nexus und SonarQube vollständig konfiguriert, sodass ein funktionierender CI-Pipeline entsteht.
-
Anmeldung auf der Jenkins-EC2 per SSH
Verbindung zur Jenkins-EC2 über Git Bash mittels SSH herstellen. Anschließend prüfen, ob Jenkins und Java korrekt laufen:
systemctl status jenkins
java -version -
Erstzugang & Initiales Admin-Setup
Zugriff auf Jenkins über den Browser:http://<JENKINS_PUBLIC_IP>:8080
Das initiale Admin-Passwort wird direkt auf der Jenkins-EC2 ausgelesen:
cat /var/lib/jenkins/secrets/initialAdminPassword
Dieses Passwort wird beim ersten Login verwendet, um Jenkins zu entsperren und die empfohlenen Plugins zu installieren. -
Erstellung eines Admin-Benutzers
Nach der Plugin-Installation wird ein eigener Admin-User erstellt (Username, Passwort, E-Mail).
Dieser Benutzer wird künftig für alle Jenkins-Operationen verwendet. - GitHub Integration Plugin – Source Code Checkout aus GitHub
- Nexus Artifact Uploader – Upload von Build-Artefakten nach Nexus
- Maven Integration – Maven Build Management
- SonarQube Scanner – Code-Qualitätsanalyse
- Slack Notification – Build-Status Benachrichtigungen
- Build Timestamp – Eindeutige Build-Versionierung
-
Jenkins Tools-Konfiguration
Konfiguration der benötigten Build-Werkzeuge, damit Jenkins Builds korrekt ausführen kann. -
Java (JDK) konfigurieren
In Jenkins zu Manage Jenkins → Tools navigieren und unter JDK Installations eine neue JDK-Konfiguration hinzufügen.
Auf der Jenkins-EC2 per SSH prüfen, wo Java installiert ist:
ls /usr/lib/jvm
Den passenden JDK-Pfad kopieren und in Jenkins als JAVA_HOME eintragen, z.B.:
/usr/lib/jvm/java-17-openjdk-amd64 -
Maven konfigurieren
Ebenfalls unter Manage Jenkins → Tools zu Maven Installations gehen und eine neue Maven-Version hinzufügen (z.B. Maven 3.9.9).
Jenkins lädt Maven automatisch oder nutzt die konfigurierte Version für alle Maven-Builds. -
SonarScanner konfigurieren
Ebenfalls unter Manage Jenkins → Tools zu SonarQube Scanner Installations gehen und eine neue SonarQube Scanner (sonnarscanner) hinzufügen (z.B. SonarQube Scanner 4.7.0.2747).
- Nach der Konfiguration aller Tools die Änderungen mit Save speichern.
-
Anmeldung auf der Nexus-EC2 per SSH
Verbindung zur Nexus-EC2 über Git Bash mittels SSH herstellen. Anschließend prüfen, ob der Nexus-Service korrekt läuft:
systemctl status nexus -
Login & Initiales Setup
Zugriff auf Nexus über den Browser:http://<NEXUS_PUBLIC_IP>:8081
Beim ersten Login wird das initiale Admin-Passwort benötigt. Dieses Passwort befindet sich auf der Nexus-EC2 und kann wie folgt ausgelesen werden:
cat /opt/sonatype-work/nexus3/admin.password
Danach im Browser mit Username: admin anmelden, das ausgelesene Passwort eingeben und anschließend ein neues Admin-Passwort setzen. -
Repository Administration
Navigation: Administration → Repositories → Create Repository
Hier werden die benötigten Maven-Repositories für den CI-Prozess erstellt. -
profile-release (maven2 hosted)
Repository für stabile Release-Artefakte (z.B. Versionen wie1.0.0). Artefakte in diesem Repository gelten als produktionsreif. -
profile-snapshot (maven2 hosted)
Repository für Snapshot-Versionen während der Entwicklungsphase (z.B.1.0.0-SNAPSHOT). -
pro-maven-central (maven2 proxy)
Proxy- und Cache-Repository für Maven Central (Nexus holt maven Dependencies hier:https://repo1.maven.org/maven2/). und liefert es weiter an Maven in jenkins
Reduziert externe Abhängigkeiten, beschleunigt Builds und erhöht die Verfügbarkeit. -
pro-maven-group (maven2 group)
Zentrales Gruppen-Repository für Jenkins und Maven.
Kombiniert:- profile-release
- profile-snapshot
- pro-maven-central
-
Login & Initiale Konfiguration
Zugriff überhttp://<SONAR_PUBLIC_IP>, initiale Admin-Anmeldung und Passwort-Änderung. -
Token-Erstellung für Jenkins
Generierung eines SonarQube Tokens und Speicherung in Jenkins Credentials. -
Quality Gate Integration
Jenkins stoppt den Pipeline automatisch, wenn der Quality Gate Status fehlschlägt.
1) Jenkins – Konfiguration nach der Installation
Benötigte Jenkins Plugins:
-
Navigation: Manage Jenkins → Plugins → Available Plugins
2) Nexus Repository – Setup & Repositories
Nexus dient als zentrales Artefakt- und Dependency-Repository für alle Maven-Builds im Continuous-Integration-Prozess.
Maven Repositories
3) SonarQube – Code Quality & Quality Gate
3.3) Git & GitHub – Repository erstellen und Code migrieren
In diesem Schritt wird der bestehende Quellcode in ein GitHub-Repository migriert und mit den lokalen Entwicklungswerkzeugen (VS Code & Git Bash) integriert.
-
Neues Repository auf GitHub anlegen
Erstellung eines leeren Repositories (profile) ohne README, um Konflikte beim ersten Push zu vermeiden. - Das Repository dient als zentrale Quelle für Jenkins, Webhooks und CI-Pipelines.
1) GitHub Repository erstellen
2) Lokalen Code mit Git initialisieren
Auf der Entwickler-Maschine (lokal) wird das bestehende Projekt unter Versionskontrolle gestellt.
cd profile
git init
git branch -M main
Ergebnis: Das Projekt ist jetzt ein lokales Git-Repository mit dem Hauptbranch main.
3) GitHub Repository als Remote hinzufügen
git remote add origin https://github.com/<username>/profile.git
git remote -v
Dadurch wird das lokale Repository mit GitHub verbunden. Jenkins greift später genau auf dieses Remote-Repository zu.
4) Code committen und nach GitHub pushen
git status
git add .
git commit -m "Initial commit – Profile Application"
git push -u origin main
Nach dem Push ist der komplette Code auf GitHub verfügbar und versionskontrolliert.
3.4) Build Job mit Nexus Integration (Jenkins + Maven)
Ziel: Jenkins baut die Profile-Applikation mit Maven, lädt Abhängigkeiten über Nexus (Proxy/Group Repo) und kann danach Artefakte in Nexus Hosted Repos (Snapshots/Releases) veröffentlichen.
- In Jenkins Browser: Manage Jenkins → Credentials → (Global) → Add Credentials
-
Typ: Username with password
Username/Password = Nexus Benutzer.
ID =nexuslogin(diese ID wird später im Jenkinsfile referenziert). -
Jenkins Pipeline erstellen
In Jenkins auf New Item klicken und einen neuen Pipeline-Job anlegen.
Schritte in Jenkins:-
Name des Jobs:
profile-ci-pipeline - Job-Typ: Pipeline auswählen → OK
- Unter Definition die Option Pipeline script from SCM wählen
- SCM-Typ: Git
-
Repository URL:
git@github.com:<username>/profile.git - Zugangsdaten: SSH Private Key von GitHub auswählen
-
Branch: z.B.
jenkins-ci -
Script Path:
Jenkinsfile - Konfiguration speichern (Save)
Jenkinsfile
Das Jenkinsfile wird im Projekt mit Visual Studio Code erstellt und beschreibt alle CI-Stages (Build, Test, Analyse, Upload).
-
Name des Jobs:
1) Jenkins Credentials (Nexus Login) anlegen
Hinweis:
Um Probleme nach einem Shutdown oder Power-Off der Jenkins-EC2-Instanz
(z.B. Änderung der Public IP-Adresse) zu vermeiden,
sollte in Jenkins eine feste Basis-URL konfiguriert werden.
Dazu in Jenkins navigieren zu:
Manage Jenkins → System
und im Feld Jenkins URL eine feste URL eintragen, z.B.:
http://myjenkins.ci.com
2) Jenkinsfile – Build Stage mit Nexus
Jenkins setzt Umgebungsvariablen (Nexus IP/Port, Repo-Namen) und nutzt Credentials, um settings.xml
dynamisch mit User/Pass zu füllen.
Jenkinsfile (Build-Teil)
pipeline {
environment {
NEXUSIP = '--EC2_NEXUS_PRIVATE_IP--'
NEXUSPORT = '8081'
NEXUS_GRP_REPO = 'vpro-maven-group'
NEXUS_LOGIN = 'nexuslogin'
}
stages {
stage('Build') {
steps {
sh 'mvn -s settings.xml -DskipTests install' // Führt den Maven-Build aus, nutzt Nexus über settings.xml und überspringt Tests
}
}
}
}
}
-
mvn -s settings.xml ...→ Maven verwendet exakt settings.xml (Mirror auf Nexus + Deploy Server-IDs). -
-DskipTests→ verkürzt Build-Zeit (Tests kommen typischerweise in eigener Stage).
3) Maven settings.xml (Nexus Mirror + Server Credentials)
Maven muss wissen: (1) wo es Dependencies holt (Mirror → Nexus Group Repo) und (2) mit welchen Credentials es in Hosted Repos deployen darf (servers).
Beispiel: settings.xml
<settings>
<servers>
<server>
<id>${env.SNAP_REPO}</id>
<username>${env.NEXUS_USER}</username>
<password>${env.NEXUS_PASS}</password>
</server>
<server>
<id>${env.RELEASE_REPO}</id>
<username>${env.NEXUS_USER}</username>
<password>${env.NEXUS_PASS}</password>
</server>
<server>
<id>${env.CENTRAL_REPO}</id>
<username>${env.NEXUS_USER}</username>
<password>${env.NEXUS_PASS}</password>
</server>
<server>
<id>${env.NEXUS_GRP_REPO}</id>
<username>${env.NEXUS_USER}</username>
<password>${env.NEXUS_PASS}</password>
</server>
</servers>
<mirrors>
<mirror>
<id>${env.CENTRAL_REPO}</id>
<name>${env.CENTRAL_REPO}</name>
<url>http://${env.NEXUSIP}:${env.NEXUSPORT}/repository/${env.NEXUS_GRP_REPO}/</url>
<mirrorOf>*</mirrorOf>
</mirror>
</mirrors>
</settings>
<mirrorOf>*</mirrorOf> sorgt dafür, dass Maven ALLE Repos über Nexus zieht
(praktisch: Nexus Group Repo wie vpro-maven-group).
4) Was passiert beim Build technisch?
- Jenkins checkt den Code aus GitHub aus.
- Maven startet den Build und fragt NEXUS Dependencies an.
- Durch Mirror gehen alle Requests an:
http://NEXUSIP:NEXUSPORT/repository/vpro-maven-group/ - Nexus liefert Dependencies aus Cache oder holt sie (einmalig) aus Maven Central.
- Build erzeugt Artefakt(e) unter
target/(z.B. WAR/JAR).
Ergebnis der Build-Stage (erster Jenkins Build)
Beim ersten Durchlauf der Pipeline ist der Build direkt in der Checkout/Fetch-Phase fehlgeschlagen. Ursache war nicht Maven oder der Code, sondern die SSH-Verifikation zu GitHub (Host Key Verification).
Was ist passiert?
-
Build #1: FAIL
Der Job wurde gestartet, aber Jenkins konnte das Repository nicht per SSH fetchen. Dadurch wurde die Pipeline abgebrochen, bevor überhaupt Maven oder Tests laufen konnten.

Fehlermeldung (Konsole)
In der Konsole sieht man klar den Grund: „Host key verification failed“. Jenkins hat striktes Checking aktiv, aber der GitHub-Host-Key war auf der Jenkins-EC2 noch nicht bekannt.

Was habe ich gemacht, damit der nächste Build funktioniert?
-
Fix (SSH Host Key bekannt machen)
Auf der Jenkins-EC2 habe ich den GitHub Host-Key in~/.ssh/known_hostseingetragen, damit GitHub als „trusted host“ gilt. Typisch z.B. mitssh-keyscanfürgithub.com. Danach konnte Jenkins das Repo per SSH sauber auschecken.-
1. Anmeldung auf der Jenkins-EC2
Zuerst habe ich mich per SSH auf die Jenkins-EC2 verbunden. -
2. Wechsel zum Jenkins-User
Da Jenkins selbst als Benutzerjenkinsläuft, habe ich zu diesem User gewechselt:
sudo su - jenkins
So stelle ich sicher, dass der SSH-Trust für genau den Benutzer gesetzt wird, der später das Git-Checkout ausführt. -
3. Manueller SSH-Test zu GitHub
Anschließend habe ich bewusst eine manuelle SSH-Verbindung zu GitHub aufgebaut:
ssh -T git@github.com
Beim ersten Verbindungsversuch erscheint Sicherheitsabfrage
Was bedeutet diese Abfrage?
SSH teilt hier mit:
- Der GitHub-Server ist noch nicht bekannt
- Der angezeigte Fingerprint gehört zum offiziellen GitHub-SSH-Key
- SSH fragt, ob dieser Host dauerhaft als vertrauenswürdig gespeichert werden soll
Entscheidung & Wirkung
-
Eingabe von
yes
Mityesbestätige ich:
→ GitHub wird in~/.ssh/known_hostsgespeichert
→ Zukünftige SSH-Verbindungen sind erlaubt
→ Kein Host-Key-Fehler mehr bei Jenkins
-
1. Anmeldung auf der Jenkins-EC2
-
Ergebnis
Der nächste Build lief erfolgreich durch (Checkout → Build → weitere Stages).

Nach dem Build: Dependencies & Artefakte in Nexus sichtbar
Nach einem erfolgreichen Pipeline-Lauf sieht man in Nexus, dass Maven-Abhängigkeiten über das Proxy/Group Repository
aufgelöst und gecached wurden (z.B. im vpro-maven-central).

3.5) GitHub Webhook
Der GitHub Webhook verbindet das GitHub-Repository direkt mit Jenkins und ermöglicht das automatische Starten des CI-Pipelines bei jedem Code-Commit.
- Automatischer Build bei jedem git push
- Kein manueller Start des Jenkins Jobs
- Schnelles Feedback über Build- und Code-Qualität
- Developer pusht Code in das GitHub Repository
- GitHub Webhook sendet ein HTTP POST Event
- Jenkins empfängt das Event
- Jenkins startet automatisch den CI Pipeline Job
- Jenkins Job → Build Triggers
- Option aktivieren:
GitHub hook trigger for GITScm polling - Repository → Settings → Webhooks → Add Webhook
- Payload URL:
http://<JENKINS_PUBLIC_IP>:8080/github-webhook/ - Content type:
application/json - Trigger Event: Just the push event
- Jenkins Security Group erlaubt eingehenden Traffic auf Port 8080
- Webhook Endpoint ist öffentlich erreichbar
- Ziel:
- Ablauf:
- Konfiguration in Jenkins:
- Konfiguration in GitHub
- Sicherheit & Netzwerk
- Ergebnis
Jeder Push auf GitHub triggert automatisch den Jenkins CI Pipeline (Build → SonarQube → Quality Gate → Nexus Upload).
3.6) SonarQube Server Integration Stage
Nach dem Build durchläuft die CI-Pipeline mehrere Qualitätsstufen. Diese Stages stellen sicher, dass nur getesteter, sauberer und qualitativ hochwertiger Code weiterverarbeitet wird.
1- Stage: Test
stage('Test') {
steps {
sh 'mvn -s settings.xml test'
}
}
- Führt alle Unit-Tests des Projekts aus
- Nutzt
settings.xml, um Abhängigkeiten über Nexus zu beziehen - Erzeugt JUnit-Testberichte in
target/surefire-reports - ❌ Bei fehlgeschlagenen Tests wird die Pipeline abgebrochen
Ziel: Sicherstellen, dass die Anwendung funktional korrekt ist.
2- Stage: Checkstyle-Analyse
stage('Checkstyle Analysis') {
steps {
sh 'mvn -s settings.xml checkstyle:checkstyle'
}
}
- Überprüft den Java-Code-Stil anhand definierter Regeln
- Erkennt Verstöße gegen Coding-Standards (Naming, Struktur, Komplexität)
- Erzeugt den Bericht
target/checkstyle-result.xml - Der Bericht wird später von SonarQube ausgewertet
- Ziel: Einheitlicher, wartbarer und sauberer Quellcode.
3- Stage: SonarQube-Analyse
- SonarQube läuft auf eigener EC2 (z.B.
http://<SONAR_PUBLIC_IP>) - Jenkins kann SonarQube erreichen (Security Group / Netzwerk ok)
- In Jenkins ist SonarQube als Server registriert (Manage Jenkins → System → SonarQube servers)
- Ein Sonar Token ist in Jenkins Credentials gespeichert (Secret Text)
- SonarScanner ist verfügbar (Jenkins Tool oder per Maven Plugin)
- sonarserver (Jenkins SonarQube Server Name) → wird in Pipeline referenziert
- sonartoken (Secret Text) → Zugriff für Scanner auf SonarQube
-
SonarQube Token erstellen in SonarQube:
My Account → Security → Generate Token → z.B.jenkins-token -
Token in Jenkins speichern:
Manage Jenkins → Credentials → (global) → Add Credentials → Secret text
Secret = <SONAR_TOKEN>
ID = sonartoken -
SonarQube Server in Jenkins registrieren:
Manage Jenkins → System → SonarQube servers
Name: sonarserver
Server URL: http://<SONAR_PRIVATE_IP>
Authentication Token: sonartoken
Voraussetzungen:
Credentials (Best Practice):
Jenkins Konfiguration (einmalig)
SonarQube Stage in Pipeline
stage('Sonar Analysis') {
environment {
scannerHome = tool "${SONARSCANNER}"
}
steps {
withSonarQubeEnv("${SONARSERVER}") {
sh '''
${scannerHome}/bin/sonar-scanner \
-Dsonar.projectKey=profile \
-Dsonar.projectName=profile \
-Dsonar.projectVersion=1.0 \
-Dsonar.sources=src/ \
-Dsonar.java.binaries=target/test-classes \
-Dsonar.junit.reportsPath=target/surefire-reports/ \
-Dsonar.jacoco.reportsPath=target/jacoco.exec \
-Dsonar.java.checkstyle.reportPaths=target/checkstyle-result.xml
'''
}
}
}
Was passiert in dieser Stage?
- Start des SonarScanners aus Jenkins
- Übertragung von Code und Metriken an SonarQube
- Analyse von:
- Bugs und Sicherheitslücken
- Code Smells
- Testabdeckung (JaCoCo)
- Checkstyle-Ergebnissen
- Ergebnisse werden in der SonarQube-Datenbank gespeichert
-
waitForQualityGatewartet auf das Ergebnis der SonarQube-Analyse -
timeoutverhindert ein endloses Warten auf die Antwort von SonarQube -
abortPipeline: truestoppt die Pipeline sofort, wenn der Quality Gate Status FAILED ist
✅ Nach dieser Stage ist das Projekt in SonarQube sichtbar und bereit für die Quality-Gate-Prüfung.
Quality Gate stage (SonarQube)
stage("Quality Gate") {
steps {
timeout(time: 1, unit: 'HOURS') {
waitForQualityGate abortPipeline: true
}
}
}
stage("Quality Gate") {
steps {
timeout(time: 1, unit: 'HOURS') {
waitForQualityGate abortPipeline: true
}
}
}Diese Stage stellt sicher, dass der Build nur dann fortgesetzt wird, wenn die Code-Qualitätsregeln von SonarQube erfüllt sind.
Erklärung
❌ Wenn der Quality Gate fehlschlägt, wird kein Artefakt veröffentlicht. Dadurch wird sichergestellt, dass nur qualitativ hochwertiger Code weitergegeben wird.
Zusammenfassung
- Test → Funktionale Validierung
- Checkstyle → Code-Qualität & Standards
- SonarQube → Zentrale Qualitätsbewertung
Ergebnis nach Hinzufügen der Stages: Test, Checkstyle & Sonar Analysis
Nach der Erweiterung der Jenkins-Pipeline um die Stages Test, Checkstyle Analysis und Sonar Analysis wurde der CI-Prozess deutlich qualitätsorientierter. Die folgenden Ergebnisse zeigen den erfolgreichen Ablauf dieser neuen Stages.
1) Jenkins Pipeline – Erfolgreicher Build
Die Jenkins-Konsole zeigt, dass alle neuen Stages ohne Fehler durchlaufen wurden. Insbesondere wurde der SonarQube-Analyseprozess erfolgreich abgeschlossen und das Quality Gate als OK bewertet.

2) SonarQube Quality Gate – Passed
Nach Abschluss der statischen Codeanalyse bestätigt SonarQube, dass alle definierten Quality-Gate-Bedingungen erfüllt wurden. Damit darf die Pipeline fortgesetzt werden (z. B. Artefakt-Upload).

3) SonarQube Projektübersicht – Code Quality Metriken
Die SonarQube-Dashboard-Ansicht zeigt detaillierte Qualitätsmetriken des Projekts: Bugs, Vulnerabilities, Code Smells, Test Coverage und technische Schulden. Obwohl Warnungen existieren, bleibt das Quality Gate insgesamt bestanden.

3.7) Artifact Upload in Nexus
Nach erfolgreichem Build, Tests und bestandener Code-Analyse wird das erzeugte Artefakt in das zentrale Artefakt-Repository Nexus Repository Manager hochgeladen.
- Vermeidet das Überschreiben von Artefakten im Nexus Repository
- Jeder Jenkins-Build erzeugt ein eindeutig versioniertes Artefakt
- Erleichtert Debugging, Rollbacks und Nachvollziehbarkeit
Timestamp – Versionierung des Artefakts vor dem Upload
Bevor das Artefakt in das Nexus Repository hochgeladen wird, wird ein Timestamp verwendet, um jede Build-Version eindeutig zu kennzeichnen. Dadurch wird verhindert, dass sich Artefakte überschreiben, und jeder Build bleibt eindeutig nachvollziehbar.
Warum ein Timestamp?
Was passiert technisch?
Das erzeugte WAR-File im target/-Verzeichnis wird logisch
versioniert, z.B.:
profile-v2.war
→ profile-v2-${BUILD_ID}-${BUILD_TIMESTAMP}.war
Der Timestamp selbst wird nicht direkt im Dateinamen geändert, sondern als Version-Attribut beim Upload nach Nexus verwendet.
Konfiguration in Jenkins
- Installation des Jenkins Plugins Build Timestamp
- Aktivierung des Plugins in der Jenkins Pipeline (Manage jenkins -> system -> Build Timestamp)
-
Nutzung der Jenkins-Variablen
BUILD_IDundBUILD_TIMESTAMPim Upload-Stage
- Stage: Publish Artifact to Nexus
stage("UploadArtifact") {
steps {
nexusArtifactUploader(
nexusVersion: 'nexus3',
protocol: 'http',
nexusUrl: "${NEXUSIP}:${NEXUSPORT}",
groupId: 'QA',
version: "${env.BUILD_ID}-${env.BUILD_TIMESTAMP}",
repository: "${RELEASE_REPO}",
credentialsId: "${NEXUS_LOGIN}",
artifacts: [
[artifactId: 'profileapp',
classifier: '',
file: 'target/vprofile-v2.war',
type: 'war']
]
)
}
}
Erklärung
- Verwendet das Jenkins Plugin Nexus Artifact Uploader
-
Lädt das erzeugte
.war-Artefakt nach Nexus 3 hoch -
Die Version wird dynamisch erzeugt:
BUILD_ID + BUILD_TIMESTAMP - Upload erfolgt nur nach bestandenem Quality Gate
- Zugangsdaten werden sicher über Jenkins Credentials verwaltet
Repository-Auswahl in Nexus
Maven entscheidet automatisch, in welches Repository das Artefakt
hochgeladen wird – abhängig von der Versionsnummer im pom.xml.
-
Snapshot-Version (
1.0-SNAPSHOT) →profile-snapshot -
Release-Version (
1.0) →profile-release
ℹ️ Beide Repositories sind über das pro-maven-group-Repository zusammengefasst, das als zentraler Zugriffspunkt dient.
Sicherheit & Credentials
- Nexus-Zugangsdaten sind nicht im Code gespeichert
- Credentials werden in Jenkins als:
- Username/Password Credentials
- z. B. ID:
nexuslogin
- Jenkins injiziert die Credentials als Umgebungsvariablen:
NEXUS_USERNEXUS_PASS
Ergebnis nach der Stage „Publish Artifact to Nexus“
- Repository: profile-release (maven2 hosted)
- GroupId: QA
- ArtifactId: profileapp
- Version: 36-26-01-20_23:46
- Datei: profileapp-36-26-01-20_23:46.war
Nach erfolgreichem Durchlauf aller vorherigen Pipeline-Stages (Build, Test, Checkstyle, Sonar Analysis und Quality Gate) wurde das erzeugte Artefakt automatisch im Nexus Repository veröffentlicht.
Das WAR-Artefakt wurde im profile-release Repository abgelegt und eindeutig versioniert, basierend auf Build-ID und Timestamp. Dadurch ist jeder Build klar nachvollziehbar und reproduzierbar.
Zusätzlich wurden automatisch Prüfsummen-Dateien (.md5 und
.sha1) generiert, um die Integrität des Artefakts sicherzustellen.

Ergebnis:
Das Artefakt steht nun zentral im Nexus Repository zur Verfügung und kann
von weiteren CI/CD- oder Deployment-Prozessen (CD, Docker, Kubernetes, EC2, etc.)
wiederverwendet werden.
3.8) Letzter Schritt: Slack Notification
In diesem finalen Schritt wird das Ergebnis der Jenkins-Pipeline automatisch an Slack gesendet. Dadurch wird das Team sofort informiert, ob der Build erfolgreich war oder fehlgeschlagen ist.
Benötigte Credentials / Jenkins Setup / Slack Konfiguration
-
Slack – Workspace & Channel erstellen
Im Slack-Browser einen neuen Workspace erstellen (profilecicd) und darin einen Channel anlegen (#jenkinscicd), der für CI-Benachrichtigungen genutzt wird. -
Slack App „Jenkins CI“ hinzufügen
In Slack unter Apps hinzufügen nach Jenkins CI suchen, die App installieren, den Channel #jenkinscicd auswählen und anschließend den generierten Token kopieren. -
Slack in Jenkins konfigurieren
In Jenkins: Manage Jenkins → Configure System → Slack-
Workspace:
profilecicd - Credentials: Slack Token als Secret Text in Jenkins speichern
-
Default Channel:
#jenkinscicd - Test Connection: Verbindung testen und Konfiguration speichern
-
Workspace:
Benachrichtigungen über den post-Block
Diese Variante ist besonders empfehlenswert, da der post-Block immer ausgeführt wird –
unabhängig davon, ob der Pipeline-Status SUCCESS, FAILURE oder ABORTED ist.
Der post-Abschnitt wird am Ende der Pipeline, nach allen Stages, definiert.
post {
always {
echo 'Slack Notification wird gesendet'
slackSend(
channel: '#jenkinscicd',
color: COLOR_MAP[currentBuild.currentResult],
message: "*${currentBuild.currentResult}:* Job ${env.JOB_NAME} \
Build ${env.BUILD_NUMBER}\nWeitere Details: ${env.BUILD_URL}"
)
}
}
Die Funktion slackSend() stammt aus dem Jenkins
Slack Notification Plugin und wird verwendet, um Nachrichten
aus der Pipeline direkt an einen Slack-Channel zu senden.
-
slackSend(
Startet den Versand einer Slack-Nachricht aus der Jenkins-Pipeline. -
channel: '#jenkinscicd'
Definiert den Slack-Channel, in den die Nachricht gesendet wird. In diesem Projekt wird der Channel #jenkinscicd verwendet, der speziell für CI/CD-Benachrichtigungen vorgesehen ist. -
color: COLOR_MAP[currentBuild.currentResult]
Setzt die Farbe der Slack-Nachricht abhängig vom Build-Ergebnis:- SUCCESS → Grün
- FAILURE → Rot
- UNSTABLE / ABORTED → Gelb
-
message:
Definiert den eigentlichen Text der Slack-Nachricht. -
*${currentBuild.currentResult}:*
Zeigt das finale Ergebnis der Pipeline an (z.B. SUCCESS oder FAILURE). Die Sterne sorgen für eine fettgedruckte Darstellung in Slack. -
Job ${env.JOB_NAME}
Gibt den Namen des Jenkins-Jobs aus, der die Pipeline ausgeführt hat. -
Build ${env.BUILD_NUMBER}
Zeigt die eindeutige Build-Nummer an, sodass der Durchlauf eindeutig identifiziert werden kann. -
${env.BUILD_URL}
Fügt einen direkten Link zum Jenkins-Build hinzu. Über diesen Link kann sofort auf Logs, Stages und Artefakte zugegriffen werden.
Ergebnis: Der komplette CI-Prozess ist automatisiert – von GitHub Commit bis Artefakt-Upload inklusive Team-Notification.
4- Fazit
In diesem Projekt wurde erfolgreich eine vollständige Continuous-Integration-Pipeline für die Web-Profile-Anwendung umgesetzt. Die gesamte CI-Architektur basiert auf AWS EC2 und nutzt Jenkins als zentrale Orchestrierungsplattform.
Durch die Integration von GitHub, Nexus Repository und SonarQube wurde ein automatisierter Build-, Analyse- und Artefakt-Management-Prozess realisiert. Jeder Code-Push triggert automatisch die Pipeline, führt Builds, Tests, statische Code-Analyse sowie Quality Gates aus und veröffentlicht geprüfte Artefakte versioniert in Nexus.
Die Verwendung von Quality Gates stellt sicher, dass nur qualitativ geprüfter Code weiterverarbeitet wird, während die Slack-Notifications dem Team unmittelbares Feedback über den Pipeline-Status liefern. Dadurch wird Transparenz, Reaktionsgeschwindigkeit und Code-Qualität deutlich verbessert.
Insgesamt zeigt dieses Projekt eine praxisnahe, skalierbare und erweiterbare CI-Lösung, die den Grundstein für eine zukünftige Continuous-Delivery- oder Continuous-Deployment-Strategie legt und moderne DevOps-Best-Practices erfolgreich umsetzt.