-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path.gitlab-ci.yml
392 lines (364 loc) · 11.9 KB
/
.gitlab-ci.yml
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
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
stages:
- prepare
- build:shared
- build
- build:docker
- deploy
- k8:verify
- k8:debug
variables:
# The suffix of the url (suffix.tld):
# feature branches: branch-name.suffix.tld
# staging: staging.suffix.tld
# production: suffix.tld
URL_SUFFIX: vcgc19.dbvis.de
#
# The namespace for kubernetes
K8_NAMESPACE: jentner
#
# Deploy production on tags (yes / no)
# If "no", the production deployment will be done when pushed to staging (e.g., master)
DEPLOY_ON_TAGS: "no"
#
# Build and deploy feature branches (yes / no)
DEPLOY_FB: "yes"
#
# The name of the staging branch
STAGING_BRANCH: master
#
# Helm chart (default lingvis-generic-chart)
HELM_CHART: registry.dbvis.de/lingvis/misc/generic-helm-chart
#
# Helm chart version
HELM_CHART_VERSION: v2.0.0
#
# Dockerfile location (default in root)
DOCKERFILE_LOC: ./deployment/Dockerfile
#
# Docker context (default root)
DOCKER_CONTEXT: ./
#
# Helm image
HELM_IMAGE: alpine/helm:3.2.4
#
# Kubectl image
KUBECTL_IMAGE: bitnami/kubectl:1.17.4
#
#
REPLICA_COUNT_PRODUCTION: 1
#
#
REPLICA_COUNT_STAGING: 1
#
#
REPLICA_COUNT_FB: 1
###########################################
# DEFINE BRANCH TRIGGER RULES
###########################################
#--------------------
# Deployment
#--------------------
.rules: &rules
rules:
# do not run pipelines for merge requests (gets rid of "detatched pipelines")
- if: $CI_MERGE_REQUEST_ID
when: never
# if this is set, run this job all the time
- if: $RUN_ALWAYS == "yes"
when: on_success
# for feature branches
- if: $DEPLOY_FB == "yes" && $RUN_ON_FB == "yes" && $CI_COMMIT_BRANCH != $STAGING_BRANCH && $CI_COMMIT_TAG == null
when: on_success
# if we want tags and it's a staging job
- if: $DEPLOY_ON_TAGS == "yes" && $RUN_ON_MASTER == "yes" && $CI_COMMIT_BRANCH == $STAGING_BRANCH
when: on_success
# if we don't want tags and it's a production job
- if: $DEPLOY_ON_TAGS == "no" && $RUN_ON_TAG == "yes" && $CI_COMMIT_BRANCH == $STAGING_BRANCH
when: on_success
# if we want tags and it is actually a tag
- if: $DEPLOY_ON_TAGS == "yes" && $RUN_ON_TAG == "yes" && $CI_COMMIT_TAG =~ /^v.*/
when: on_success
# default is on_success, so explicitly set job not to run if none of the above rules matched
- when: never
#--------------------
# Environment Cleanup
#--------------------
.rules-cleanup: &rules-cleanup
rules:
# do not run pipelines for merge requests (gets rid of "detatched pipelines")
- if: $CI_MERGE_REQUEST_ID
when: never
# if this is set, run this job all the time
- if: $RUN_ALWAYS == "yes"
when: manual
# run if files changed
# and if it should run on a feature branch or it should run on master
# - changes:
# - Backend/**/*
# - k8/Backend/**/*
# - .gitlab-ci.yml
- if: $RUN_ON_FB == "yes" && $CI_COMMIT_BRANCH != $STAGING_BRANCH && $CI_COMMIT_TAG == null
when: manual
allow_failure: true
# - changes:
# - Backend/**/*
# - k8/Backend/**/*
# - .gitlab-ci.yml
- if: $RUN_ON_MASTER == "yes" && $CI_COMMIT_BRANCH == $STAGING_BRANCH
when: manual
allow_failure: true
# default is on_success, so explicitly set job not to run if none of the above rules matched
- when: never
###########################################
# SETUP ENVIRONMENT VARIALBES
###########################################
export-environment:
image: debian:stretch-slim
stage: prepare
script:
- echo $CI_COMMIT_BRANCH
- echo $STAGING_BRANCH
# set the version either as a tag (v0.0.1) or as a commit sha (74bac331)
- if [[ ${CI_COMMIT_TAG} =~ ^v[0-9].[0-9].[0-9] ]]; then VERSION=${CI_COMMIT_TAG}; else VERSION=${CI_COMMIT_SHORT_SHA}; fi
# the current URL suffix
#- URL_SUFFIX="covis.dbvis.de" # defined in the variables section
# this shortens the slug to 30 characters and removes all trailing dashes
- SHORTENED_CI_COMMIT_REF_SLUG=$(echo ${CI_COMMIT_REF_SLUG} | tr / - | cut -c -30 | sed -E 's#-+$##')
- URL_PREFIX=""
- URL_PROTOCOL="https"
- ENV_TYPE="review"
- REPLICA_COUNT="${REPLICA_COUNT_PRODUCTION}"
- if [ "${DEPLOY_ON_TAGS}" == "yes" ] && [[ "${CI_COMMIT_TAG}" =~ ^v[0-9].[0-9].[0-9] ]]; then ENV_TYPE="production"; fi
- if [ "${DEPLOY_ON_TAGS}" == "yes" ] && [ "${CI_COMMIT_BRANCH}" == "${STAGING_BRANCH}" ]; then ENV_TYPE="staging"; fi
- if [ "${DEPLOY_ON_TAGS}" == "no" ] && [ "${CI_COMMIT_BRANCH}" == "${STAGING_BRANCH}" ]; then ENV_TYPE="production"; fi
- if [ "${ENV_TYPE}" == "staging" ]; then URL_PREFIX="staging."; REPLICA_COUNT="${REPLICA_COUNT_STAGING}"; fi
- if [ "${ENV_TYPE}" == "review" ]; then URL_PREFIX="${SHORTENED_CI_COMMIT_REF_SLUG}."; REPLICA_COUNT="${REPLICA_COUNT_FB}"; fi
# Build the backend url: prefix.api.suffix
- URL_BACKEND="${URL_PREFIX}${URL_SUFFIX}"
# all the stuff into the var.env
- echo "ENV_TYPE=${ENV_TYPE}" >> var.env
- echo "VERSION=${VERSION}" >> var.env
- echo "URL_PROTOCOL=${URL_PROTOCOL}" >> var.env
- echo "URL_BACKEND=${URL_BACKEND}" >> var.env
- echo "REPLICA_COUNT=${REPLICA_COUNT}" >> var.env
# DEBUG
- cat var.env
artifacts:
paths:
- var.env
expire_in: 300 days
tags:
- docker
###########################################
# BUILD
###########################################
build:shared:
image: node:12
stage: build:shared
before_script:
- npm i -g typescript
script:
- cd shared
- tsc -b -v
artifacts:
paths:
- ./shared/dist
tags:
- docker
build:client:
image: node:12
stage: build
script:
- cd ./client-code
- npm ci
- npm run-script build:prod
dependencies:
- export-environment
- build:shared
artifacts:
paths:
- ./server-code/public
tags:
- docker
build:server:
image: node:12
stage: build
script:
- cd ./server-code
- npm ci
- npm run-script build
dependencies:
- export-environment
- build:shared
artifacts:
paths:
- ./server-code/dist
expire_in: 1 week
tags:
- docker
###########################################
# DOCKERIZE
###########################################
dockerize:
stage: build:docker
image: docker:latest
services:
- docker:dind
script:
# needed for VERSION
- source var.env
- echo "$CI_REGISTRY_PASSWORD" | docker login --username "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
# generate imagename using a lowercased foldername == app
- IMG="${CI_REGISTRY_IMAGE}:${VERSION}"
- docker build --build-arg VERSION=${VERSION} -t "$IMG" -f $DOCKERFILE_LOC $DOCKER_CONTEXT
- docker push "$IMG"
tags:
- docker-build
###########################################
# DEPLOY
###########################################
.deploy-script: &deploy-template
stage: deploy
image:
name: $HELM_IMAGE
entrypoint: ["sh", "-c", "apk add bash sed && /bin/bash"]
script:
- echo $KUBECONFIG
- source var.env
# DEBUG
- cat var.env
- URL=${URL_BACKEND}
# DEBUG
- echo ${URL}
# generates the chart name using the environment name, replace all / with -; result: review-backend-100-fancify-pipeline
- RELEASE_NAME=$(echo ${CI_ENVIRONMENT_NAME} | tr / - | tr _ - | tr '[:upper:]' '[:lower:]' | cut -c -53 | sed -E 's#-+$##')
# DEBUG
- echo ${RELEASE_NAME}
# write the url into the var.env file for the dynamic env url generation
- echo "URL=${URL}" >> var.env
# use chart name and the folder by uppercasing the first character of the app name; result: Backend
- export HELM_EXPERIMENTAL_OCI=1
- helm registry login -u ${HELM_CHART_PULL_USER} --password ${HELM_CHART_PULL_PW} ${HELM_CHART}
- helm chart list
- helm chart pull ${HELM_CHART}:${HELM_CHART_VERSION}
- helm chart export ${HELM_CHART}:${HELM_CHART_VERSION}
- helm upgrade --namespace=${K8_NAMESPACE} --dry-run --debug --install -f values.yaml --set app.image.tag="${VERSION}" --set app.ingress.url=${URL} --set app.replicaCount=${REPLICA_COUNT} --set app.image.name=${CI_REGISTRY_IMAGE} ${RELEASE_NAME} ./lingvis-generic
- helm upgrade --namespace=${K8_NAMESPACE} --install -f values.yaml --set app.image.tag="${VERSION}" --set app.ingress.url=${URL} --set app.replicaCount=${REPLICA_COUNT} --set app.image.name=${CI_REGISTRY_IMAGE} ${RELEASE_NAME} ./lingvis-generic
- helm upgrade --namespace=${K8_NAMESPACE} --install --debug -f values-rethinkdb.yaml "${RELEASE_NAME}-rethinkdb" ./lingvis-generic
tags:
- docker
.deploy:
<<: *deploy-template
<<: *rules
variables:
RUN_ON_FB: "no"
RUN_ON_MASTER: "no"
RUN_ON_TAG: "no"
environment:
url: $URL_PROTOCOL://$URL
name: $ENV_TYPE/$CI_PROJECT_NAME/$CI_COMMIT_REF_SLUG
kubernetes:
namespace: $K8_NAMESPACE
artifacts:
reports:
dotenv: var.env
deploy-fb:
extends: .deploy
variables:
ENV_TYPE: review
RUN_ON_FB: "yes"
environment:
on_stop: remove-deployment-fb
deploy-staging:
extends: .deploy
variables:
ENV_TYPE: staging
RUN_ON_MASTER: "yes"
deploy-production:
extends: .deploy
variables:
ENV_TYPE: production
RUN_ON_TAG: "yes"
environment:
name: $ENV_TYPE/$CI_PROJECT_NAME
###########################################
# VERIFY & DEBUG
###########################################
verify successful k8 deployment:
stage: k8:verify
image: alpine:latest
dependencies:
- export-environment
before_script:
- apk add --update curl
script:
- source var.env
# DEBUG
- cat var.env
- URL=${URL_BACKEND}
- curl -v --fail --connect-timeout 10 --max-time 10 --retry 20 --retry-delay 10 --retry-max-time 120 "${URL}"
retry: 2
debug k8 cluster state:
stage: k8:debug
image:
name: $KUBECTL_IMAGE
entrypoint: [""]
environment:
url: $URL_PROTOCOL://$URL
name: $ENV_TYPE/$CI_PROJECT_NAME/$CI_COMMIT_REF_SLUG
kubernetes:
namespace: $K8_NAMESPACE
script:
- source var.env
# generates the chart name using the environment name, replace all / with -; result: review-backend-100-fancify-pipeline
- RELEASE_NAME=$(echo ${CI_ENVIRONMENT_NAME} | tr / - | tr _ - | tr '[:upper:]' '[:lower:]' | cut -c -53 | sed -E 's#-+$##')
# DEBUG
- echo ${RELEASE_NAME}
- "kubectl describe node || :"
- "kubectl -n ${K8_NAMESPACE} describe service \"${RELEASE_NAME}\" || :"
- "kubectl -n ${K8_NAMESPACE} describe ingress \"${RELEASE_NAME}\" || :"
- "kubectl -n ${K8_NAMESPACE} describe deployment \"${RELEASE_NAME}\" || :"
- "kubectl -n ${K8_NAMESPACE} describe replicaset \"${RELEASE_NAME}\" || :"
- "kubectl -n ${K8_NAMESPACE} describe pod \"${RELEASE_NAME}\" || :"
- "kubectl -n ${K8_NAMESPACE} describe pvc \"${RELEASE_NAME}\" || :"
- "kubectl -n ${K8_NAMESPACE} describe pv \"${RELEASE_NAME}\" || :"
- "kubectl logs $(kubectl -n ${K8_NAMESPACE} get pods | awk -v pattern=\"${RELEASE_NAME}\" '$0 ~ pattern {print $1;exit}') || :"
when: always
tags:
- docker
allow_failure: true
###########################################
# CLEANUP NEW ENV
###########################################
.remove-deployment:
stage: deploy
image:
name: $HELM_IMAGE
entrypoint: ["sh", "-c", "apk add bash && /bin/bash"]
variables:
GIT_STRATEGY: none
RUN_ON_FB: "no"
RUN_ON_MASTER: "no"
RUN_ON_TAG: "no"
script:
- echo $KUBECONFIG
- RELEASE_NAME=$(echo "${ENV_TYPE}/$CI_PROJECT_NAME/${CI_COMMIT_REF_SLUG}" | tr / - | cut -c -53 | sed -E 's#-+$##')
# DEBUG
- echo $RELEASE_NAME
- helm delete --namespace=${K8_NAMESPACE} --dry-run --debug ${RELEASE_NAME}
- helm delete --namespace=${K8_NAMESPACE} ${RELEASE_NAME}
- helm delete --namespace=${K8_NAMESPACE} "${RELEASE_NAME}-rethinkdb"
dependencies: []
allow_failure: true
tags:
- docker
remove-deployment-fb:
extends: .remove-deployment
<<: *rules-cleanup
variables:
APP: backend
ENV_TYPE: review
RUN_ON_FB: "yes"
environment:
name: $ENV_TYPE/$CI_PROJECT_NAME/$CI_COMMIT_REF_SLUG
action: stop