-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathJenkinsfile
More file actions
246 lines (227 loc) · 12.3 KB
/
Copy pathJenkinsfile
File metadata and controls
246 lines (227 loc) · 12.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
pipeline {
agent any
options {
buildDiscarder(logRotator(numToKeepStr: '20', artifactNumToKeepStr: '10'))
disableConcurrentBuilds()
skipDefaultCheckout(true)
timestamps()
}
parameters {
choice(name: 'BUILD_RUNTIME', choices: ['auto', 'jenkins-maven', 'docker-maven'], description: 'Use Jenkins Maven when a full JDK 17+ is available, or Docker Maven when Jenkins only has a JRE.')
string(name: 'MAVEN_TOOL', defaultValue: 'maven3.9.16', description: 'Jenkins Maven tool name used by the successful library pipeline.')
string(name: 'MAVEN_DOCKER_IMAGE', defaultValue: 'maven:3.9.9-eclipse-temurin-21', description: 'Maven image used when BUILD_RUNTIME is auto/docker-maven.')
booleanParam(name: 'RUN_SONAR', defaultValue: true, description: 'Run SonarQube analysis and quality gate.')
string(name: 'SONAR_HOST_URL', defaultValue: 'http://52.91.204.64:9000', description: 'SonarQube server URL.')
string(name: 'SONAR_TOKEN_CREDENTIALS_ID', defaultValue: 'sonarqube-token', description: 'Secret text credential for SonarQube.')
booleanParam(name: 'PUBLISH_TO_NEXUS', defaultValue: true, description: 'Publish the WAR artifact to Nexus with Maven deploy.')
string(name: 'NEXUS_CREDENTIALS_ID', defaultValue: 'nexus-credentials', description: 'Username/password credential for Nexus.')
string(name: 'NEXUS_URL', defaultValue: 'http://nexus.example.com:8081/', description: 'Base Nexus URL.')
string(name: 'NEXUS_RELEASES_URL', defaultValue: 'http://nexus.example.com:8081/repository/maven-releases/', description: 'Nexus Maven releases repository URL.')
string(name: 'NEXUS_SNAPSHOTS_URL', defaultValue: 'http://nexus.example.com:8081/repository/maven-snapshots/', description: 'Nexus Maven snapshots repository URL.')
booleanParam(name: 'DEPLOY_TO_TOMCAT', defaultValue: false, description: 'Deploy the generated WAR to Tomcat.')
string(name: 'TOMCAT_URL', defaultValue: 'http://tomcat.example.com:8080', description: 'Base Tomcat URL.')
string(name: 'TOMCAT_CREDENTIALS_ID', defaultValue: 'tomcat-manager', description: 'Username/password credential for Tomcat Manager.')
}
environment {
APP_NAME = 'liontech-resorts'
WAR_FILE = 'target/liontech-resorts.war'
MAVEN_OPTS = '-Dmaven.repo.local=.m2/repository'
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Configure Maven') {
steps {
script {
env.BUILD_RUNTIME = params.BUILD_RUNTIME
env.MAVEN_DOCKER_IMAGE = params.MAVEN_DOCKER_IMAGE
if (params.BUILD_RUNTIME != 'docker-maven') {
try {
def mavenHome = tool name: params.MAVEN_TOOL, type: 'hudson.tasks.Maven$MavenInstallation'
env.MAVEN_HOME = mavenHome
env.M2_HOME = mavenHome
env.PATH = "${mavenHome}/bin:${env.PATH}"
} catch (Exception toolError) {
if (params.BUILD_RUNTIME == 'jenkins-maven') {
error "Jenkins Maven tool '${params.MAVEN_TOOL}' was not found."
}
echo "Jenkins Maven tool '${params.MAVEN_TOOL}' was not found; auto mode can still use Docker Maven."
}
}
}
sh 'sh ./ci/maven-ci.sh --version'
}
}
stage('Unit Tests and Jacoco Coverage') {
steps {
sh 'sh ./ci/maven-ci.sh clean verify'
}
post {
always {
junit allowEmptyResults: true, testResults: 'target/surefire-reports/*.xml'
archiveArtifacts artifacts: 'target/site/jacoco/**/*', allowEmptyArchive: true, fingerprint: true
}
}
}
stage('SonarQube Analysis') {
when {
expression { return params.RUN_SONAR }
}
steps {
script {
def sonarHostUrl = params.SONAR_HOST_URL?.trim()?.replaceAll('/+$', '')
if (!sonarHostUrl) {
error 'Set SONAR_HOST_URL to the real SonarQube URL.'
}
withCredentials([string(credentialsId: "${params.SONAR_TOKEN_CREDENTIALS_ID}", variable: 'SONAR_TOKEN')]) {
withEnv(["SONAR_HOST_URL=${sonarHostUrl}"]) {
sh '''
set -eu
echo "Running SonarQube analysis against $SONAR_HOST_URL"
sh ./ci/maven-ci.sh sonar:sonar \
-Dsonar.host.url="$SONAR_HOST_URL" \
-Dsonar.token="$SONAR_TOKEN"
'''
}
}
}
}
}
stage('SonarQube Quality Gate') {
when {
expression { return params.RUN_SONAR }
}
steps {
script {
def sonarHostUrl = params.SONAR_HOST_URL?.trim()?.replaceAll('/+$', '')
withCredentials([string(credentialsId: "${params.SONAR_TOKEN_CREDENTIALS_ID}", variable: 'SONAR_TOKEN')]) {
withEnv(["SONAR_HOST_URL=${sonarHostUrl}"]) {
timeout(time: 5, unit: 'MINUTES') {
sh '''
set -eu
if ! command -v curl >/dev/null 2>&1; then
echo "ERROR: curl is required on the Jenkins agent for SonarQube quality gate checks."
exit 1
fi
report_file="target/sonar/report-task.txt"
if [ ! -f "$report_file" ]; then
echo "ERROR: SonarQube task report was not found at $report_file."
exit 1
fi
ce_task_url="$(sed -n 's/^ceTaskUrl=//p' "$report_file")"
dashboard_url="$(sed -n 's/^dashboardUrl=//p' "$report_file")"
if [ -z "$ce_task_url" ]; then
echo "ERROR: SonarQube ceTaskUrl was not found in $report_file."
cat "$report_file"
exit 1
fi
echo "SonarQube dashboard: ${dashboard_url:-unknown}"
for attempt in $(seq 1 30); do
response="$(curl --fail --silent --show-error --user "$SONAR_TOKEN:" "$ce_task_url")"
task_status="$(printf '%s' "$response" | grep -o '"status":"[^"]*"' | head -n 1 | cut -d: -f2 | tr -d '"')"
echo "SonarQube background task status: ${task_status:-unknown} (attempt $attempt)"
if [ "$task_status" = "SUCCESS" ]; then
analysis_id="$(printf '%s' "$response" | grep -o '"analysisId":"[^"]*"' | head -n 1 | cut -d: -f2 | tr -d '"')"
if [ -z "$analysis_id" ]; then
echo "ERROR: SonarQube analysisId was not present in CE task response."
echo "$response"
exit 1
fi
quality_response="$(curl --fail --silent --show-error --user "$SONAR_TOKEN:" "$SONAR_HOST_URL/api/qualitygates/project_status?analysisId=$analysis_id")"
gate_status="$(printf '%s' "$quality_response" | grep -o '"status":"[^"]*"' | head -n 1 | cut -d: -f2 | tr -d '"')"
echo "SonarQube quality gate status: ${gate_status:-unknown}"
if [ "$gate_status" = "OK" ]; then
exit 0
fi
echo "$quality_response"
exit 1
fi
if [ "$task_status" = "FAILED" ] || [ "$task_status" = "CANCELED" ]; then
echo "$response"
exit 1
fi
sleep 10
done
echo "ERROR: Timed out waiting for SonarQube quality gate."
exit 1
'''
}
}
}
}
}
}
stage('Package WAR') {
steps {
sh 'sh ./ci/maven-ci.sh -DskipTests package'
archiveArtifacts artifacts: "${env.WAR_FILE}", fingerprint: true
}
}
stage('Publish WAR to Nexus') {
when {
expression { return params.PUBLISH_TO_NEXUS }
}
steps {
withEnv([
"NEXUS_RELEASES_URL=${params.NEXUS_RELEASES_URL}",
"NEXUS_SNAPSHOTS_URL=${params.NEXUS_SNAPSHOTS_URL}",
"NEXUS_URL=${params.NEXUS_URL}"
]) {
withCredentials([usernamePassword(credentialsId: "${params.NEXUS_CREDENTIALS_ID}", usernameVariable: 'NEXUS_USERNAME', passwordVariable: 'NEXUS_PASSWORD')]) {
sh 'sh ./ci/maven-ci.sh -s maven-settings.example.xml -DskipTests deploy'
}
}
}
}
stage('Deploy to Tomcat') {
when {
expression { return params.DEPLOY_TO_TOMCAT }
}
steps {
withCredentials([usernamePassword(credentialsId: "${params.TOMCAT_CREDENTIALS_ID}", usernameVariable: 'TOMCAT_USER', passwordVariable: 'TOMCAT_PASSWORD')]) {
withEnv(["TOMCAT_URL=${params.TOMCAT_URL}"]) {
sh '''
set -eu
TOMCAT_BASE="${TOMCAT_URL%/}"
curl --fail --show-error --silent \
--user "$TOMCAT_USER:$TOMCAT_PASSWORD" \
--upload-file "$WAR_FILE" \
"$TOMCAT_BASE/manager/text/deploy?path=/$APP_NAME&update=true"
for attempt in $(seq 1 30); do
if curl --fail --silent "$TOMCAT_BASE/$APP_NAME/actuator/health" >/tmp/liontech-resorts-health.json; then
cat /tmp/liontech-resorts-health.json
exit 0
fi
sleep 5
done
echo "Tomcat deployment did not become healthy in time."
exit 1
'''
}
}
}
}
}
post {
always {
archiveArtifacts artifacts: 'target/*.war,target/site/jacoco/**/*', allowEmptyArchive: true, fingerprint: true
script {
try {
publishHTML(target: [
allowMissing: true,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'target/site/jacoco',
reportFiles: 'index.html',
reportName: 'Jacoco Coverage'
])
} catch (ignored) {
echo 'HTML Publisher plugin is not installed; Jacoco HTML report was archived instead.'
}
}
}
}
}