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,106 +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
- sh ' docker pull nginxproxymanager/nginx-full:certbot-node'
66
- // See: https://github.com/yarnpkg/yarn/issues/3254
67
- sh ''' docker run --rm \\
68
- -v "$(pwd)/backend:/app" \\
69
- -v "$(pwd)/global:/app/global" \\
70
- -w /app \\
71
- nginxproxymanager/nginx-full:certbot-node \\
72
- sh -c "yarn install && yarn eslint . && rm -rf node_modules"
73
- '''
74
-
75
- echo ' Docker Build ...'
76
- sh ''' docker build --pull --no-cache --squash --compress \\
77
- -t "${IMAGE}:ci-${BUILD_NUMBER}" \\
78
- -f docker/Dockerfile \\
79
- --build-arg TARGETPLATFORM=linux/amd64 \\
80
- --build-arg BUILDPLATFORM=linux/amd64 \\
81
- --build-arg BUILD_VERSION="${BUILD_VERSION}" \\
82
- --build-arg BUILD_COMMIT="${BUILD_COMMIT}" \\
83
- --build-arg BUILD_DATE="$(date '+%Y-%m-%d %T %Z')" \\
84
- .
85
- '''
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
+ }
86
95
}
87
96
}
88
- stage(' Integration Tests Sqlite' ) {
89
- steps {
90
- // Bring up a stack
91
- sh ' docker-compose up -d fullstack-sqlite'
92
- sh ' ./scripts/wait-healthy $(docker-compose ps -q fullstack-sqlite) 120'
93
-
94
- // Run tests
95
- sh ' rm -rf test/results'
96
- sh ' docker-compose up cypress-sqlite'
97
- // Get results
98
- 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'
99
101
}
100
- post {
101
- always {
102
- // Dumps to analyze later
103
- sh ' mkdir -p debug'
104
- sh ' docker-compose logs fullstack-sqlite | gzip > debug/docker_fullstack_sqlite.log.gz'
105
- sh ' docker-compose logs db | gzip > debug/docker_db.log.gz'
106
- // Cypress videos and screenshot artifacts
107
- dir(path : ' test/results' ) {
108
- archiveArtifacts allowEmptyArchive : true , artifacts : ' **/*' , excludes : ' **/*.xml'
109
- }
110
- junit ' test/results/junit/*'
102
+ when {
103
+ not {
104
+ equals expected : ' UNSTABLE' , actual : currentBuild. result
111
105
}
112
106
}
113
- }
114
- stage(' Integration Tests Mysql' ) {
115
107
steps {
116
- // Bring up a stack
117
- sh ' docker-compose up -d fullstack-mysql'
118
- sh ' ./scripts/wait-healthy $(docker-compose ps -q fullstack-mysql) 120'
119
-
120
- // Run tests
121
- sh ' rm -rf test/results'
122
- sh ' docker-compose up cypress-mysql'
123
- // Get results
124
- 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'
125
110
}
126
111
post {
127
112
always {
128
113
// Dumps to analyze later
129
- sh ' mkdir -p debug'
130
- sh ' docker-compose logs fullstack-mysql | gzip > debug/docker_fullstack_mysql.log.gz'
131
- sh ' docker-compose logs db | gzip > debug/docker_db.log.gz'
132
- // Cypress videos and screenshot artifacts
133
- dir(path : ' test/results' ) {
134
- archiveArtifacts allowEmptyArchive : true , artifacts : ' **/*' , excludes : ' **/*.xml'
135
- }
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'
136
120
junit ' test/results/junit/*'
121
+ sh ' docker-compose down --remove-orphans --volumes -t 30 || true'
137
122
}
138
123
}
139
124
}
140
- 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
+ }
141
130
when {
142
131
not {
143
132
equals expected : ' UNSTABLE' , actual : currentBuild. result
144
133
}
145
134
}
146
135
steps {
147
- dir(path : ' docs' ) {
148
- sh ' yarn install'
149
- sh ' yarn build'
150
- }
151
-
152
- dir(path : ' docs/.vuepress/dist' ) {
153
- 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'
154
150
}
155
-
156
- archiveArtifacts(artifacts : ' docs/docs.tgz' , allowEmptyArchive : false )
157
151
}
158
152
}
159
153
stage(' MultiArch Build' ) {
@@ -164,78 +158,60 @@ pipeline {
164
158
}
165
159
steps {
166
160
withCredentials([usernamePassword(credentialsId : ' jc21-dockerhub' , passwordVariable : ' dpass' , usernameVariable : ' duser' )]) {
167
- // Docker Login
168
- sh " docker login -u '${ duser} ' -p '${ dpass} '"
169
- // Buildx with push from cache
170
- sh " ./scripts/buildx --push ${ BUILDX_PUSH_TAGS} "
161
+ sh ' docker login -u "${duser}" -p "${dpass}"'
162
+ sh " ./scripts/buildx --push ${ buildxPushTags} "
171
163
}
172
164
}
173
165
}
174
- stage(' Docs Deploy' ) {
175
- when {
176
- allOf {
177
- branch ' master'
178
- not {
179
- 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
+ }
180
176
}
181
- }
182
- }
183
- steps {
184
- withCredentials([[$class : ' AmazonWebServicesCredentialsBinding' , accessKeyVariable : ' AWS_ACCESS_KEY_ID' , credentialsId : ' npm-s3-docs' , secretKeyVariable : ' AWS_SECRET_ACCESS_KEY' ]]) {
185
- sh """ docker run --rm \\
186
- --name \$ {COMPOSE_PROJECT_NAME}-docs-upload \\
187
- -e S3_BUCKET=jc21-npm-site \\
188
- -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \\
189
- -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \\
190
- -v \$ (pwd):/app \\
191
- -w /app \\
192
- jc21/ci-tools \\
193
- scripts/docs-upload /app/docs/.vuepress/dist/
194
- """
195
-
196
- sh """ docker run --rm \\
197
- --name \$ {COMPOSE_PROJECT_NAME}-docs-invalidate \\
198
- -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \\
199
- -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \\
200
- jc21/ci-tools \\
201
- aws cloudfront create-invalidation --distribution-id EN1G6DEWZUTDT --paths '/*'
202
- """
203
- }
204
- }
205
- }
206
- stage(' PR Comment' ) {
207
- when {
208
- allOf {
209
- changeRequest()
210
- not {
211
- 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 " )]
212
179
}
213
180
}
214
- }
215
- steps {
216
- script {
217
- 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
+ }
218
195
}
219
196
}
220
197
}
221
198
}
222
199
post {
223
200
always {
224
- sh ' docker-compose down --remove-orphans --volumes -t 30'
225
201
sh ' echo Reverting ownership'
226
- 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'
227
203
}
228
204
success {
229
205
juxtapose event : ' success'
230
206
sh ' figlet "SUCCESS"'
231
207
}
232
208
failure {
233
- archiveArtifacts(artifacts : ' debug/**.*' , allowEmptyArchive : true )
209
+ archiveArtifacts(artifacts : ' debug/**/* .*' , allowEmptyArchive : true )
234
210
juxtapose event : ' failure'
235
211
sh ' figlet "FAILURE"'
236
212
}
237
213
unstable {
238
- archiveArtifacts(artifacts : ' debug/**.*' , allowEmptyArchive : true )
214
+ archiveArtifacts(artifacts : ' debug/**/* .*' , allowEmptyArchive : true )
239
215
juxtapose event : ' unstable'
240
216
sh ' figlet "UNSTABLE"'
241
217
}
0 commit comments