1
+ import groovy.transform.Field
2
+
3
+ @Field
4
+ def shOutput = " "
5
+ def buildxPushTags = " "
6
+
1
7
pipeline {
2
8
agent {
3
9
label ' docker-multiarch'
@@ -8,14 +14,12 @@ pipeline {
8
14
ansiColor(' xterm' )
9
15
}
10
16
environment {
11
- IMAGE = " nginx-proxy-manager"
17
+ IMAGE = ' nginx-proxy-manager'
12
18
BUILD_VERSION = getVersion()
13
- MAJOR_VERSION = " 2"
14
- BRANCH_LOWER = " ${ BRANCH_NAME.toLowerCase().replaceAll('/', '-')} "
15
- COMPOSE_PROJECT_NAME = " npm_${ BRANCH_LOWER} _${ BUILD_NUMBER} "
16
- COMPOSE_FILE = ' docker/docker-compose.ci.yml'
19
+ MAJOR_VERSION = ' 2'
20
+ BRANCH_LOWER = " ${ BRANCH_NAME.toLowerCase().replaceAll('\\\\', '-').replaceAll('/', '-').replaceAll('\\.', '-')} "
21
+ BUILDX_NAME = " npm_${ BRANCH_LOWER} _${ BUILD_NUMBER} "
17
22
COMPOSE_INTERACTIVE_NO_CLI = 1
18
- BUILDX_NAME = " ${ COMPOSE_PROJECT_NAME} "
19
23
}
20
24
stages {
21
25
stage(' Environment' ) {
@@ -26,7 +30,7 @@ pipeline {
26
30
}
27
31
steps {
28
32
script {
29
- env . BUILDX_PUSH_TAGS = " -t docker.io/jc21/${ IMAGE} :${ BUILD_VERSION} -t docker.io/jc21/${ IMAGE} :${ MAJOR_VERSION} -t docker.io/jc21/${ IMAGE} :latest"
33
+ buildxPushTags = " -t docker.io/jc21/${ IMAGE} :${ BUILD_VERSION} -t docker.io/jc21/${ IMAGE} :${ MAJOR_VERSION} -t docker.io/jc21/${ IMAGE} :latest"
30
34
}
31
35
}
32
36
}
@@ -39,7 +43,7 @@ pipeline {
39
43
steps {
40
44
script {
41
45
// Defaults to the Branch name, which is applies to all branches AND pr's
42
- env . BUILDX_PUSH_TAGS = " -t docker.io/jc21/${ IMAGE} :github-${ BRANCH_LOWER} "
46
+ buildxPushTags = " -t docker.io/jc21/${ IMAGE} :github-${ BRANCH_LOWER} "
43
47
}
44
48
}
45
49
}
@@ -54,105 +58,96 @@ pipeline {
54
58
}
55
59
}
56
60
}
57
- stage(' Frontend' ) {
58
- steps {
59
- sh ' ./scripts/frontend-build'
60
- }
61
- }
62
- stage(' Backend' ) {
63
- steps {
64
- echo ' Checking Syntax ...'
65
- // See: https://github.com/yarnpkg/yarn/issues/3254
66
- sh ''' docker run --rm \\
67
- -v "$(pwd)/backend:/app" \\
68
- -v "$(pwd)/global:/app/global" \\
69
- -w /app \\
70
- node:latest \\
71
- sh -c "yarn install && yarn eslint . && rm -rf node_modules"
72
- '''
73
-
74
- echo ' Docker Build ...'
75
- sh ''' docker build --pull --no-cache --squash --compress \\
76
- -t "${IMAGE}:ci-${BUILD_NUMBER}" \\
77
- -f docker/Dockerfile \\
78
- --build-arg TARGETPLATFORM=linux/amd64 \\
79
- --build-arg BUILDPLATFORM=linux/amd64 \\
80
- --build-arg BUILD_VERSION="${BUILD_VERSION}" \\
81
- --build-arg BUILD_COMMIT="${BUILD_COMMIT}" \\
82
- --build-arg BUILD_DATE="$(date '+%Y-%m-%d %T %Z')" \\
83
- .
84
- '''
61
+ stage(' Builds' ) {
62
+ parallel {
63
+ stage(' Project' ) {
64
+ steps {
65
+ script {
66
+ // Frontend and Backend
67
+ def shStatusCode = sh(label : ' Checking and Building' , returnStatus : true , script : '''
68
+ set -e
69
+ ./scripts/ci/frontend-build > ${WORKSPACE}/tmp-sh-build 2>&1
70
+ ./scripts/ci/test-and-build > ${WORKSPACE}/tmp-sh-build 2>&1
71
+ ''' )
72
+ shOutput = readFile " ${ env.WORKSPACE} /tmp-sh-build"
73
+ if (shStatusCode != 0 ) {
74
+ error " ${ shOutput} "
75
+ }
76
+ }
77
+ }
78
+ post {
79
+ always {
80
+ sh ' rm -f ${WORKSPACE}/tmp-sh-build'
81
+ }
82
+ failure {
83
+ npmGithubPrComment(" CI Error:\n\n ```\n ${ shOutput} \n ```" , true )
84
+ }
85
+ }
86
+ }
87
+ stage(' Docs' ) {
88
+ steps {
89
+ dir(path : ' docs' ) {
90
+ sh ' yarn install'
91
+ sh ' yarn build'
92
+ }
93
+ }
94
+ }
85
95
}
86
96
}
87
- stage(' Integration Tests Sqlite' ) {
88
- steps {
89
- // Bring up a stack
90
- sh ' docker-compose up -d fullstack-sqlite'
91
- sh ' ./scripts/wait-healthy $(docker-compose ps -q fullstack-sqlite) 120'
92
-
93
- // Run tests
94
- sh ' rm -rf test/results'
95
- sh ' docker-compose up cypress-sqlite'
96
- // Get results
97
- sh ' docker cp -L "$(docker-compose ps -q cypress-sqlite):/test/results" test/'
97
+ stage(' Test Sqlite' ) {
98
+ environment {
99
+ COMPOSE_PROJECT_NAME = " npm_${ BRANCH_LOWER} _${ BUILD_NUMBER} _sqlite"
100
+ COMPOSE_FILE = ' docker/docker-compose.ci.yml:docker/docker-compose.ci.sqlite.yml'
98
101
}
99
- post {
100
- always {
101
- // Dumps to analyze later
102
- sh ' mkdir -p debug'
103
- sh ' docker-compose logs fullstack-sqlite | gzip > debug/docker_fullstack_sqlite.log.gz'
104
- sh ' docker-compose logs db | gzip > debug/docker_db.log.gz'
105
- // Cypress videos and screenshot artifacts
106
- dir(path : ' test/results' ) {
107
- archiveArtifacts allowEmptyArchive : true , artifacts : ' **/*' , excludes : ' **/*.xml'
108
- }
109
- junit ' test/results/junit/*'
102
+ when {
103
+ not {
104
+ equals expected : ' UNSTABLE' , actual : currentBuild. result
110
105
}
111
106
}
112
- }
113
- stage(' Integration Tests Mysql' ) {
114
107
steps {
115
- // Bring up a stack
116
- sh ' docker-compose up -d fullstack-mysql'
117
- sh ' ./scripts/wait-healthy $(docker-compose ps -q fullstack-mysql) 120'
118
-
119
- // Run tests
120
- sh ' rm -rf test/results'
121
- sh ' docker-compose up cypress-mysql'
122
- // Get results
123
- sh ' docker cp -L "$(docker-compose ps -q cypress-mysql):/test/results" test/'
108
+ sh ' rm -rf ./test/results/junit/*'
109
+ sh ' ./scripts/ci/fulltest-cypress'
124
110
}
125
111
post {
126
112
always {
127
113
// Dumps to analyze later
128
- sh ' mkdir -p debug'
129
- sh ' docker-compose logs fullstack-mysql | gzip > debug/docker_fullstack_mysql.log.gz'
130
- sh ' docker-compose logs db | gzip > debug/docker_db.log.gz'
131
- // Cypress videos and screenshot artifacts
132
- dir(path : ' test/results' ) {
133
- archiveArtifacts allowEmptyArchive : true , artifacts : ' **/*' , excludes : ' **/*.xml'
134
- }
114
+ sh ' mkdir -p debug/sqlite'
115
+ sh ' docker logs $(docker-compose ps --all -q fullstack) > debug/sqlite/docker_fullstack.log 2>&1'
116
+ sh ' docker logs $(docker-compose ps --all -q stepca) > debug/sqlite/docker_stepca.log 2>&1'
117
+ sh ' docker logs $(docker-compose ps --all -q pdns) > debug/sqlite/docker_pdns.log 2>&1'
118
+ sh ' docker logs $(docker-compose ps --all -q pdns-db) > debug/sqlite/docker_pdns-db.log 2>&1'
119
+ sh ' docker logs $(docker-compose ps --all -q dnsrouter) > debug/sqlite/docker_dnsrouter.log 2>&1'
135
120
junit ' test/results/junit/*'
121
+ sh ' docker-compose down --remove-orphans --volumes -t 30 || true'
136
122
}
137
123
}
138
124
}
139
- stage(' Docs' ) {
125
+ stage(' Test Mysql' ) {
126
+ environment {
127
+ COMPOSE_PROJECT_NAME = " npm_${ BRANCH_LOWER} _${ BUILD_NUMBER} _mysql"
128
+ COMPOSE_FILE = ' docker/docker-compose.ci.yml:docker/docker-compose.ci.mysql.yml'
129
+ }
140
130
when {
141
131
not {
142
132
equals expected : ' UNSTABLE' , actual : currentBuild. result
143
133
}
144
134
}
145
135
steps {
146
- dir(path : ' docs' ) {
147
- sh ' yarn install'
148
- sh ' yarn build'
149
- }
150
-
151
- dir(path : ' docs/.vuepress/dist' ) {
152
- sh ' tar -czf ../../docs.tgz *'
136
+ sh ' rm -rf ./test/results/junit/*'
137
+ sh ' ./scripts/ci/fulltest-cypress'
138
+ }
139
+ post {
140
+ always {
141
+ // Dumps to analyze later
142
+ sh ' mkdir -p debug/mysql'
143
+ sh ' docker logs $(docker-compose ps --all -q fullstack) > debug/mysql/docker_fullstack.log 2>&1'
144
+ sh ' docker logs $(docker-compose ps --all -q stepca) > debug/mysql/docker_stepca.log 2>&1'
145
+ sh ' docker logs $(docker-compose ps --all -q pdns) > debug/mysql/docker_pdns.log 2>&1'
146
+ sh ' docker logs $(docker-compose ps --all -q pdns-db) > debug/mysql/docker_pdns-db.log 2>&1'
147
+ sh ' docker logs $(docker-compose ps --all -q dnsrouter) > debug/mysql/docker_dnsrouter.log 2>&1'
148
+ junit ' test/results/junit/*'
149
+ sh ' docker-compose down --remove-orphans --volumes -t 30 || true'
153
150
}
154
-
155
- archiveArtifacts(artifacts : ' docs/docs.tgz' , allowEmptyArchive : false )
156
151
}
157
152
}
158
153
stage(' MultiArch Build' ) {
@@ -163,78 +158,60 @@ pipeline {
163
158
}
164
159
steps {
165
160
withCredentials([usernamePassword(credentialsId : ' jc21-dockerhub' , passwordVariable : ' dpass' , usernameVariable : ' duser' )]) {
166
- // Docker Login
167
- sh " docker login -u '${ duser} ' -p '${ dpass} '"
168
- // Buildx with push from cache
169
- sh " ./scripts/buildx --push ${ BUILDX_PUSH_TAGS} "
161
+ sh ' docker login -u "${duser}" -p "${dpass}"'
162
+ sh " ./scripts/buildx --push ${ buildxPushTags} "
170
163
}
171
164
}
172
165
}
173
- stage(' Docs Deploy' ) {
174
- when {
175
- allOf {
176
- branch ' master'
177
- not {
178
- equals expected : ' UNSTABLE' , actual : currentBuild. result
166
+ stage(' Docs / Comment' ) {
167
+ parallel {
168
+ stage(' Docs Job' ) {
169
+ when {
170
+ allOf {
171
+ branch pattern : " ^(develop|master)\$ " , comparator : " REGEXP"
172
+ not {
173
+ equals expected : ' UNSTABLE' , actual : currentBuild. result
174
+ }
175
+ }
179
176
}
180
- }
181
- }
182
- steps {
183
- withCredentials([[$class : ' AmazonWebServicesCredentialsBinding' , accessKeyVariable : ' AWS_ACCESS_KEY_ID' , credentialsId : ' npm-s3-docs' , secretKeyVariable : ' AWS_SECRET_ACCESS_KEY' ]]) {
184
- sh """ docker run --rm \\
185
- --name \$ {COMPOSE_PROJECT_NAME}-docs-upload \\
186
- -e S3_BUCKET=jc21-npm-site \\
187
- -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \\
188
- -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \\
189
- -v \$ (pwd):/app \\
190
- -w /app \\
191
- jc21/ci-tools \\
192
- scripts/docs-upload /app/docs/.vuepress/dist/
193
- """
194
-
195
- sh """ docker run --rm \\
196
- --name \$ {COMPOSE_PROJECT_NAME}-docs-invalidate \\
197
- -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \\
198
- -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \\
199
- jc21/ci-tools \\
200
- aws cloudfront create-invalidation --distribution-id EN1G6DEWZUTDT --paths '/*'
201
- """
202
- }
203
- }
204
- }
205
- stage(' PR Comment' ) {
206
- when {
207
- allOf {
208
- changeRequest()
209
- not {
210
- equals expected : ' UNSTABLE' , actual : currentBuild. result
177
+ steps {
178
+ build wait : false , job : ' nginx-proxy-manager-docs' , parameters : [string(name : ' docs_branch' , value : " $BRANCH_NAME " )]
211
179
}
212
180
}
213
- }
214
- steps {
215
- script {
216
- def comment = pullRequest. comment(" This is an automated message from CI:\n\n Docker Image for build ${ BUILD_NUMBER} is available on [DockerHub](https://cloud.docker.com/repository/docker/jc21/${ IMAGE} ) as `jc21/${ IMAGE} :github-${ BRANCH_LOWER} `\n\n **Note:** ensure you backup your NPM instance before testing this PR image! Especially if this PR contains database changes." )
181
+ stage(' PR Comment' ) {
182
+ when {
183
+ allOf {
184
+ changeRequest()
185
+ not {
186
+ equals expected : ' UNSTABLE' , actual : currentBuild. result
187
+ }
188
+ }
189
+ }
190
+ steps {
191
+ script {
192
+ npmGithubPrComment(" Docker Image for build ${ BUILD_NUMBER} is available on [DockerHub](https://cloud.docker.com/repository/docker/jc21/${ IMAGE} ) as `jc21/${ IMAGE} :github-${ BRANCH_LOWER} `\n\n **Note:** ensure you backup your NPM instance before testing this PR image! Especially if this PR contains database changes." , true )
193
+ }
194
+ }
217
195
}
218
196
}
219
197
}
220
198
}
221
199
post {
222
200
always {
223
- sh ' docker-compose down --rmi all --remove-orphans --volumes -t 30'
224
201
sh ' echo Reverting ownership'
225
- sh ' docker run --rm -v $(pwd):/data jc21/ci-tools chown -R $(id -u):$(id -g) /data'
202
+ sh ' docker run --rm -v " $(pwd):/data" jc21/ci-tools chown -R " $(id -u):$(id -g)" /data'
226
203
}
227
204
success {
228
205
juxtapose event : ' success'
229
206
sh ' figlet "SUCCESS"'
230
207
}
231
208
failure {
232
- archiveArtifacts(artifacts : ' debug/**.*' , allowEmptyArchive : true )
209
+ archiveArtifacts(artifacts : ' debug/**/* .*' , allowEmptyArchive : true )
233
210
juxtapose event : ' failure'
234
211
sh ' figlet "FAILURE"'
235
212
}
236
213
unstable {
237
- archiveArtifacts(artifacts : ' debug/**.*' , allowEmptyArchive : true )
214
+ archiveArtifacts(artifacts : ' debug/**/* .*' , allowEmptyArchive : true )
238
215
juxtapose event : ' unstable'
239
216
sh ' figlet "UNSTABLE"'
240
217
}
0 commit comments