@catladder/pipeline 3.5.0 โ†’ 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/build/artifacts/createBuildJobArtifact.js +1 -1
  2. package/dist/build/base/index.d.ts +2 -3
  3. package/dist/build/cache/getAllCacheConfigsFromConfig.js +2 -2
  4. package/dist/build/custom/buildJob.d.ts +2 -2
  5. package/dist/build/custom/index.d.ts +2 -2
  6. package/dist/build/custom/testJob.d.ts +2 -2
  7. package/dist/build/docker.d.ts +4 -4
  8. package/dist/build/index.d.ts +2 -2
  9. package/dist/build/node/buildJob.d.ts +5 -3
  10. package/dist/build/node/index.d.ts +4 -4
  11. package/dist/build/node/meteor.d.ts +2 -2
  12. package/dist/build/node/yarn.d.ts +1 -1
  13. package/dist/build/node/yarn.js +1 -1
  14. package/dist/build/rails/build.d.ts +2 -2
  15. package/dist/build/rails/index.d.ts +2 -2
  16. package/dist/build/sbom.d.ts +2 -2
  17. package/dist/constants.js +1 -1
  18. package/dist/context/createComponentContext.js +11 -4
  19. package/dist/context/getLabels.js +1 -1
  20. package/dist/deploy/cloudRun/createJobs/cloudRunJobs.js +2 -2
  21. package/dist/deploy/cloudRun/createJobs/cloudRunServices.js +28 -10
  22. package/dist/deploy/cloudRun/createJobs/execute/onDeploy.d.ts +2 -3
  23. package/dist/deploy/cloudRun/createJobs/execute/onDeploy.js +4 -9
  24. package/dist/deploy/cloudRun/utils/getJobOrServiceArgs.d.ts +2 -0
  25. package/dist/deploy/cloudRun/utils/getJobOrServiceArgs.js +12 -0
  26. package/dist/deploy/kubernetes/kubeValues.d.ts +2 -2
  27. package/dist/deploy/kubernetes/kubeValues.js +1 -1
  28. package/dist/deploy/sbom.js +1 -1
  29. package/dist/deploy/types/googleCloudRun.d.ts +20 -0
  30. package/dist/pipeline/createJobsForComponent.js +1 -1
  31. package/dist/tsconfig.tsbuildinfo +1 -1
  32. package/dist/types/config.d.ts +1 -1
  33. package/dist/types/context.d.ts +6 -1
  34. package/examples/__snapshots__/cloud-run-llama.test.ts.snap +624 -0
  35. package/examples/__snapshots__/cloud-run-with-gpu.test.ts.snap +1382 -0
  36. package/examples/cloud-run-llama.test.ts +11 -0
  37. package/examples/cloud-run-llama.ts +40 -0
  38. package/examples/cloud-run-with-gpu.test.ts +11 -0
  39. package/examples/cloud-run-with-gpu.ts +30 -0
  40. package/package.json +1 -1
  41. package/src/build/artifacts/createBuildJobArtifact.ts +3 -1
  42. package/src/build/base/index.ts +5 -2
  43. package/src/build/cache/getAllCacheConfigsFromConfig.ts +7 -6
  44. package/src/build/custom/buildJob.ts +2 -2
  45. package/src/build/custom/index.ts +4 -2
  46. package/src/build/custom/testJob.ts +2 -2
  47. package/src/build/docker.ts +8 -4
  48. package/src/build/index.ts +5 -2
  49. package/src/build/node/buildJob.ts +5 -2
  50. package/src/build/node/index.ts +9 -4
  51. package/src/build/node/meteor.ts +5 -2
  52. package/src/build/node/yarn.ts +4 -2
  53. package/src/build/rails/build.ts +3 -7
  54. package/src/build/rails/index.ts +4 -2
  55. package/src/build/sbom.ts +4 -2
  56. package/src/context/createComponentContext.ts +22 -9
  57. package/src/context/getLabels.ts +4 -1
  58. package/src/deploy/cloudRun/createJobs/cloudRunJobs.ts +2 -2
  59. package/src/deploy/cloudRun/createJobs/cloudRunServices.ts +24 -3
  60. package/src/deploy/cloudRun/createJobs/execute/onDeploy.ts +3 -13
  61. package/src/deploy/cloudRun/utils/getJobOrServiceArgs.ts +18 -0
  62. package/src/deploy/kubernetes/kubeValues.ts +13 -4
  63. package/src/deploy/sbom.ts +4 -3
  64. package/src/deploy/types/googleCloudRun.ts +23 -0
  65. package/src/pipeline/createJobsForComponent.ts +10 -2
  66. package/src/types/config.ts +1 -1
  67. package/src/types/context.ts +10 -1
@@ -0,0 +1,1382 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`matches snapshot for cloud-run-with-gpu local pipeline YAML 1`] = `
4
+ "image: path/to/docker/jobs-default:the-version
5
+ stages:
6
+ - setup
7
+ - setup dev
8
+ - setup review
9
+ - setup stage
10
+ - setup prod
11
+ - test
12
+ - test dev
13
+ - test review
14
+ - test stage
15
+ - test prod
16
+ - build
17
+ - build dev
18
+ - build review
19
+ - build stage
20
+ - build prod
21
+ - deploy
22
+ - deploy dev
23
+ - deploy review
24
+ - deploy stage
25
+ - deploy prod
26
+ - verify
27
+ - verify dev
28
+ - verify review
29
+ - verify stage
30
+ - verify prod
31
+ - rollback
32
+ - rollback dev
33
+ - rollback review
34
+ - rollback stage
35
+ - rollback prod
36
+ - stop
37
+ - stop dev
38
+ - stop review
39
+ - stop stage
40
+ - stop prod
41
+ - release
42
+ variables:
43
+ FF_USE_FASTZIP: 'true'
44
+ ARTIFACT_COMPRESSION_LEVEL: fast
45
+ CACHE_COMPRESSION_LEVEL: fast
46
+ TRANSFER_METER_FREQUENCY: 5s
47
+ GIT_DEPTH: '1'
48
+ before_script:
49
+ - |-
50
+ function escapeForDotEnv () {
51
+ input="\${1:-$(cat)}"
52
+ input="\${input//$'\\n'/\\\\n}"
53
+ if [[ "$input" == *\\\\n* ]]; then
54
+ if [[ "$input" == *\\"* && "$input" == *\\'* && "$input" == *\\\`* ]]; then
55
+ printf "\\"%s\\"\\n" "$input"
56
+ elif [[ "$input" == *\\"* && "$input" == *\\'* ]]; then
57
+ printf "\`%s\`\\n" "$input"
58
+ elif [[ "$input" == *\\"* ]]; then
59
+ printf "'%s'\\n" "$input"
60
+ else
61
+ printf "\\"%s\\"\\n" "$input"
62
+ fi
63
+ else
64
+ printf "%s\\n" "$input"
65
+ fi
66
+ }
67
+ - |-
68
+ function collapseable_section_start () {
69
+ local section_title="\${1}"
70
+ local section_description="\${2:-$section_title}"
71
+ echo -e "section_start:\`date +%s\`:\${section_title}[collapsed=true]\\r\\e[0K\${section_description}"
72
+ }
73
+ - |-
74
+ function collapseable_section_end () {
75
+ local section_title="\${1}"
76
+ echo -e "section_end:\`date +%s\`:\${section_title}\\r\\e[0K"
77
+ }
78
+ api ๐Ÿ›ก audit:
79
+ stage: test
80
+ image: path/to/docker/jobs-default:the-version
81
+ variables:
82
+ KUBERNETES_CPU_REQUEST: '0.45'
83
+ KUBERNETES_MEMORY_REQUEST: 1Gi
84
+ KUBERNETES_MEMORY_LIMIT: 4Gi
85
+ script:
86
+ - collapseable_section_start "injectvars" "Injecting variables"
87
+ - export APP_PATH="api"
88
+ - collapseable_section_end "injectvars"
89
+ - cd api
90
+ - yarn npm audit --environment production
91
+ rules:
92
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_MESSAGE !~ /^chore\\(release\\).*/
93
+ - if: $CI_MERGE_REQUEST_ID
94
+ needs: []
95
+ retry: &a1
96
+ max: 2
97
+ when:
98
+ - runner_system_failure
99
+ - stuck_or_timeout_failure
100
+ interruptible: true
101
+ allow_failure: true
102
+ api ๐Ÿ‘ฎ lint:
103
+ stage: test
104
+ image: path/to/docker/jobs-default:the-version
105
+ variables:
106
+ KUBERNETES_CPU_REQUEST: '0.45'
107
+ KUBERNETES_MEMORY_REQUEST: 1Gi
108
+ KUBERNETES_MEMORY_LIMIT: 4Gi
109
+ script:
110
+ - collapseable_section_start "injectvars" "Injecting variables"
111
+ - export APP_PATH="api"
112
+ - collapseable_section_end "injectvars"
113
+ - collapseable_section_start "nodeinstall" "Ensure node version"
114
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
115
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
116
+ - collapseable_section_end "nodeinstall"
117
+ - cd api
118
+ - collapseable_section_start "nodeinstall" "Ensure node version"
119
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
120
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
121
+ - collapseable_section_end "nodeinstall"
122
+ - collapseable_section_start "yarninstall" "Yarn install"
123
+ - yarn install --immutable
124
+ - collapseable_section_end "yarninstall"
125
+ - yarn lint
126
+ cache:
127
+ - key: api-yarn
128
+ policy: pull-push
129
+ paths:
130
+ - api/.yarn
131
+ - key: api-node-modules
132
+ policy: pull-push
133
+ paths:
134
+ - api/node_modules
135
+ rules:
136
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_MESSAGE !~ /^chore\\(release\\).*/
137
+ - if: $CI_MERGE_REQUEST_ID
138
+ needs: []
139
+ retry: *a1
140
+ interruptible: true
141
+ api ๐Ÿงช test:
142
+ stage: test
143
+ image: path/to/docker/jobs-testing-chrome:the-version
144
+ variables:
145
+ KUBERNETES_CPU_REQUEST: '0.45'
146
+ KUBERNETES_MEMORY_REQUEST: 1Gi
147
+ KUBERNETES_MEMORY_LIMIT: 4Gi
148
+ script:
149
+ - collapseable_section_start "injectvars" "Injecting variables"
150
+ - export APP_PATH="api"
151
+ - collapseable_section_end "injectvars"
152
+ - collapseable_section_start "nodeinstall" "Ensure node version"
153
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
154
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
155
+ - collapseable_section_end "nodeinstall"
156
+ - cd api
157
+ - collapseable_section_start "nodeinstall" "Ensure node version"
158
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
159
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
160
+ - collapseable_section_end "nodeinstall"
161
+ - collapseable_section_start "yarninstall" "Yarn install"
162
+ - yarn install --immutable
163
+ - collapseable_section_end "yarninstall"
164
+ - yarn test
165
+ cache:
166
+ - key: api-yarn
167
+ policy: pull-push
168
+ paths:
169
+ - api/.yarn
170
+ - key: api-node-modules
171
+ policy: pull-push
172
+ paths:
173
+ - api/node_modules
174
+ rules:
175
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_MESSAGE !~ /^chore\\(release\\).*/
176
+ - if: $CI_MERGE_REQUEST_ID
177
+ needs: []
178
+ retry: *a1
179
+ interruptible: true
180
+ 'api ๐Ÿ”จ app | dev ':
181
+ stage: build
182
+ image: path/to/docker/jobs-default:the-version
183
+ variables:
184
+ KUBERNETES_CPU_REQUEST: '0.45'
185
+ KUBERNETES_MEMORY_REQUEST: 1Gi
186
+ KUBERNETES_MEMORY_LIMIT: 4Gi
187
+ script:
188
+ - collapseable_section_start "injectvars" "Injecting variables"
189
+ - export ENV_SHORT="dev"
190
+ - export APP_DIR="api"
191
+ - export ENV_TYPE="dev"
192
+ - export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"
193
+ - export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"
194
+ - export BUILD_INFO_CURRENT_VERSION="$(tag=$(git ls-remote origin "refs/tags/v*[0-9]" 2>/dev/null | cut -f 2- | sort -V | tail -1 | sed 's/refs\\/tags\\/v//'); [ -z "$tag" ] && echo "0.0.0" || echo "$tag")"
195
+ - export HOSTNAME="$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
196
+ - export ROOT_URL="https://$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
197
+ - export HOSTNAME_INTERNAL="$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
198
+ - export ROOT_URL_INTERNAL="https://$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
199
+ - export DEPLOY_CLOUD_RUN_PROJECT_ID="google-project-id"
200
+ - export DEPLOY_CLOUD_RUN_REGION="europe-west4"
201
+ - export GCLOUD_DEPLOY_credentialsKey="$CL_dev_api_GCLOUD_DEPLOY_credentialsKey"
202
+ - export GCLOUD_RUN_canonicalHostSuffix="$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix"
203
+ - export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"HOSTNAME\\",\\"ROOT_URL\\",\\"HOSTNAME_INTERNAL\\",\\"ROOT_URL_INTERNAL\\",\\"DEPLOY_CLOUD_RUN_PROJECT_ID\\",\\"DEPLOY_CLOUD_RUN_REGION\\",\\"GCLOUD_DEPLOY_credentialsKey\\",\\"GCLOUD_RUN_canonicalHostSuffix\\"]"
204
+ - collapseable_section_end "injectvars"
205
+ - collapseable_section_start "write-dotenv-api" "write dot env for api"
206
+ - |-
207
+ cat <<EOF > api/.env
208
+ ENV_SHORT=dev
209
+ APP_DIR=api
210
+ ENV_TYPE=dev
211
+ HOSTNAME=$(printf %s "$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
212
+ ROOT_URL=$(printf %s "https://$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
213
+ HOSTNAME_INTERNAL=$(printf %s "$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
214
+ ROOT_URL_INTERNAL=$(printf %s "https://$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
215
+ DEPLOY_CLOUD_RUN_PROJECT_ID=google-project-id
216
+ DEPLOY_CLOUD_RUN_REGION=europe-west4
217
+ GCLOUD_DEPLOY_credentialsKey=$(printf %s "$CL_dev_api_GCLOUD_DEPLOY_credentialsKey" | escapeForDotEnv)
218
+ GCLOUD_RUN_canonicalHostSuffix=$(printf %s "$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | escapeForDotEnv)
219
+ _ALL_ENV_VAR_KEYS=["ENV_SHORT","APP_DIR","ENV_TYPE","BUILD_INFO_BUILD_ID","BUILD_INFO_BUILD_TIME","BUILD_INFO_CURRENT_VERSION","HOSTNAME","ROOT_URL","HOSTNAME_INTERNAL","ROOT_URL_INTERNAL","DEPLOY_CLOUD_RUN_PROJECT_ID","DEPLOY_CLOUD_RUN_REGION","GCLOUD_DEPLOY_credentialsKey","GCLOUD_RUN_canonicalHostSuffix"]
220
+ EOF
221
+ - collapseable_section_end "write-dotenv-api"
222
+ - echo '{"id":"$(git describe --tags 2>/dev/null || git rev-parse HEAD)","time":"$CI_JOB_STARTED_AT"}' > api/__build_info.json
223
+ - collapseable_section_start "nodeinstall" "Ensure node version"
224
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
225
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
226
+ - collapseable_section_end "nodeinstall"
227
+ - cd api
228
+ - collapseable_section_start "nodeinstall" "Ensure node version"
229
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
230
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
231
+ - collapseable_section_end "nodeinstall"
232
+ - collapseable_section_start "yarninstall" "Yarn install"
233
+ - yarn install --immutable
234
+ - collapseable_section_end "yarninstall"
235
+ - yarn build
236
+ cache:
237
+ - key: api-yarn
238
+ policy: pull-push
239
+ paths:
240
+ - api/.yarn
241
+ - key: api-node-modules
242
+ policy: pull-push
243
+ paths:
244
+ - api/node_modules
245
+ artifacts:
246
+ paths:
247
+ - api/__build_info.json
248
+ - api/.next
249
+ - api/dist
250
+ exclude:
251
+ - api/.env
252
+ expire_in: 1 day
253
+ when: always
254
+ reports: {}
255
+ rules:
256
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_MESSAGE !~ /^chore\\(release\\).*/
257
+ needs: []
258
+ retry: *a1
259
+ interruptible: true
260
+ 'api ๐Ÿ”จ docker | dev ':
261
+ stage: build
262
+ image: path/to/docker/docker-build:the-version
263
+ services:
264
+ - name: docker:24.0.6-dind
265
+ command:
266
+ - --tls=false
267
+ - --registry-mirror=https://mirror.gcr.io
268
+ variables:
269
+ DOCKER_HOST: tcp://0.0.0.0:2375
270
+ DOCKER_TLS_CERTDIR: ''
271
+ DOCKER_DRIVER: overlay2
272
+ DOCKER_BUILDKIT: '1'
273
+ KUBERNETES_CPU_REQUEST: '0.45'
274
+ KUBERNETES_MEMORY_REQUEST: 1Gi
275
+ KUBERNETES_MEMORY_LIMIT: 2Gi
276
+ script:
277
+ - collapseable_section_start "injectvars" "Injecting variables"
278
+ - export APP_DIR="api"
279
+ - export DOCKER_BUILD_CONTEXT="."
280
+ - export DOCKER_REGISTRY="europe-west4-docker.pkg.dev"
281
+ - export DOCKER_IMAGE="europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/dev/api"
282
+ - export DOCKER_CACHE_IMAGE="europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api"
283
+ - export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"
284
+ - |-
285
+ export DOCKER_COPY_AND_INSTALL_APP="COPY --chown=node:node $APP_DIR .
286
+ RUN yarn plugin import workspace-tools
287
+ RUN yarn workspaces focus --production && yarn rebuild"
288
+ - |-
289
+ export DOCKER_COPY_WORKSPACE_FILES="COPY --chown=node:node api/package.json /app/api/package.json
290
+ COPY --chown=node:node api/yarn.lock /app/api/yarn.lock
291
+ COPY --chown=node:node .yarnrc.yml /app/.yarnrc.yml
292
+ COPY --chown=node:node .yarn /app/.yarn"
293
+ - collapseable_section_end "injectvars"
294
+ - ensureNodeDockerfile
295
+ - collapseable_section_start "docker-login" "Docker Login"
296
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_dev_api_GCLOUD_DEPLOY_credentialsKey")
297
+ - gcloud auth configure-docker europe-west4-docker.pkg.dev
298
+ - collapseable_section_end "docker-login"
299
+ - collapseable_section_start "docker-build" "Docker build"
300
+ - docker build --network host --cache-from $DOCKER_CACHE_IMAGE --tag $DOCKER_IMAGE:$DOCKER_IMAGE_TAG -f $APP_DIR/Dockerfile $DOCKER_BUILD_CONTEXT --build-arg BUILDKIT_INLINE_CACHE=1
301
+ - collapseable_section_end "docker-build"
302
+ - collapseable_section_start "docker-push" "Docker push and tag"
303
+ - docker push $DOCKER_IMAGE:$DOCKER_IMAGE_TAG
304
+ - docker tag $DOCKER_IMAGE:$DOCKER_IMAGE_TAG $DOCKER_CACHE_IMAGE
305
+ - docker push $DOCKER_CACHE_IMAGE
306
+ - collapseable_section_end "docker-push"
307
+ cache:
308
+ - key: api-yarn
309
+ policy: pull
310
+ paths:
311
+ - api/.yarn
312
+ rules:
313
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_MESSAGE !~ /^chore\\(release\\).*/
314
+ needs:
315
+ - 'api ๐Ÿ”จ app | dev '
316
+ retry: *a1
317
+ interruptible: true
318
+ 'api ๐Ÿงพ sbom | dev ':
319
+ stage: build
320
+ image: aquasec/trivy:0.38.3
321
+ variables: {}
322
+ script:
323
+ - collapseable_section_start "injectvars" "Injecting variables"
324
+ - collapseable_section_end "injectvars"
325
+ - trivy fs --quiet --format cyclonedx --output "__sbom.json" api
326
+ artifacts:
327
+ paths:
328
+ - __sbom.json
329
+ rules:
330
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_MESSAGE !~ /^chore\\(release\\).*/
331
+ needs: []
332
+ retry: *a1
333
+ interruptible: true
334
+ allow_failure: true
335
+ 'api ๐Ÿš€ Deploy | dev ':
336
+ stage: deploy dev
337
+ image: path/to/docker/gcloud:the-version
338
+ variables:
339
+ KUBERNETES_CPU_REQUEST: '0.22'
340
+ KUBERNETES_MEMORY_REQUEST: 200Mi
341
+ KUBERNETES_MEMORY_LIMIT: 400Mi
342
+ script:
343
+ - collapseable_section_start "injectvars" "Injecting variables"
344
+ - export ENV_SHORT="dev"
345
+ - export APP_DIR="api"
346
+ - export ENV_TYPE="dev"
347
+ - export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"
348
+ - export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"
349
+ - export BUILD_INFO_CURRENT_VERSION="$(tag=$(git ls-remote origin "refs/tags/v*[0-9]" 2>/dev/null | cut -f 2- | sort -V | tail -1 | sed 's/refs\\/tags\\/v//'); [ -z "$tag" ] && echo "0.0.0" || echo "$tag")"
350
+ - export HOSTNAME="$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
351
+ - export ROOT_URL="https://$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
352
+ - export HOSTNAME_INTERNAL="$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
353
+ - export ROOT_URL_INTERNAL="https://$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
354
+ - export DEPLOY_CLOUD_RUN_PROJECT_ID="google-project-id"
355
+ - export DEPLOY_CLOUD_RUN_REGION="europe-west4"
356
+ - export GCLOUD_DEPLOY_credentialsKey="$CL_dev_api_GCLOUD_DEPLOY_credentialsKey"
357
+ - export GCLOUD_RUN_canonicalHostSuffix="$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix"
358
+ - export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"HOSTNAME\\",\\"ROOT_URL\\",\\"HOSTNAME_INTERNAL\\",\\"ROOT_URL_INTERNAL\\",\\"DEPLOY_CLOUD_RUN_PROJECT_ID\\",\\"DEPLOY_CLOUD_RUN_REGION\\",\\"GCLOUD_DEPLOY_credentialsKey\\",\\"GCLOUD_RUN_canonicalHostSuffix\\"]"
359
+ - export DOCKER_REGISTRY="europe-west4-docker.pkg.dev"
360
+ - export DOCKER_IMAGE="europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/dev/api"
361
+ - export DOCKER_CACHE_IMAGE="europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api"
362
+ - export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"
363
+ - export CLOUDSDK_CORE_DISABLE_PROMPTS="1"
364
+ - collapseable_section_end "injectvars"
365
+ - collapseable_section_start "prepare" "Prepare..."
366
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_dev_api_GCLOUD_DEPLOY_credentialsKey")
367
+ - export GCLOUD_PROJECT_NUMBER=$(gcloud projects describe google-project-id --format="value(projectNumber)")
368
+ - 'echo "GCLOUD_PROJECT_NUMBER: $GCLOUD_PROJECT_NUMBER"'
369
+ - collapseable_section_end "prepare"
370
+ - collapseable_section_start "writeenvvars" "Write env vars to file"
371
+ - |
372
+ cat > ____envvars.yaml <<EOF
373
+ ENV_SHORT: |-
374
+ dev
375
+ APP_DIR: |-
376
+ api
377
+ ENV_TYPE: |-
378
+ dev
379
+ BUILD_INFO_BUILD_ID: |-
380
+ $(printf %s "$(git describe --tags 2>/dev/null || git rev-parse HEAD)" | sed '1!s/^/ /')
381
+ BUILD_INFO_BUILD_TIME: |-
382
+ $(printf %s "$CI_JOB_STARTED_AT" | sed '1!s/^/ /')
383
+ BUILD_INFO_CURRENT_VERSION: |-
384
+ $(printf %s "$(tag=$(git ls-remote origin "refs/tags/v*[0-9]" 2>/dev/null | cut -f 2- | sort -V | tail -1 | sed 's/refs\\/tags\\/v//'); [ -z "$tag" ] && echo "0.0.0" || echo "$tag")" | sed '1!s/^/ /')
385
+ HOSTNAME: |-
386
+ $(printf %s "$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
387
+ ROOT_URL: |-
388
+ $(printf %s "https://$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
389
+ HOSTNAME_INTERNAL: |-
390
+ $(printf %s "$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
391
+ ROOT_URL_INTERNAL: |-
392
+ $(printf %s "https://$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
393
+ DEPLOY_CLOUD_RUN_PROJECT_ID: |-
394
+ google-project-id
395
+ DEPLOY_CLOUD_RUN_REGION: |-
396
+ europe-west4
397
+ GCLOUD_RUN_canonicalHostSuffix: |-
398
+ $(printf %s "$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | sed '1!s/^/ /')
399
+ _ALL_ENV_VAR_KEYS: |-
400
+ ["ENV_SHORT","APP_DIR","ENV_TYPE","BUILD_INFO_BUILD_ID","BUILD_INFO_BUILD_TIME","BUILD_INFO_CURRENT_VERSION","HOSTNAME","ROOT_URL","HOSTNAME_INTERNAL","ROOT_URL_INTERNAL","DEPLOY_CLOUD_RUN_PROJECT_ID","DEPLOY_CLOUD_RUN_REGION","GCLOUD_DEPLOY_credentialsKey","GCLOUD_RUN_canonicalHostSuffix"]
401
+
402
+ EOF
403
+ - collapseable_section_end "writeenvvars"
404
+ - collapseable_section_start "deploy" "Deploy to cloud run"
405
+ - gcloud beta run deploy pan-test-app-dev-api --command="yarn,start" --image=europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/dev/api:$DOCKER_IMAGE_TAG --project=google-project-id --region=europe-west4 --labels=customer-name=pan,component-name=api,app-name=test-app,env-type=dev,env-name=dev,build-type=node,cloud-run-service-name=pan-test-app-dev-api --env-vars-file=____envvars.yaml --min-instances=0 --max-instances=100 --cpu-throttling --memory=32Gi --allow-unauthenticated --ingress=all --cpu-boost --gpu=1 --gpu-type=nvidia-l4
406
+ - collapseable_section_end "deploy"
407
+ - collapseable_section_start "cleanup" "Cleanup"
408
+ - gcloud run revisions list --project=google-project-id --region=europe-west4 --service=pan-test-app-dev-api --limit=unlimited --sort-by=metadata.creationTimestamp --format="value(name)" --filter='(status.conditions.status=False OR status.conditions.status=Unknown)' | while read -r revisionname; do gcloud run revisions delete --project=google-project-id --region=europe-west4 --quiet $revisionname ; done
409
+ - gcloud artifacts docker images list europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/dev/api --sort-by=~CREATE_TIME --format="value(version)" | tail -n +2 | while read -r version; do gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/dev/api@$version --quiet --delete-tags; done
410
+ - gcloud artifacts docker images list europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api --sort-by=~CREATE_TIME --format="value(version)" | tail -n +2 | while read -r version; do gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api@$version --quiet --delete-tags; done
411
+ - collapseable_section_end "cleanup"
412
+ - echo 'Uploading SBOM to Dependency Track'
413
+ - /dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" upload "pan-test-app/api" "$ROOT_URL" "__sbom.json" vex.json || true
414
+ - echo "CL_GITLAB_ENVIRONMENT_URL=$ROOT_URL" >> gitlab_environment.env
415
+ environment:
416
+ name: dev/api
417
+ url: $CL_GITLAB_ENVIRONMENT_URL
418
+ on_stop: 'api ๐Ÿ›‘ Stop โš ๏ธ | dev '
419
+ auto_stop_in: 4 weeks
420
+ artifacts:
421
+ reports:
422
+ dotenv: gitlab_environment.env
423
+ rules:
424
+ - when: on_success
425
+ if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_MESSAGE !~ /^chore\\(release\\).*/
426
+ needs:
427
+ - job: api ๐Ÿ‘ฎ lint
428
+ artifacts: false
429
+ - job: 'api ๐Ÿ”จ app | dev '
430
+ artifacts: false
431
+ - job: 'api ๐Ÿ”จ docker | dev '
432
+ artifacts: false
433
+ - job: api ๐Ÿงช test
434
+ artifacts: false
435
+ - job: 'api ๐Ÿงพ sbom | dev '
436
+ artifacts: true
437
+ - job: api ๐Ÿ›ก audit
438
+ artifacts: false
439
+ retry: *a1
440
+ interruptible: true
441
+ allow_failure: false
442
+ 'api ๐Ÿ›‘ Stop โš ๏ธ | dev ':
443
+ stage: stop dev
444
+ image: path/to/docker/gcloud:the-version
445
+ variables:
446
+ KUBERNETES_CPU_REQUEST: '0.22'
447
+ KUBERNETES_MEMORY_REQUEST: 200Mi
448
+ KUBERNETES_MEMORY_LIMIT: 400Mi
449
+ GIT_STRATEGY: none
450
+ script:
451
+ - collapseable_section_start "injectvars" "Injecting variables"
452
+ - export CLOUDSDK_CORE_DISABLE_PROMPTS="1"
453
+ - collapseable_section_end "injectvars"
454
+ - set +e
455
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_dev_api_GCLOUD_DEPLOY_credentialsKey")
456
+ - gcloud run services delete pan-test-app-dev-api --project=google-project-id --region=europe-west4
457
+ - gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/dev/api --quiet --delete-tags
458
+ - gcloud artifacts docker images list europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api --sort-by=~CREATE_TIME --format="value(version)" | tail -n +2 | while read -r version; do gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api@$version --quiet --delete-tags; done
459
+ - echo 'Disabling component in Dependency Track'
460
+ - /dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" disable "pan-test-app/api" "$CI_ENVIRONMENT_URL" || true
461
+ - set -e
462
+ environment:
463
+ name: dev/api
464
+ action: stop
465
+ rules:
466
+ - if: $CI_COMMIT_BRANCH =~ /^[0-9]+\\.([0-9]+|x)\\.x$/
467
+ when: on_success
468
+ - when: manual
469
+ if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_MESSAGE !~ /^chore\\(release\\).*/
470
+ needs: []
471
+ retry: *a1
472
+ interruptible: true
473
+ allow_failure: true
474
+ 'api ๐Ÿ”จ app | review ':
475
+ stage: build
476
+ image: path/to/docker/jobs-default:the-version
477
+ variables:
478
+ KUBERNETES_CPU_REQUEST: '0.45'
479
+ KUBERNETES_MEMORY_REQUEST: 1Gi
480
+ KUBERNETES_MEMORY_LIMIT: 4Gi
481
+ script:
482
+ - collapseable_section_start "injectvars" "Injecting variables"
483
+ - export ENV_SHORT="review"
484
+ - export APP_DIR="api"
485
+ - export ENV_TYPE="review"
486
+ - export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"
487
+ - export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"
488
+ - export BUILD_INFO_CURRENT_VERSION="$(tag=$(git ls-remote origin "refs/tags/v*[0-9]" 2>/dev/null | cut -f 2- | sort -V | tail -1 | sed 's/refs\\/tags\\/v//'); [ -z "$tag" ] && echo "0.0.0" || echo "$tag")"
489
+ - export HOSTNAME="$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api-$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
490
+ - export ROOT_URL="https://$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api-$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
491
+ - export HOSTNAME_INTERNAL="$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api-$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
492
+ - export ROOT_URL_INTERNAL="https://$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api-$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
493
+ - export DEPLOY_CLOUD_RUN_PROJECT_ID="google-project-id"
494
+ - export DEPLOY_CLOUD_RUN_REGION="europe-west4"
495
+ - export GCLOUD_DEPLOY_credentialsKey="$CL_review_api_GCLOUD_DEPLOY_credentialsKey"
496
+ - export GCLOUD_RUN_canonicalHostSuffix="$CL_review_api_GCLOUD_RUN_canonicalHostSuffix"
497
+ - export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"HOSTNAME\\",\\"ROOT_URL\\",\\"HOSTNAME_INTERNAL\\",\\"ROOT_URL_INTERNAL\\",\\"DEPLOY_CLOUD_RUN_PROJECT_ID\\",\\"DEPLOY_CLOUD_RUN_REGION\\",\\"GCLOUD_DEPLOY_credentialsKey\\",\\"GCLOUD_RUN_canonicalHostSuffix\\"]"
498
+ - collapseable_section_end "injectvars"
499
+ - collapseable_section_start "write-dotenv-api" "write dot env for api"
500
+ - |-
501
+ cat <<EOF > api/.env
502
+ ENV_SHORT=review
503
+ APP_DIR=api
504
+ ENV_TYPE=review
505
+ HOSTNAME=$(printf %s "$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api-$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
506
+ ROOT_URL=$(printf %s "https://$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api-$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
507
+ HOSTNAME_INTERNAL=$(printf %s "$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api-$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
508
+ ROOT_URL_INTERNAL=$(printf %s "https://$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api-$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
509
+ DEPLOY_CLOUD_RUN_PROJECT_ID=google-project-id
510
+ DEPLOY_CLOUD_RUN_REGION=europe-west4
511
+ GCLOUD_DEPLOY_credentialsKey=$(printf %s "$CL_review_api_GCLOUD_DEPLOY_credentialsKey" | escapeForDotEnv)
512
+ GCLOUD_RUN_canonicalHostSuffix=$(printf %s "$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | escapeForDotEnv)
513
+ _ALL_ENV_VAR_KEYS=["ENV_SHORT","APP_DIR","ENV_TYPE","BUILD_INFO_BUILD_ID","BUILD_INFO_BUILD_TIME","BUILD_INFO_CURRENT_VERSION","HOSTNAME","ROOT_URL","HOSTNAME_INTERNAL","ROOT_URL_INTERNAL","DEPLOY_CLOUD_RUN_PROJECT_ID","DEPLOY_CLOUD_RUN_REGION","GCLOUD_DEPLOY_credentialsKey","GCLOUD_RUN_canonicalHostSuffix"]
514
+ EOF
515
+ - collapseable_section_end "write-dotenv-api"
516
+ - echo '{"id":"$(git describe --tags 2>/dev/null || git rev-parse HEAD)","time":"$CI_JOB_STARTED_AT"}' > api/__build_info.json
517
+ - collapseable_section_start "nodeinstall" "Ensure node version"
518
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
519
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
520
+ - collapseable_section_end "nodeinstall"
521
+ - cd api
522
+ - collapseable_section_start "nodeinstall" "Ensure node version"
523
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
524
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
525
+ - collapseable_section_end "nodeinstall"
526
+ - collapseable_section_start "yarninstall" "Yarn install"
527
+ - yarn install --immutable
528
+ - collapseable_section_end "yarninstall"
529
+ - yarn build
530
+ cache:
531
+ - key: api-yarn
532
+ policy: pull-push
533
+ paths:
534
+ - api/.yarn
535
+ - key: api-node-modules
536
+ policy: pull-push
537
+ paths:
538
+ - api/node_modules
539
+ artifacts:
540
+ paths:
541
+ - api/__build_info.json
542
+ - api/.next
543
+ - api/dist
544
+ exclude:
545
+ - api/.env
546
+ expire_in: 1 day
547
+ when: always
548
+ reports: {}
549
+ rules:
550
+ - if: $CI_MERGE_REQUEST_ID
551
+ needs: []
552
+ retry: *a1
553
+ interruptible: true
554
+ 'api ๐Ÿ”จ docker | review ':
555
+ stage: build
556
+ image: path/to/docker/docker-build:the-version
557
+ services:
558
+ - name: docker:24.0.6-dind
559
+ command:
560
+ - --tls=false
561
+ - --registry-mirror=https://mirror.gcr.io
562
+ variables:
563
+ DOCKER_HOST: tcp://0.0.0.0:2375
564
+ DOCKER_TLS_CERTDIR: ''
565
+ DOCKER_DRIVER: overlay2
566
+ DOCKER_BUILDKIT: '1'
567
+ KUBERNETES_CPU_REQUEST: '0.45'
568
+ KUBERNETES_MEMORY_REQUEST: 1Gi
569
+ KUBERNETES_MEMORY_LIMIT: 2Gi
570
+ script:
571
+ - collapseable_section_start "injectvars" "Injecting variables"
572
+ - export APP_DIR="api"
573
+ - export DOCKER_BUILD_CONTEXT="."
574
+ - export DOCKER_REGISTRY="europe-west4-docker.pkg.dev"
575
+ - export DOCKER_IMAGE="europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/review/api/$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })"
576
+ - export DOCKER_CACHE_IMAGE="europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api"
577
+ - export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"
578
+ - |-
579
+ export DOCKER_COPY_AND_INSTALL_APP="COPY --chown=node:node $APP_DIR .
580
+ RUN yarn plugin import workspace-tools
581
+ RUN yarn workspaces focus --production && yarn rebuild"
582
+ - |-
583
+ export DOCKER_COPY_WORKSPACE_FILES="COPY --chown=node:node api/package.json /app/api/package.json
584
+ COPY --chown=node:node api/yarn.lock /app/api/yarn.lock
585
+ COPY --chown=node:node .yarnrc.yml /app/.yarnrc.yml
586
+ COPY --chown=node:node .yarn /app/.yarn"
587
+ - collapseable_section_end "injectvars"
588
+ - ensureNodeDockerfile
589
+ - collapseable_section_start "docker-login" "Docker Login"
590
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_review_api_GCLOUD_DEPLOY_credentialsKey")
591
+ - gcloud auth configure-docker europe-west4-docker.pkg.dev
592
+ - collapseable_section_end "docker-login"
593
+ - collapseable_section_start "docker-build" "Docker build"
594
+ - docker build --network host --cache-from $DOCKER_CACHE_IMAGE --tag $DOCKER_IMAGE:$DOCKER_IMAGE_TAG -f $APP_DIR/Dockerfile $DOCKER_BUILD_CONTEXT --build-arg BUILDKIT_INLINE_CACHE=1
595
+ - collapseable_section_end "docker-build"
596
+ - collapseable_section_start "docker-push" "Docker push and tag"
597
+ - docker push $DOCKER_IMAGE:$DOCKER_IMAGE_TAG
598
+ - docker tag $DOCKER_IMAGE:$DOCKER_IMAGE_TAG $DOCKER_CACHE_IMAGE
599
+ - docker push $DOCKER_CACHE_IMAGE
600
+ - collapseable_section_end "docker-push"
601
+ cache:
602
+ - key: api-yarn
603
+ policy: pull
604
+ paths:
605
+ - api/.yarn
606
+ rules:
607
+ - if: $CI_MERGE_REQUEST_ID
608
+ needs:
609
+ - 'api ๐Ÿ”จ app | review '
610
+ retry: *a1
611
+ interruptible: true
612
+ 'api ๐Ÿงพ sbom | review ':
613
+ stage: build
614
+ image: aquasec/trivy:0.38.3
615
+ variables: {}
616
+ script:
617
+ - collapseable_section_start "injectvars" "Injecting variables"
618
+ - collapseable_section_end "injectvars"
619
+ - trivy fs --quiet --format cyclonedx --output "__sbom.json" api
620
+ artifacts:
621
+ paths:
622
+ - __sbom.json
623
+ rules:
624
+ - if: $CI_MERGE_REQUEST_ID
625
+ needs: []
626
+ retry: *a1
627
+ interruptible: true
628
+ allow_failure: true
629
+ 'api ๐Ÿš€ Deploy | review ':
630
+ stage: deploy review
631
+ image: path/to/docker/gcloud:the-version
632
+ variables:
633
+ KUBERNETES_CPU_REQUEST: '0.22'
634
+ KUBERNETES_MEMORY_REQUEST: 200Mi
635
+ KUBERNETES_MEMORY_LIMIT: 400Mi
636
+ script:
637
+ - collapseable_section_start "injectvars" "Injecting variables"
638
+ - export ENV_SHORT="review"
639
+ - export APP_DIR="api"
640
+ - export ENV_TYPE="review"
641
+ - export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"
642
+ - export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"
643
+ - export BUILD_INFO_CURRENT_VERSION="$(tag=$(git ls-remote origin "refs/tags/v*[0-9]" 2>/dev/null | cut -f 2- | sort -V | tail -1 | sed 's/refs\\/tags\\/v//'); [ -z "$tag" ] && echo "0.0.0" || echo "$tag")"
644
+ - export HOSTNAME="$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api-$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
645
+ - export ROOT_URL="https://$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api-$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
646
+ - export HOSTNAME_INTERNAL="$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api-$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
647
+ - export ROOT_URL_INTERNAL="https://$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api-$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
648
+ - export DEPLOY_CLOUD_RUN_PROJECT_ID="google-project-id"
649
+ - export DEPLOY_CLOUD_RUN_REGION="europe-west4"
650
+ - export GCLOUD_DEPLOY_credentialsKey="$CL_review_api_GCLOUD_DEPLOY_credentialsKey"
651
+ - export GCLOUD_RUN_canonicalHostSuffix="$CL_review_api_GCLOUD_RUN_canonicalHostSuffix"
652
+ - export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"HOSTNAME\\",\\"ROOT_URL\\",\\"HOSTNAME_INTERNAL\\",\\"ROOT_URL_INTERNAL\\",\\"DEPLOY_CLOUD_RUN_PROJECT_ID\\",\\"DEPLOY_CLOUD_RUN_REGION\\",\\"GCLOUD_DEPLOY_credentialsKey\\",\\"GCLOUD_RUN_canonicalHostSuffix\\"]"
653
+ - export DOCKER_REGISTRY="europe-west4-docker.pkg.dev"
654
+ - export DOCKER_IMAGE="europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/review/api/$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })"
655
+ - export DOCKER_CACHE_IMAGE="europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api"
656
+ - export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"
657
+ - export CLOUDSDK_CORE_DISABLE_PROMPTS="1"
658
+ - collapseable_section_end "injectvars"
659
+ - collapseable_section_start "prepare" "Prepare..."
660
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_review_api_GCLOUD_DEPLOY_credentialsKey")
661
+ - export GCLOUD_PROJECT_NUMBER=$(gcloud projects describe google-project-id --format="value(projectNumber)")
662
+ - 'echo "GCLOUD_PROJECT_NUMBER: $GCLOUD_PROJECT_NUMBER"'
663
+ - collapseable_section_end "prepare"
664
+ - collapseable_section_start "writeenvvars" "Write env vars to file"
665
+ - |
666
+ cat > ____envvars.yaml <<EOF
667
+ ENV_SHORT: |-
668
+ review
669
+ APP_DIR: |-
670
+ api
671
+ ENV_TYPE: |-
672
+ review
673
+ BUILD_INFO_BUILD_ID: |-
674
+ $(printf %s "$(git describe --tags 2>/dev/null || git rev-parse HEAD)" | sed '1!s/^/ /')
675
+ BUILD_INFO_BUILD_TIME: |-
676
+ $(printf %s "$CI_JOB_STARTED_AT" | sed '1!s/^/ /')
677
+ BUILD_INFO_CURRENT_VERSION: |-
678
+ $(printf %s "$(tag=$(git ls-remote origin "refs/tags/v*[0-9]" 2>/dev/null | cut -f 2- | sort -V | tail -1 | sed 's/refs\\/tags\\/v//'); [ -z "$tag" ] && echo "0.0.0" || echo "$tag")" | sed '1!s/^/ /')
679
+ HOSTNAME: |-
680
+ $(printf %s "$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api-$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
681
+ ROOT_URL: |-
682
+ $(printf %s "https://$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api-$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
683
+ HOSTNAME_INTERNAL: |-
684
+ $(printf %s "$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api-$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
685
+ ROOT_URL_INTERNAL: |-
686
+ $(printf %s "https://$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api-$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
687
+ DEPLOY_CLOUD_RUN_PROJECT_ID: |-
688
+ google-project-id
689
+ DEPLOY_CLOUD_RUN_REGION: |-
690
+ europe-west4
691
+ GCLOUD_RUN_canonicalHostSuffix: |-
692
+ $(printf %s "$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | sed '1!s/^/ /')
693
+ _ALL_ENV_VAR_KEYS: |-
694
+ ["ENV_SHORT","APP_DIR","ENV_TYPE","BUILD_INFO_BUILD_ID","BUILD_INFO_BUILD_TIME","BUILD_INFO_CURRENT_VERSION","HOSTNAME","ROOT_URL","HOSTNAME_INTERNAL","ROOT_URL_INTERNAL","DEPLOY_CLOUD_RUN_PROJECT_ID","DEPLOY_CLOUD_RUN_REGION","GCLOUD_DEPLOY_credentialsKey","GCLOUD_RUN_canonicalHostSuffix"]
695
+
696
+ EOF
697
+ - collapseable_section_end "writeenvvars"
698
+ - collapseable_section_start "deploy" "Deploy to cloud run"
699
+ - gcloud beta run deploy $(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api" | awk '{print tolower($0)}') --command="yarn,start" --image=europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/review/api/$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }):$DOCKER_IMAGE_TAG --project=google-project-id --region=europe-west4 --labels=customer-name=pan,component-name=api,app-name=test-app,env-type=review,env-name=review,build-type=node,cloud-run-service-name=$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api" | awk '{print tolower($0)}') --env-vars-file=____envvars.yaml --min-instances=0 --max-instances=100 --cpu-throttling --memory=32Gi --allow-unauthenticated --ingress=all --cpu-boost --gpu=1 --gpu-type=nvidia-l4
700
+ - collapseable_section_end "deploy"
701
+ - collapseable_section_start "cleanup" "Cleanup"
702
+ - gcloud run revisions list --project=google-project-id --region=europe-west4 --service=$(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api" | awk '{print tolower($0)}') --limit=unlimited --sort-by=metadata.creationTimestamp --format="value(name)" --filter='(status.conditions.status=False OR status.conditions.status=Unknown)' | while read -r revisionname; do gcloud run revisions delete --project=google-project-id --region=europe-west4 --quiet $revisionname ; done
703
+ - gcloud artifacts docker images list europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/review/api/$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }) --sort-by=~CREATE_TIME --format="value(version)" | tail -n +2 | while read -r version; do gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/review/api/$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })@$version --quiet --delete-tags; done
704
+ - gcloud artifacts docker images list europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api --sort-by=~CREATE_TIME --format="value(version)" | tail -n +2 | while read -r version; do gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api@$version --quiet --delete-tags; done
705
+ - set +e
706
+ - gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/review/api --quiet --delete-tags
707
+ - set -e
708
+ - collapseable_section_end "cleanup"
709
+ - echo 'Uploading SBOM to Dependency Track'
710
+ - /dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" upload "pan-test-app/api" "$ROOT_URL" "__sbom.json" vex.json || true
711
+ - echo "CL_GITLAB_ENVIRONMENT_URL=$ROOT_URL" >> gitlab_environment.env
712
+ environment:
713
+ name: review/$CI_COMMIT_REF_NAME/api
714
+ url: $CL_GITLAB_ENVIRONMENT_URL
715
+ on_stop: 'api ๐Ÿ›‘ Stop โš ๏ธ | review '
716
+ auto_stop_in: 1 week
717
+ artifacts:
718
+ reports:
719
+ dotenv: gitlab_environment.env
720
+ rules:
721
+ - when: on_success
722
+ if: $CI_MERGE_REQUEST_ID
723
+ needs:
724
+ - job: api ๐Ÿ‘ฎ lint
725
+ artifacts: false
726
+ - job: 'api ๐Ÿ”จ app | review '
727
+ artifacts: false
728
+ - job: 'api ๐Ÿ”จ docker | review '
729
+ artifacts: false
730
+ - job: api ๐Ÿงช test
731
+ artifacts: false
732
+ - job: 'api ๐Ÿงพ sbom | review '
733
+ artifacts: true
734
+ - job: api ๐Ÿ›ก audit
735
+ artifacts: false
736
+ retry: *a1
737
+ interruptible: true
738
+ allow_failure: false
739
+ 'api ๐Ÿ›‘ Stop โš ๏ธ | review ':
740
+ stage: stop review
741
+ image: path/to/docker/gcloud:the-version
742
+ variables:
743
+ KUBERNETES_CPU_REQUEST: '0.22'
744
+ KUBERNETES_MEMORY_REQUEST: 200Mi
745
+ KUBERNETES_MEMORY_LIMIT: 400Mi
746
+ GIT_STRATEGY: none
747
+ script:
748
+ - collapseable_section_start "injectvars" "Injecting variables"
749
+ - export CLOUDSDK_CORE_DISABLE_PROMPTS="1"
750
+ - collapseable_section_end "injectvars"
751
+ - set +e
752
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_review_api_GCLOUD_DEPLOY_credentialsKey")
753
+ - gcloud run services delete $(printf %s "pan-test-app-review-$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-api" | awk '{print tolower($0)}') --project=google-project-id --region=europe-west4
754
+ - gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/review/api/$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }) --quiet --delete-tags
755
+ - gcloud artifacts docker images list europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api --sort-by=~CREATE_TIME --format="value(version)" | tail -n +2 | while read -r version; do gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api@$version --quiet --delete-tags; done
756
+ - set +e
757
+ - gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/review/api --quiet --delete-tags
758
+ - set -e
759
+ - echo 'Disabling component in Dependency Track'
760
+ - /dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" disable "pan-test-app/api" "$CI_ENVIRONMENT_URL" || true
761
+ - set -e
762
+ environment:
763
+ name: review/$CI_COMMIT_REF_NAME/api
764
+ action: stop
765
+ rules:
766
+ - if: $CI_COMMIT_BRANCH =~ /^[0-9]+\\.([0-9]+|x)\\.x$/
767
+ when: on_success
768
+ - when: manual
769
+ if: $CI_MERGE_REQUEST_ID
770
+ needs: []
771
+ retry: *a1
772
+ interruptible: true
773
+ allow_failure: true
774
+ 'api ๐Ÿ”จ app | stage ':
775
+ stage: build
776
+ image: path/to/docker/jobs-default:the-version
777
+ variables:
778
+ KUBERNETES_CPU_REQUEST: '0.45'
779
+ KUBERNETES_MEMORY_REQUEST: 1Gi
780
+ KUBERNETES_MEMORY_LIMIT: 4Gi
781
+ script:
782
+ - collapseable_section_start "injectvars" "Injecting variables"
783
+ - export ENV_SHORT="stage"
784
+ - export APP_DIR="api"
785
+ - export ENV_TYPE="stage"
786
+ - export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"
787
+ - export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"
788
+ - export BUILD_INFO_CURRENT_VERSION="$(tag=$(git ls-remote origin "refs/tags/v*[0-9]" 2>/dev/null | cut -f 2- | sort -V | tail -1 | sed 's/refs\\/tags\\/v//'); [ -z "$tag" ] && echo "0.0.0" || echo "$tag")"
789
+ - export HOSTNAME="$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
790
+ - export ROOT_URL="https://$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
791
+ - export HOSTNAME_INTERNAL="$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
792
+ - export ROOT_URL_INTERNAL="https://$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
793
+ - export DEPLOY_CLOUD_RUN_PROJECT_ID="google-project-id"
794
+ - export DEPLOY_CLOUD_RUN_REGION="europe-west4"
795
+ - export GCLOUD_DEPLOY_credentialsKey="$CL_stage_api_GCLOUD_DEPLOY_credentialsKey"
796
+ - export GCLOUD_RUN_canonicalHostSuffix="$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix"
797
+ - export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"HOSTNAME\\",\\"ROOT_URL\\",\\"HOSTNAME_INTERNAL\\",\\"ROOT_URL_INTERNAL\\",\\"DEPLOY_CLOUD_RUN_PROJECT_ID\\",\\"DEPLOY_CLOUD_RUN_REGION\\",\\"GCLOUD_DEPLOY_credentialsKey\\",\\"GCLOUD_RUN_canonicalHostSuffix\\"]"
798
+ - collapseable_section_end "injectvars"
799
+ - collapseable_section_start "write-dotenv-api" "write dot env for api"
800
+ - |-
801
+ cat <<EOF > api/.env
802
+ ENV_SHORT=stage
803
+ APP_DIR=api
804
+ ENV_TYPE=stage
805
+ HOSTNAME=$(printf %s "$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
806
+ ROOT_URL=$(printf %s "https://$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
807
+ HOSTNAME_INTERNAL=$(printf %s "$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
808
+ ROOT_URL_INTERNAL=$(printf %s "https://$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
809
+ DEPLOY_CLOUD_RUN_PROJECT_ID=google-project-id
810
+ DEPLOY_CLOUD_RUN_REGION=europe-west4
811
+ GCLOUD_DEPLOY_credentialsKey=$(printf %s "$CL_stage_api_GCLOUD_DEPLOY_credentialsKey" | escapeForDotEnv)
812
+ GCLOUD_RUN_canonicalHostSuffix=$(printf %s "$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | escapeForDotEnv)
813
+ _ALL_ENV_VAR_KEYS=["ENV_SHORT","APP_DIR","ENV_TYPE","BUILD_INFO_BUILD_ID","BUILD_INFO_BUILD_TIME","BUILD_INFO_CURRENT_VERSION","HOSTNAME","ROOT_URL","HOSTNAME_INTERNAL","ROOT_URL_INTERNAL","DEPLOY_CLOUD_RUN_PROJECT_ID","DEPLOY_CLOUD_RUN_REGION","GCLOUD_DEPLOY_credentialsKey","GCLOUD_RUN_canonicalHostSuffix"]
814
+ EOF
815
+ - collapseable_section_end "write-dotenv-api"
816
+ - echo '{"id":"$(git describe --tags 2>/dev/null || git rev-parse HEAD)","time":"$CI_JOB_STARTED_AT"}' > api/__build_info.json
817
+ - collapseable_section_start "nodeinstall" "Ensure node version"
818
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
819
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
820
+ - collapseable_section_end "nodeinstall"
821
+ - cd api
822
+ - collapseable_section_start "nodeinstall" "Ensure node version"
823
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
824
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
825
+ - collapseable_section_end "nodeinstall"
826
+ - collapseable_section_start "yarninstall" "Yarn install"
827
+ - yarn install --immutable
828
+ - collapseable_section_end "yarninstall"
829
+ - yarn build
830
+ cache:
831
+ - key: api-yarn
832
+ policy: pull-push
833
+ paths:
834
+ - api/.yarn
835
+ - key: api-node-modules
836
+ policy: pull-push
837
+ paths:
838
+ - api/node_modules
839
+ artifacts:
840
+ paths:
841
+ - api/__build_info.json
842
+ - api/.next
843
+ - api/dist
844
+ exclude:
845
+ - api/.env
846
+ expire_in: 1 day
847
+ when: always
848
+ reports: {}
849
+ rules:
850
+ - if: $CI_COMMIT_TAG
851
+ needs: []
852
+ retry: *a1
853
+ interruptible: true
854
+ 'api ๐Ÿ”จ docker | stage ':
855
+ stage: build
856
+ image: path/to/docker/docker-build:the-version
857
+ services:
858
+ - name: docker:24.0.6-dind
859
+ command:
860
+ - --tls=false
861
+ - --registry-mirror=https://mirror.gcr.io
862
+ variables:
863
+ DOCKER_HOST: tcp://0.0.0.0:2375
864
+ DOCKER_TLS_CERTDIR: ''
865
+ DOCKER_DRIVER: overlay2
866
+ DOCKER_BUILDKIT: '1'
867
+ KUBERNETES_CPU_REQUEST: '0.45'
868
+ KUBERNETES_MEMORY_REQUEST: 1Gi
869
+ KUBERNETES_MEMORY_LIMIT: 2Gi
870
+ script:
871
+ - collapseable_section_start "injectvars" "Injecting variables"
872
+ - export APP_DIR="api"
873
+ - export DOCKER_BUILD_CONTEXT="."
874
+ - export DOCKER_REGISTRY="europe-west4-docker.pkg.dev"
875
+ - export DOCKER_IMAGE="europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/stage/api"
876
+ - export DOCKER_CACHE_IMAGE="europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api"
877
+ - export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"
878
+ - |-
879
+ export DOCKER_COPY_AND_INSTALL_APP="COPY --chown=node:node $APP_DIR .
880
+ RUN yarn plugin import workspace-tools
881
+ RUN yarn workspaces focus --production && yarn rebuild"
882
+ - |-
883
+ export DOCKER_COPY_WORKSPACE_FILES="COPY --chown=node:node api/package.json /app/api/package.json
884
+ COPY --chown=node:node api/yarn.lock /app/api/yarn.lock
885
+ COPY --chown=node:node .yarnrc.yml /app/.yarnrc.yml
886
+ COPY --chown=node:node .yarn /app/.yarn"
887
+ - collapseable_section_end "injectvars"
888
+ - ensureNodeDockerfile
889
+ - collapseable_section_start "docker-login" "Docker Login"
890
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_stage_api_GCLOUD_DEPLOY_credentialsKey")
891
+ - gcloud auth configure-docker europe-west4-docker.pkg.dev
892
+ - collapseable_section_end "docker-login"
893
+ - collapseable_section_start "docker-build" "Docker build"
894
+ - docker build --network host --cache-from $DOCKER_CACHE_IMAGE --tag $DOCKER_IMAGE:$DOCKER_IMAGE_TAG -f $APP_DIR/Dockerfile $DOCKER_BUILD_CONTEXT --build-arg BUILDKIT_INLINE_CACHE=1
895
+ - collapseable_section_end "docker-build"
896
+ - collapseable_section_start "docker-push" "Docker push and tag"
897
+ - docker push $DOCKER_IMAGE:$DOCKER_IMAGE_TAG
898
+ - docker tag $DOCKER_IMAGE:$DOCKER_IMAGE_TAG $DOCKER_CACHE_IMAGE
899
+ - docker push $DOCKER_CACHE_IMAGE
900
+ - collapseable_section_end "docker-push"
901
+ cache:
902
+ - key: api-yarn
903
+ policy: pull
904
+ paths:
905
+ - api/.yarn
906
+ rules:
907
+ - if: $CI_COMMIT_TAG
908
+ needs:
909
+ - 'api ๐Ÿ”จ app | stage '
910
+ retry: *a1
911
+ interruptible: true
912
+ 'api ๐Ÿงพ sbom | stage ':
913
+ stage: build
914
+ image: aquasec/trivy:0.38.3
915
+ variables: {}
916
+ script:
917
+ - collapseable_section_start "injectvars" "Injecting variables"
918
+ - collapseable_section_end "injectvars"
919
+ - trivy fs --quiet --format cyclonedx --output "__sbom.json" api
920
+ artifacts:
921
+ paths:
922
+ - __sbom.json
923
+ rules:
924
+ - if: $CI_COMMIT_TAG
925
+ needs: []
926
+ retry: *a1
927
+ interruptible: true
928
+ allow_failure: true
929
+ 'api ๐Ÿš€ Deploy | stage ':
930
+ stage: deploy stage
931
+ image: path/to/docker/gcloud:the-version
932
+ variables:
933
+ KUBERNETES_CPU_REQUEST: '0.22'
934
+ KUBERNETES_MEMORY_REQUEST: 200Mi
935
+ KUBERNETES_MEMORY_LIMIT: 400Mi
936
+ script:
937
+ - collapseable_section_start "injectvars" "Injecting variables"
938
+ - export ENV_SHORT="stage"
939
+ - export APP_DIR="api"
940
+ - export ENV_TYPE="stage"
941
+ - export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"
942
+ - export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"
943
+ - export BUILD_INFO_CURRENT_VERSION="$(tag=$(git ls-remote origin "refs/tags/v*[0-9]" 2>/dev/null | cut -f 2- | sort -V | tail -1 | sed 's/refs\\/tags\\/v//'); [ -z "$tag" ] && echo "0.0.0" || echo "$tag")"
944
+ - export HOSTNAME="$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
945
+ - export ROOT_URL="https://$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
946
+ - export HOSTNAME_INTERNAL="$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
947
+ - export ROOT_URL_INTERNAL="https://$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
948
+ - export DEPLOY_CLOUD_RUN_PROJECT_ID="google-project-id"
949
+ - export DEPLOY_CLOUD_RUN_REGION="europe-west4"
950
+ - export GCLOUD_DEPLOY_credentialsKey="$CL_stage_api_GCLOUD_DEPLOY_credentialsKey"
951
+ - export GCLOUD_RUN_canonicalHostSuffix="$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix"
952
+ - export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"HOSTNAME\\",\\"ROOT_URL\\",\\"HOSTNAME_INTERNAL\\",\\"ROOT_URL_INTERNAL\\",\\"DEPLOY_CLOUD_RUN_PROJECT_ID\\",\\"DEPLOY_CLOUD_RUN_REGION\\",\\"GCLOUD_DEPLOY_credentialsKey\\",\\"GCLOUD_RUN_canonicalHostSuffix\\"]"
953
+ - export DOCKER_REGISTRY="europe-west4-docker.pkg.dev"
954
+ - export DOCKER_IMAGE="europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/stage/api"
955
+ - export DOCKER_CACHE_IMAGE="europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api"
956
+ - export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"
957
+ - export CLOUDSDK_CORE_DISABLE_PROMPTS="1"
958
+ - collapseable_section_end "injectvars"
959
+ - collapseable_section_start "prepare" "Prepare..."
960
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_stage_api_GCLOUD_DEPLOY_credentialsKey")
961
+ - export GCLOUD_PROJECT_NUMBER=$(gcloud projects describe google-project-id --format="value(projectNumber)")
962
+ - 'echo "GCLOUD_PROJECT_NUMBER: $GCLOUD_PROJECT_NUMBER"'
963
+ - collapseable_section_end "prepare"
964
+ - collapseable_section_start "writeenvvars" "Write env vars to file"
965
+ - |
966
+ cat > ____envvars.yaml <<EOF
967
+ ENV_SHORT: |-
968
+ stage
969
+ APP_DIR: |-
970
+ api
971
+ ENV_TYPE: |-
972
+ stage
973
+ BUILD_INFO_BUILD_ID: |-
974
+ $(printf %s "$(git describe --tags 2>/dev/null || git rev-parse HEAD)" | sed '1!s/^/ /')
975
+ BUILD_INFO_BUILD_TIME: |-
976
+ $(printf %s "$CI_JOB_STARTED_AT" | sed '1!s/^/ /')
977
+ BUILD_INFO_CURRENT_VERSION: |-
978
+ $(printf %s "$(tag=$(git ls-remote origin "refs/tags/v*[0-9]" 2>/dev/null | cut -f 2- | sort -V | tail -1 | sed 's/refs\\/tags\\/v//'); [ -z "$tag" ] && echo "0.0.0" || echo "$tag")" | sed '1!s/^/ /')
979
+ HOSTNAME: |-
980
+ $(printf %s "$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
981
+ ROOT_URL: |-
982
+ $(printf %s "https://$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
983
+ HOSTNAME_INTERNAL: |-
984
+ $(printf %s "$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
985
+ ROOT_URL_INTERNAL: |-
986
+ $(printf %s "https://$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
987
+ DEPLOY_CLOUD_RUN_PROJECT_ID: |-
988
+ google-project-id
989
+ DEPLOY_CLOUD_RUN_REGION: |-
990
+ europe-west4
991
+ GCLOUD_RUN_canonicalHostSuffix: |-
992
+ $(printf %s "$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | sed '1!s/^/ /')
993
+ _ALL_ENV_VAR_KEYS: |-
994
+ ["ENV_SHORT","APP_DIR","ENV_TYPE","BUILD_INFO_BUILD_ID","BUILD_INFO_BUILD_TIME","BUILD_INFO_CURRENT_VERSION","HOSTNAME","ROOT_URL","HOSTNAME_INTERNAL","ROOT_URL_INTERNAL","DEPLOY_CLOUD_RUN_PROJECT_ID","DEPLOY_CLOUD_RUN_REGION","GCLOUD_DEPLOY_credentialsKey","GCLOUD_RUN_canonicalHostSuffix"]
995
+
996
+ EOF
997
+ - collapseable_section_end "writeenvvars"
998
+ - collapseable_section_start "deploy" "Deploy to cloud run"
999
+ - gcloud beta run deploy pan-test-app-stage-api --command="yarn,start" --image=europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/stage/api:$DOCKER_IMAGE_TAG --project=google-project-id --region=europe-west4 --labels=customer-name=pan,component-name=api,app-name=test-app,env-type=stage,env-name=stage,build-type=node,cloud-run-service-name=pan-test-app-stage-api --env-vars-file=____envvars.yaml --min-instances=0 --max-instances=100 --cpu-throttling --memory=32Gi --allow-unauthenticated --ingress=all --cpu-boost --gpu=1 --gpu-type=nvidia-l4
1000
+ - collapseable_section_end "deploy"
1001
+ - collapseable_section_start "cleanup" "Cleanup"
1002
+ - gcloud run revisions list --project=google-project-id --region=europe-west4 --service=pan-test-app-stage-api --limit=unlimited --sort-by=metadata.creationTimestamp --format="value(name)" --filter='(status.conditions.status=False OR status.conditions.status=Unknown)' | while read -r revisionname; do gcloud run revisions delete --project=google-project-id --region=europe-west4 --quiet $revisionname ; done
1003
+ - gcloud artifacts docker images list europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/stage/api --sort-by=~CREATE_TIME --format="value(version)" | tail -n +2 | while read -r version; do gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/stage/api@$version --quiet --delete-tags; done
1004
+ - gcloud artifacts docker images list europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api --sort-by=~CREATE_TIME --format="value(version)" | tail -n +2 | while read -r version; do gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api@$version --quiet --delete-tags; done
1005
+ - collapseable_section_end "cleanup"
1006
+ - echo 'Uploading SBOM to Dependency Track'
1007
+ - /dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" upload "pan-test-app/api" "$ROOT_URL" "__sbom.json" vex.json || true
1008
+ - echo "CL_GITLAB_ENVIRONMENT_URL=$ROOT_URL" >> gitlab_environment.env
1009
+ environment:
1010
+ name: stage/api
1011
+ url: $CL_GITLAB_ENVIRONMENT_URL
1012
+ on_stop: 'api ๐Ÿ›‘ Stop โš ๏ธ | stage '
1013
+ artifacts:
1014
+ reports:
1015
+ dotenv: gitlab_environment.env
1016
+ rules:
1017
+ - when: on_success
1018
+ if: $CI_COMMIT_TAG
1019
+ needs:
1020
+ - job: 'api ๐Ÿ”จ app | stage '
1021
+ artifacts: false
1022
+ - job: 'api ๐Ÿ”จ docker | stage '
1023
+ artifacts: false
1024
+ - job: 'api ๐Ÿงพ sbom | stage '
1025
+ artifacts: true
1026
+ retry: *a1
1027
+ interruptible: true
1028
+ allow_failure: false
1029
+ 'api ๐Ÿ›‘ Stop โš ๏ธ | stage ':
1030
+ stage: stop stage
1031
+ image: path/to/docker/gcloud:the-version
1032
+ variables:
1033
+ KUBERNETES_CPU_REQUEST: '0.22'
1034
+ KUBERNETES_MEMORY_REQUEST: 200Mi
1035
+ KUBERNETES_MEMORY_LIMIT: 400Mi
1036
+ GIT_STRATEGY: none
1037
+ script:
1038
+ - collapseable_section_start "injectvars" "Injecting variables"
1039
+ - export CLOUDSDK_CORE_DISABLE_PROMPTS="1"
1040
+ - collapseable_section_end "injectvars"
1041
+ - set +e
1042
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_stage_api_GCLOUD_DEPLOY_credentialsKey")
1043
+ - gcloud run services delete pan-test-app-stage-api --project=google-project-id --region=europe-west4
1044
+ - gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/stage/api --quiet --delete-tags
1045
+ - gcloud artifacts docker images list europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api --sort-by=~CREATE_TIME --format="value(version)" | tail -n +2 | while read -r version; do gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api@$version --quiet --delete-tags; done
1046
+ - echo 'Disabling component in Dependency Track'
1047
+ - /dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" disable "pan-test-app/api" "$CI_ENVIRONMENT_URL" || true
1048
+ - set -e
1049
+ environment:
1050
+ name: stage/api
1051
+ action: stop
1052
+ rules:
1053
+ - if: $CI_COMMIT_BRANCH =~ /^[0-9]+\\.([0-9]+|x)\\.x$/
1054
+ when: on_success
1055
+ - when: manual
1056
+ if: $CI_COMMIT_TAG
1057
+ needs: []
1058
+ retry: *a1
1059
+ interruptible: true
1060
+ allow_failure: true
1061
+ 'api ๐Ÿ”จ app | prod ':
1062
+ stage: build
1063
+ image: path/to/docker/jobs-default:the-version
1064
+ variables:
1065
+ KUBERNETES_CPU_REQUEST: '0.45'
1066
+ KUBERNETES_MEMORY_REQUEST: 1Gi
1067
+ KUBERNETES_MEMORY_LIMIT: 4Gi
1068
+ script:
1069
+ - collapseable_section_start "injectvars" "Injecting variables"
1070
+ - export ENV_SHORT="prod"
1071
+ - export APP_DIR="api"
1072
+ - export ENV_TYPE="prod"
1073
+ - export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"
1074
+ - export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"
1075
+ - export BUILD_INFO_CURRENT_VERSION="$(tag=$(git ls-remote origin "refs/tags/v*[0-9]" 2>/dev/null | cut -f 2- | sort -V | tail -1 | sed 's/refs\\/tags\\/v//'); [ -z "$tag" ] && echo "0.0.0" || echo "$tag")"
1076
+ - export HOSTNAME="$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1077
+ - export ROOT_URL="https://$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1078
+ - export HOSTNAME_INTERNAL="$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1079
+ - export ROOT_URL_INTERNAL="https://$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1080
+ - export DEPLOY_CLOUD_RUN_PROJECT_ID="google-project-id"
1081
+ - export DEPLOY_CLOUD_RUN_REGION="europe-west4"
1082
+ - export GCLOUD_DEPLOY_credentialsKey="$CL_prod_api_GCLOUD_DEPLOY_credentialsKey"
1083
+ - export GCLOUD_RUN_canonicalHostSuffix="$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix"
1084
+ - export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"HOSTNAME\\",\\"ROOT_URL\\",\\"HOSTNAME_INTERNAL\\",\\"ROOT_URL_INTERNAL\\",\\"DEPLOY_CLOUD_RUN_PROJECT_ID\\",\\"DEPLOY_CLOUD_RUN_REGION\\",\\"GCLOUD_DEPLOY_credentialsKey\\",\\"GCLOUD_RUN_canonicalHostSuffix\\"]"
1085
+ - collapseable_section_end "injectvars"
1086
+ - collapseable_section_start "write-dotenv-api" "write dot env for api"
1087
+ - |-
1088
+ cat <<EOF > api/.env
1089
+ ENV_SHORT=prod
1090
+ APP_DIR=api
1091
+ ENV_TYPE=prod
1092
+ HOSTNAME=$(printf %s "$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
1093
+ ROOT_URL=$(printf %s "https://$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
1094
+ HOSTNAME_INTERNAL=$(printf %s "$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
1095
+ ROOT_URL_INTERNAL=$(printf %s "https://$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
1096
+ DEPLOY_CLOUD_RUN_PROJECT_ID=google-project-id
1097
+ DEPLOY_CLOUD_RUN_REGION=europe-west4
1098
+ GCLOUD_DEPLOY_credentialsKey=$(printf %s "$CL_prod_api_GCLOUD_DEPLOY_credentialsKey" | escapeForDotEnv)
1099
+ GCLOUD_RUN_canonicalHostSuffix=$(printf %s "$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | escapeForDotEnv)
1100
+ _ALL_ENV_VAR_KEYS=["ENV_SHORT","APP_DIR","ENV_TYPE","BUILD_INFO_BUILD_ID","BUILD_INFO_BUILD_TIME","BUILD_INFO_CURRENT_VERSION","HOSTNAME","ROOT_URL","HOSTNAME_INTERNAL","ROOT_URL_INTERNAL","DEPLOY_CLOUD_RUN_PROJECT_ID","DEPLOY_CLOUD_RUN_REGION","GCLOUD_DEPLOY_credentialsKey","GCLOUD_RUN_canonicalHostSuffix"]
1101
+ EOF
1102
+ - collapseable_section_end "write-dotenv-api"
1103
+ - echo '{"id":"$(git describe --tags 2>/dev/null || git rev-parse HEAD)","time":"$CI_JOB_STARTED_AT"}' > api/__build_info.json
1104
+ - collapseable_section_start "nodeinstall" "Ensure node version"
1105
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
1106
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
1107
+ - collapseable_section_end "nodeinstall"
1108
+ - cd api
1109
+ - collapseable_section_start "nodeinstall" "Ensure node version"
1110
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
1111
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
1112
+ - collapseable_section_end "nodeinstall"
1113
+ - collapseable_section_start "yarninstall" "Yarn install"
1114
+ - yarn install --immutable
1115
+ - collapseable_section_end "yarninstall"
1116
+ - yarn build
1117
+ cache:
1118
+ - key: api-yarn
1119
+ policy: pull-push
1120
+ paths:
1121
+ - api/.yarn
1122
+ - key: api-node-modules
1123
+ policy: pull-push
1124
+ paths:
1125
+ - api/node_modules
1126
+ artifacts:
1127
+ paths:
1128
+ - api/__build_info.json
1129
+ - api/.next
1130
+ - api/dist
1131
+ exclude:
1132
+ - api/.env
1133
+ expire_in: 1 day
1134
+ when: always
1135
+ reports: {}
1136
+ rules:
1137
+ - if: $CI_COMMIT_TAG
1138
+ needs: []
1139
+ retry: *a1
1140
+ interruptible: true
1141
+ 'api ๐Ÿ”จ docker | prod ':
1142
+ stage: build
1143
+ image: path/to/docker/docker-build:the-version
1144
+ services:
1145
+ - name: docker:24.0.6-dind
1146
+ command:
1147
+ - --tls=false
1148
+ - --registry-mirror=https://mirror.gcr.io
1149
+ variables:
1150
+ DOCKER_HOST: tcp://0.0.0.0:2375
1151
+ DOCKER_TLS_CERTDIR: ''
1152
+ DOCKER_DRIVER: overlay2
1153
+ DOCKER_BUILDKIT: '1'
1154
+ KUBERNETES_CPU_REQUEST: '0.45'
1155
+ KUBERNETES_MEMORY_REQUEST: 1Gi
1156
+ KUBERNETES_MEMORY_LIMIT: 2Gi
1157
+ script:
1158
+ - collapseable_section_start "injectvars" "Injecting variables"
1159
+ - export APP_DIR="api"
1160
+ - export DOCKER_BUILD_CONTEXT="."
1161
+ - export DOCKER_REGISTRY="europe-west4-docker.pkg.dev"
1162
+ - export DOCKER_IMAGE="europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/prod/api"
1163
+ - export DOCKER_CACHE_IMAGE="europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api"
1164
+ - export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"
1165
+ - |-
1166
+ export DOCKER_COPY_AND_INSTALL_APP="COPY --chown=node:node $APP_DIR .
1167
+ RUN yarn plugin import workspace-tools
1168
+ RUN yarn workspaces focus --production && yarn rebuild"
1169
+ - |-
1170
+ export DOCKER_COPY_WORKSPACE_FILES="COPY --chown=node:node api/package.json /app/api/package.json
1171
+ COPY --chown=node:node api/yarn.lock /app/api/yarn.lock
1172
+ COPY --chown=node:node .yarnrc.yml /app/.yarnrc.yml
1173
+ COPY --chown=node:node .yarn /app/.yarn"
1174
+ - collapseable_section_end "injectvars"
1175
+ - ensureNodeDockerfile
1176
+ - collapseable_section_start "docker-login" "Docker Login"
1177
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_prod_api_GCLOUD_DEPLOY_credentialsKey")
1178
+ - gcloud auth configure-docker europe-west4-docker.pkg.dev
1179
+ - collapseable_section_end "docker-login"
1180
+ - collapseable_section_start "docker-build" "Docker build"
1181
+ - docker build --network host --cache-from $DOCKER_CACHE_IMAGE --tag $DOCKER_IMAGE:$DOCKER_IMAGE_TAG -f $APP_DIR/Dockerfile $DOCKER_BUILD_CONTEXT --build-arg BUILDKIT_INLINE_CACHE=1
1182
+ - collapseable_section_end "docker-build"
1183
+ - collapseable_section_start "docker-push" "Docker push and tag"
1184
+ - docker push $DOCKER_IMAGE:$DOCKER_IMAGE_TAG
1185
+ - docker tag $DOCKER_IMAGE:$DOCKER_IMAGE_TAG $DOCKER_CACHE_IMAGE
1186
+ - docker push $DOCKER_CACHE_IMAGE
1187
+ - collapseable_section_end "docker-push"
1188
+ cache:
1189
+ - key: api-yarn
1190
+ policy: pull
1191
+ paths:
1192
+ - api/.yarn
1193
+ rules:
1194
+ - if: $CI_COMMIT_TAG
1195
+ needs:
1196
+ - 'api ๐Ÿ”จ app | prod '
1197
+ retry: *a1
1198
+ interruptible: true
1199
+ 'api ๐Ÿงพ sbom | prod ':
1200
+ stage: build
1201
+ image: aquasec/trivy:0.38.3
1202
+ variables: {}
1203
+ script:
1204
+ - collapseable_section_start "injectvars" "Injecting variables"
1205
+ - collapseable_section_end "injectvars"
1206
+ - trivy fs --quiet --format cyclonedx --output "__sbom.json" api
1207
+ artifacts:
1208
+ paths:
1209
+ - __sbom.json
1210
+ rules:
1211
+ - if: $CI_COMMIT_TAG
1212
+ needs: []
1213
+ retry: *a1
1214
+ interruptible: true
1215
+ allow_failure: true
1216
+ 'api ๐Ÿš€ Deploy | prod ':
1217
+ stage: deploy prod
1218
+ image: path/to/docker/gcloud:the-version
1219
+ variables:
1220
+ KUBERNETES_CPU_REQUEST: '0.22'
1221
+ KUBERNETES_MEMORY_REQUEST: 200Mi
1222
+ KUBERNETES_MEMORY_LIMIT: 400Mi
1223
+ script:
1224
+ - collapseable_section_start "injectvars" "Injecting variables"
1225
+ - export ENV_SHORT="prod"
1226
+ - export APP_DIR="api"
1227
+ - export ENV_TYPE="prod"
1228
+ - export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"
1229
+ - export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"
1230
+ - export BUILD_INFO_CURRENT_VERSION="$(tag=$(git ls-remote origin "refs/tags/v*[0-9]" 2>/dev/null | cut -f 2- | sort -V | tail -1 | sed 's/refs\\/tags\\/v//'); [ -z "$tag" ] && echo "0.0.0" || echo "$tag")"
1231
+ - export HOSTNAME="$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1232
+ - export ROOT_URL="https://$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1233
+ - export HOSTNAME_INTERNAL="$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1234
+ - export ROOT_URL_INTERNAL="https://$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1235
+ - export DEPLOY_CLOUD_RUN_PROJECT_ID="google-project-id"
1236
+ - export DEPLOY_CLOUD_RUN_REGION="europe-west4"
1237
+ - export GCLOUD_DEPLOY_credentialsKey="$CL_prod_api_GCLOUD_DEPLOY_credentialsKey"
1238
+ - export GCLOUD_RUN_canonicalHostSuffix="$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix"
1239
+ - export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"HOSTNAME\\",\\"ROOT_URL\\",\\"HOSTNAME_INTERNAL\\",\\"ROOT_URL_INTERNAL\\",\\"DEPLOY_CLOUD_RUN_PROJECT_ID\\",\\"DEPLOY_CLOUD_RUN_REGION\\",\\"GCLOUD_DEPLOY_credentialsKey\\",\\"GCLOUD_RUN_canonicalHostSuffix\\"]"
1240
+ - export DOCKER_REGISTRY="europe-west4-docker.pkg.dev"
1241
+ - export DOCKER_IMAGE="europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/prod/api"
1242
+ - export DOCKER_CACHE_IMAGE="europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api"
1243
+ - export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"
1244
+ - export CLOUDSDK_CORE_DISABLE_PROMPTS="1"
1245
+ - collapseable_section_end "injectvars"
1246
+ - collapseable_section_start "prepare" "Prepare..."
1247
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_prod_api_GCLOUD_DEPLOY_credentialsKey")
1248
+ - export GCLOUD_PROJECT_NUMBER=$(gcloud projects describe google-project-id --format="value(projectNumber)")
1249
+ - 'echo "GCLOUD_PROJECT_NUMBER: $GCLOUD_PROJECT_NUMBER"'
1250
+ - collapseable_section_end "prepare"
1251
+ - collapseable_section_start "writeenvvars" "Write env vars to file"
1252
+ - |
1253
+ cat > ____envvars.yaml <<EOF
1254
+ ENV_SHORT: |-
1255
+ prod
1256
+ APP_DIR: |-
1257
+ api
1258
+ ENV_TYPE: |-
1259
+ prod
1260
+ BUILD_INFO_BUILD_ID: |-
1261
+ $(printf %s "$(git describe --tags 2>/dev/null || git rev-parse HEAD)" | sed '1!s/^/ /')
1262
+ BUILD_INFO_BUILD_TIME: |-
1263
+ $(printf %s "$CI_JOB_STARTED_AT" | sed '1!s/^/ /')
1264
+ BUILD_INFO_CURRENT_VERSION: |-
1265
+ $(printf %s "$(tag=$(git ls-remote origin "refs/tags/v*[0-9]" 2>/dev/null | cut -f 2- | sort -V | tail -1 | sed 's/refs\\/tags\\/v//'); [ -z "$tag" ] && echo "0.0.0" || echo "$tag")" | sed '1!s/^/ /')
1266
+ HOSTNAME: |-
1267
+ $(printf %s "$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
1268
+ ROOT_URL: |-
1269
+ $(printf %s "https://$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
1270
+ HOSTNAME_INTERNAL: |-
1271
+ $(printf %s "$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
1272
+ ROOT_URL_INTERNAL: |-
1273
+ $(printf %s "https://$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
1274
+ DEPLOY_CLOUD_RUN_PROJECT_ID: |-
1275
+ google-project-id
1276
+ DEPLOY_CLOUD_RUN_REGION: |-
1277
+ europe-west4
1278
+ GCLOUD_RUN_canonicalHostSuffix: |-
1279
+ $(printf %s "$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | sed '1!s/^/ /')
1280
+ _ALL_ENV_VAR_KEYS: |-
1281
+ ["ENV_SHORT","APP_DIR","ENV_TYPE","BUILD_INFO_BUILD_ID","BUILD_INFO_BUILD_TIME","BUILD_INFO_CURRENT_VERSION","HOSTNAME","ROOT_URL","HOSTNAME_INTERNAL","ROOT_URL_INTERNAL","DEPLOY_CLOUD_RUN_PROJECT_ID","DEPLOY_CLOUD_RUN_REGION","GCLOUD_DEPLOY_credentialsKey","GCLOUD_RUN_canonicalHostSuffix"]
1282
+
1283
+ EOF
1284
+ - collapseable_section_end "writeenvvars"
1285
+ - collapseable_section_start "deploy" "Deploy to cloud run"
1286
+ - gcloud beta run deploy pan-test-app-prod-api --command="yarn,start" --image=europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/prod/api:$DOCKER_IMAGE_TAG --project=google-project-id --region=europe-west4 --labels=customer-name=pan,component-name=api,app-name=test-app,env-type=prod,env-name=prod,build-type=node,cloud-run-service-name=pan-test-app-prod-api --env-vars-file=____envvars.yaml --min-instances=0 --max-instances=100 --cpu-throttling --memory=32Gi --allow-unauthenticated --ingress=all --cpu-boost --gpu=1 --gpu-type=nvidia-l4
1287
+ - collapseable_section_end "deploy"
1288
+ - collapseable_section_start "cleanup" "Cleanup"
1289
+ - gcloud run revisions list --project=google-project-id --region=europe-west4 --service=pan-test-app-prod-api --limit=unlimited --sort-by=metadata.creationTimestamp --format="value(name)" --filter='(status.conditions.status=False OR status.conditions.status=Unknown)' | tail -n +6 | while read -r revisionname; do gcloud run revisions delete --project=google-project-id --region=europe-west4 --quiet $revisionname ; done
1290
+ - gcloud artifacts docker images list europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/prod/api --sort-by=~CREATE_TIME --format="value(version)" | tail -n +7 | while read -r version; do gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/prod/api@$version --quiet --delete-tags; done
1291
+ - gcloud artifacts docker images list europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api --sort-by=~CREATE_TIME --format="value(version)" | tail -n +2 | while read -r version; do gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api@$version --quiet --delete-tags; done
1292
+ - collapseable_section_end "cleanup"
1293
+ - echo 'Uploading SBOM to Dependency Track'
1294
+ - /dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" upload "pan-test-app/api" "$ROOT_URL" "__sbom.json" vex.json || true
1295
+ - echo "CL_GITLAB_ENVIRONMENT_URL=$ROOT_URL" >> gitlab_environment.env
1296
+ environment:
1297
+ name: prod/api
1298
+ url: $CL_GITLAB_ENVIRONMENT_URL
1299
+ on_stop: 'api ๐Ÿ›‘ Stop โš ๏ธ | prod '
1300
+ artifacts:
1301
+ reports:
1302
+ dotenv: gitlab_environment.env
1303
+ rules:
1304
+ - when: manual
1305
+ if: $CI_COMMIT_TAG
1306
+ needs:
1307
+ - job: 'api ๐Ÿ”จ app | prod '
1308
+ artifacts: false
1309
+ - job: 'api ๐Ÿ”จ docker | prod '
1310
+ artifacts: false
1311
+ - job: 'api ๐Ÿงพ sbom | prod '
1312
+ artifacts: true
1313
+ retry: *a1
1314
+ interruptible: true
1315
+ allow_failure: true
1316
+ 'api ๐Ÿ›‘ Stop โš ๏ธ | prod ':
1317
+ stage: stop prod
1318
+ image: path/to/docker/gcloud:the-version
1319
+ variables:
1320
+ KUBERNETES_CPU_REQUEST: '0.22'
1321
+ KUBERNETES_MEMORY_REQUEST: 200Mi
1322
+ KUBERNETES_MEMORY_LIMIT: 400Mi
1323
+ GIT_STRATEGY: none
1324
+ script:
1325
+ - collapseable_section_start "injectvars" "Injecting variables"
1326
+ - export CLOUDSDK_CORE_DISABLE_PROMPTS="1"
1327
+ - collapseable_section_end "injectvars"
1328
+ - set +e
1329
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_prod_api_GCLOUD_DEPLOY_credentialsKey")
1330
+ - gcloud run services delete pan-test-app-prod-api --project=google-project-id --region=europe-west4
1331
+ - gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/prod/api --quiet --delete-tags
1332
+ - gcloud artifacts docker images list europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api --sort-by=~CREATE_TIME --format="value(version)" | tail -n +2 | while read -r version; do gcloud artifacts docker images delete europe-west4-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api@$version --quiet --delete-tags; done
1333
+ - echo 'Disabling component in Dependency Track'
1334
+ - /dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" disable "pan-test-app/api" "$CI_ENVIRONMENT_URL" || true
1335
+ - set -e
1336
+ environment:
1337
+ name: prod/api
1338
+ action: stop
1339
+ rules:
1340
+ - if: $CI_COMMIT_BRANCH =~ /^[0-9]+\\.([0-9]+|x)\\.x$/
1341
+ when: on_success
1342
+ - when: manual
1343
+ if: $CI_COMMIT_TAG
1344
+ needs: []
1345
+ retry: *a1
1346
+ interruptible: true
1347
+ allow_failure: true
1348
+ create release:
1349
+ stage: release
1350
+ image: path/to/docker/semantic-release:the-version
1351
+ script:
1352
+ - semanticRelease
1353
+ - echo '๐Ÿ‘‰ The project access token might be invald - run \`project-renew-token\` in catladder CLI to fix.'
1354
+ rules:
1355
+ - &a2
1356
+ if: $CI_COMMIT_MESSAGE =~ /^chore\\(release\\).*/
1357
+ when: never
1358
+ - &a3
1359
+ if: $CI_PIPELINE_SOURCE == "schedule"
1360
+ when: never
1361
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $AUTO_RELEASE == "true"
1362
+ when: on_success
1363
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
1364
+ when: manual
1365
+ - if: $CI_COMMIT_BRANCH =~ /^[0-9]+.([0-9]+|x).x$/
1366
+ when: manual
1367
+ โš ๏ธ force create release:
1368
+ stage: release
1369
+ image: path/to/docker/semantic-release:the-version
1370
+ script:
1371
+ - semanticRelease
1372
+ - echo '๐Ÿ‘‰ The project access token might be invald - run \`project-renew-token\` in catladder CLI to fix.'
1373
+ rules:
1374
+ - *a2
1375
+ - *a3
1376
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
1377
+ when: manual
1378
+ - if: $CI_COMMIT_BRANCH =~ /^[0-9]+.([0-9]+|x).x$/
1379
+ when: manual
1380
+ needs: []
1381
+ "
1382
+ `;