@catladder/pipeline 2.9.2 โ†’ 2.10.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 (36) hide show
  1. package/dist/constants.js +1 -1
  2. package/dist/deploy/cloudRun/createJobs/cloudRunJobs.d.ts +5 -3
  3. package/dist/deploy/cloudRun/createJobs/cloudRunJobs.js +17 -101
  4. package/dist/deploy/cloudRun/createJobs/execute/onDeploy.d.ts +4 -0
  5. package/dist/deploy/cloudRun/createJobs/execute/onDeploy.js +120 -0
  6. package/dist/deploy/cloudRun/createJobs/execute/schedules.d.ts +3 -0
  7. package/dist/deploy/cloudRun/createJobs/execute/schedules.js +173 -0
  8. package/dist/deploy/cloudRun/createJobs/getCloudRunDeployScripts.js +4 -2
  9. package/dist/deploy/cloudRun/createJobs/getCloudRunStopScripts.js +4 -2
  10. package/dist/deploy/cloudRun/index.js +6 -2
  11. package/dist/deploy/cloudRun/utils/cloudRunExecutionUrl.d.ts +10 -0
  12. package/dist/deploy/cloudRun/utils/cloudRunExecutionUrl.js +16 -0
  13. package/dist/deploy/cloudRun/utils/jobName.d.ts +5 -1
  14. package/dist/deploy/cloudRun/utils/jobName.js +14 -2
  15. package/dist/deploy/types/googleCloudRun.d.ts +95 -1
  16. package/dist/tsconfig.tsbuildinfo +1 -1
  17. package/examples/__snapshots__/cloud-run-with-sql-legacy-jobs.test.ts.snap +1697 -0
  18. package/examples/__snapshots__/cloud-run-with-sql.test.ts.snap +133 -70
  19. package/examples/cloud-run-no-service.ts +6 -0
  20. package/examples/cloud-run-post-stop-job.ts +7 -0
  21. package/examples/cloud-run-service-custom-vpc-connector.ts +0 -1
  22. package/examples/cloud-run-service-custom-vpc.ts +0 -1
  23. package/examples/cloud-run-service-with-volumes.ts +9 -1
  24. package/examples/cloud-run-with-sql-legacy-jobs.test.ts +11 -0
  25. package/examples/cloud-run-with-sql-legacy-jobs.ts +49 -0
  26. package/examples/cloud-run-with-sql.ts +38 -4
  27. package/package.json +1 -1
  28. package/src/deploy/cloudRun/createJobs/cloudRunJobs.ts +16 -155
  29. package/src/deploy/cloudRun/createJobs/execute/onDeploy.ts +112 -0
  30. package/src/deploy/cloudRun/createJobs/execute/schedules.ts +186 -0
  31. package/src/deploy/cloudRun/createJobs/getCloudRunDeployScripts.ts +6 -8
  32. package/src/deploy/cloudRun/createJobs/getCloudRunStopScripts.ts +6 -8
  33. package/src/deploy/cloudRun/index.ts +6 -6
  34. package/src/deploy/cloudRun/utils/cloudRunExecutionUrl.ts +20 -0
  35. package/src/deploy/cloudRun/utils/jobName.ts +16 -1
  36. package/src/deploy/types/googleCloudRun.ts +123 -1
@@ -0,0 +1,1697 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`matches snapshot for cloud-run-with-sql-legacy-jobs 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 CLOUD_SQL_INSTANCE_CONNECTION_NAME="projectId:region:instancename"
200
+ - export DB_NAME="pan-test-app-dev-api"
201
+ - export DB_USER="my-user"
202
+ - export DB_PASSWORD="$CL_dev_api_DB_PASSWORD"
203
+ - export DATABASE_URL="postgresql://$DB_USER:$DB_PASSWORD@localhost/$DB_NAME?host=/cloudsql/$CLOUD_SQL_INSTANCE_CONNECTION_NAME"
204
+ - export DATABASE_JDBC_URL="jdbc:postgresql:///$DB_NAME?cloudSqlInstance=$CLOUD_SQL_INSTANCE_CONNECTION_NAME&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=$DB_USER&password=$DB_PASSWORD"
205
+ - export CLOUD_RUN_JOB_TRIGGER_URL_migration="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-dev-api-migration:run"
206
+ - export CLOUD_RUN_JOB_TRIGGER_URL_send_reminders="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-dev-api-send-reminders:run"
207
+ - export DEPLOY_CLOUD_RUN_PROJECT_ID="google-project-id"
208
+ - export DEPLOY_CLOUD_RUN_REGION="europe-west6"
209
+ - export GCLOUD_DEPLOY_credentialsKey="$CL_dev_api_GCLOUD_DEPLOY_credentialsKey"
210
+ - export GCLOUD_RUN_canonicalHostSuffix="$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix"
211
+ - 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\\",\\"CLOUD_SQL_INSTANCE_CONNECTION_NAME\\",\\"DB_NAME\\",\\"DB_USER\\",\\"DB_PASSWORD\\",\\"DATABASE_URL\\",\\"DATABASE_JDBC_URL\\",\\"CLOUD_RUN_JOB_TRIGGER_URL_migration\\",\\"CLOUD_RUN_JOB_TRIGGER_URL_send_reminders\\",\\"DEPLOY_CLOUD_RUN_PROJECT_ID\\",\\"DEPLOY_CLOUD_RUN_REGION\\",\\"GCLOUD_DEPLOY_credentialsKey\\",\\"GCLOUD_RUN_canonicalHostSuffix\\"]"
212
+ - collapseable_section_end "injectvars"
213
+ - collapseable_section_start "write-dotenv-api" "write dot env for api"
214
+ - |-
215
+ cat <<EOF > api/.env
216
+ ENV_SHORT=dev
217
+ APP_DIR=api
218
+ ENV_TYPE=dev
219
+ HOSTNAME=$(printf %s "$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
220
+ ROOT_URL=$(printf %s "https://$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
221
+ HOSTNAME_INTERNAL=$(printf %s "$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
222
+ ROOT_URL_INTERNAL=$(printf %s "https://$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
223
+ CLOUD_SQL_INSTANCE_CONNECTION_NAME=projectId:region:instancename
224
+ DB_NAME=pan-test-app-dev-api
225
+ DB_USER=my-user
226
+ DB_PASSWORD=$(printf %s "$CL_dev_api_DB_PASSWORD" | escapeForDotEnv)
227
+ DATABASE_URL=postgresql://$DB_USER:$DB_PASSWORD@localhost/$DB_NAME?host=/cloudsql/$CLOUD_SQL_INSTANCE_CONNECTION_NAME
228
+ DATABASE_JDBC_URL=jdbc:postgresql:///$DB_NAME?cloudSqlInstance=$CLOUD_SQL_INSTANCE_CONNECTION_NAME&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=$DB_USER&password=$DB_PASSWORD
229
+ CLOUD_RUN_JOB_TRIGGER_URL_migration=https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-dev-api-migration:run
230
+ CLOUD_RUN_JOB_TRIGGER_URL_send_reminders=https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-dev-api-send-reminders:run
231
+ DEPLOY_CLOUD_RUN_PROJECT_ID=google-project-id
232
+ DEPLOY_CLOUD_RUN_REGION=europe-west6
233
+ GCLOUD_DEPLOY_credentialsKey=$(printf %s "$CL_dev_api_GCLOUD_DEPLOY_credentialsKey" | escapeForDotEnv)
234
+ GCLOUD_RUN_canonicalHostSuffix=$(printf %s "$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | escapeForDotEnv)
235
+ _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","CLOUD_SQL_INSTANCE_CONNECTION_NAME","DB_NAME","DB_USER","DB_PASSWORD","DATABASE_URL","DATABASE_JDBC_URL","CLOUD_RUN_JOB_TRIGGER_URL_migration","CLOUD_RUN_JOB_TRIGGER_URL_send_reminders","DEPLOY_CLOUD_RUN_PROJECT_ID","DEPLOY_CLOUD_RUN_REGION","GCLOUD_DEPLOY_credentialsKey","GCLOUD_RUN_canonicalHostSuffix"]
236
+ EOF
237
+ - collapseable_section_end "write-dotenv-api"
238
+ - echo '{"id":"$(git describe --tags 2>/dev/null || git rev-parse HEAD)","time":"$CI_JOB_STARTED_AT"}' > api/__build_info.json
239
+ - collapseable_section_start "nodeinstall" "Ensure node version"
240
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
241
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
242
+ - collapseable_section_end "nodeinstall"
243
+ - cd api
244
+ - collapseable_section_start "nodeinstall" "Ensure node version"
245
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
246
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
247
+ - collapseable_section_end "nodeinstall"
248
+ - collapseable_section_start "yarninstall" "Yarn install"
249
+ - yarn install --immutable
250
+ - collapseable_section_end "yarninstall"
251
+ - yarn build
252
+ cache:
253
+ - key: api-yarn
254
+ policy: pull-push
255
+ paths:
256
+ - api/.yarn
257
+ - key: api-node-modules
258
+ policy: pull-push
259
+ paths:
260
+ - api/node_modules
261
+ artifacts:
262
+ paths:
263
+ - api/__build_info.json
264
+ - api/.next
265
+ - api/dist
266
+ exclude:
267
+ - api/.env
268
+ expire_in: 1 day
269
+ when: always
270
+ reports: {}
271
+ rules:
272
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_MESSAGE !~ /^chore\\(release\\).*/
273
+ needs: []
274
+ retry: *a1
275
+ interruptible: true
276
+ 'api ๐Ÿ”จ docker | dev ':
277
+ stage: build
278
+ image: path/to/docker/docker-build:the-version
279
+ services:
280
+ - name: docker:24.0.6-dind
281
+ command:
282
+ - --tls=false
283
+ - --registry-mirror=https://mirror.gcr.io
284
+ variables:
285
+ DOCKER_HOST: tcp://0.0.0.0:2375
286
+ DOCKER_TLS_CERTDIR: ''
287
+ DOCKER_DRIVER: overlay2
288
+ DOCKER_BUILDKIT: '1'
289
+ KUBERNETES_CPU_REQUEST: '0.45'
290
+ KUBERNETES_MEMORY_REQUEST: 1Gi
291
+ KUBERNETES_MEMORY_LIMIT: 2Gi
292
+ script:
293
+ - collapseable_section_start "injectvars" "Injecting variables"
294
+ - export APP_DIR="api"
295
+ - export DOCKER_BUILD_CONTEXT="."
296
+ - export DOCKER_REGISTRY="europe-west6-docker.pkg.dev"
297
+ - export DOCKER_IMAGE="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/dev/api"
298
+ - export DOCKER_CACHE_IMAGE="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api"
299
+ - export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"
300
+ - |-
301
+ export DOCKER_COPY_AND_INSTALL_APP="COPY --chown=node:node $APP_DIR .
302
+ RUN yarn plugin import workspace-tools
303
+ RUN yarn workspaces focus --production && yarn rebuild"
304
+ - |-
305
+ export DOCKER_COPY_WORKSPACE_FILES="COPY --chown=node:node api/package.json /app/api/package.json
306
+ COPY --chown=node:node api/yarn.lock /app/api/yarn.lock
307
+ COPY --chown=node:node .yarnrc.yml /app/.yarnrc.yml
308
+ COPY --chown=node:node .yarn /app/.yarn"
309
+ - collapseable_section_end "injectvars"
310
+ - ensureNodeDockerfile
311
+ - collapseable_section_start "docker-login" "Docker Login"
312
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_dev_api_GCLOUD_DEPLOY_credentialsKey")
313
+ - gcloud auth configure-docker europe-west6-docker.pkg.dev
314
+ - collapseable_section_end "docker-login"
315
+ - collapseable_section_start "docker-build" "Docker build"
316
+ - 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
317
+ - collapseable_section_end "docker-build"
318
+ - collapseable_section_start "docker-push" "Docker push and tag"
319
+ - docker push $DOCKER_IMAGE:$DOCKER_IMAGE_TAG
320
+ - docker tag $DOCKER_IMAGE:$DOCKER_IMAGE_TAG $DOCKER_CACHE_IMAGE
321
+ - docker push $DOCKER_CACHE_IMAGE
322
+ - collapseable_section_end "docker-push"
323
+ cache:
324
+ - key: api-yarn
325
+ policy: pull
326
+ paths:
327
+ - api/.yarn
328
+ rules:
329
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_MESSAGE !~ /^chore\\(release\\).*/
330
+ needs:
331
+ - 'api ๐Ÿ”จ app | dev '
332
+ retry: *a1
333
+ interruptible: true
334
+ 'api ๐Ÿงพ sbom | dev ':
335
+ stage: build
336
+ image: aquasec/trivy:0.38.3
337
+ variables: {}
338
+ script:
339
+ - collapseable_section_start "injectvars" "Injecting variables"
340
+ - collapseable_section_end "injectvars"
341
+ - trivy fs --quiet --format cyclonedx --output "__sbom.json" api
342
+ artifacts:
343
+ paths:
344
+ - __sbom.json
345
+ rules:
346
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_MESSAGE !~ /^chore\\(release\\).*/
347
+ needs: []
348
+ retry: *a1
349
+ interruptible: true
350
+ allow_failure: true
351
+ 'api ๐Ÿš€ Deploy | dev ':
352
+ stage: deploy dev
353
+ image: path/to/docker/gcloud:the-version
354
+ variables:
355
+ KUBERNETES_CPU_REQUEST: '0.22'
356
+ KUBERNETES_MEMORY_REQUEST: 200Mi
357
+ KUBERNETES_MEMORY_LIMIT: 400Mi
358
+ script:
359
+ - collapseable_section_start "injectvars" "Injecting variables"
360
+ - export ENV_SHORT="dev"
361
+ - export APP_DIR="api"
362
+ - export ENV_TYPE="dev"
363
+ - export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"
364
+ - export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"
365
+ - 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")"
366
+ - export HOSTNAME="$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
367
+ - export ROOT_URL="https://$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
368
+ - export HOSTNAME_INTERNAL="$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
369
+ - export ROOT_URL_INTERNAL="https://$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
370
+ - export CLOUD_SQL_INSTANCE_CONNECTION_NAME="projectId:region:instancename"
371
+ - export DB_NAME="pan-test-app-dev-api"
372
+ - export DB_USER="my-user"
373
+ - export DB_PASSWORD="$CL_dev_api_DB_PASSWORD"
374
+ - export DATABASE_URL="postgresql://$DB_USER:$DB_PASSWORD@localhost/$DB_NAME?host=/cloudsql/$CLOUD_SQL_INSTANCE_CONNECTION_NAME"
375
+ - export DATABASE_JDBC_URL="jdbc:postgresql:///$DB_NAME?cloudSqlInstance=$CLOUD_SQL_INSTANCE_CONNECTION_NAME&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=$DB_USER&password=$DB_PASSWORD"
376
+ - export CLOUD_RUN_JOB_TRIGGER_URL_migration="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-dev-api-migration:run"
377
+ - export CLOUD_RUN_JOB_TRIGGER_URL_send_reminders="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-dev-api-send-reminders:run"
378
+ - export DEPLOY_CLOUD_RUN_PROJECT_ID="google-project-id"
379
+ - export DEPLOY_CLOUD_RUN_REGION="europe-west6"
380
+ - export GCLOUD_DEPLOY_credentialsKey="$CL_dev_api_GCLOUD_DEPLOY_credentialsKey"
381
+ - export GCLOUD_RUN_canonicalHostSuffix="$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix"
382
+ - 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\\",\\"CLOUD_SQL_INSTANCE_CONNECTION_NAME\\",\\"DB_NAME\\",\\"DB_USER\\",\\"DB_PASSWORD\\",\\"DATABASE_URL\\",\\"DATABASE_JDBC_URL\\",\\"CLOUD_RUN_JOB_TRIGGER_URL_migration\\",\\"CLOUD_RUN_JOB_TRIGGER_URL_send_reminders\\",\\"DEPLOY_CLOUD_RUN_PROJECT_ID\\",\\"DEPLOY_CLOUD_RUN_REGION\\",\\"GCLOUD_DEPLOY_credentialsKey\\",\\"GCLOUD_RUN_canonicalHostSuffix\\"]"
383
+ - export DOCKER_REGISTRY="europe-west6-docker.pkg.dev"
384
+ - export DOCKER_IMAGE="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/dev/api"
385
+ - export DOCKER_CACHE_IMAGE="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api"
386
+ - export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"
387
+ - export CLOUDSDK_CORE_DISABLE_PROMPTS="1"
388
+ - collapseable_section_end "injectvars"
389
+ - collapseable_section_start "prepare" "Prepare..."
390
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_dev_api_GCLOUD_DEPLOY_credentialsKey")
391
+ - export GCLOUD_PROJECT_NUMBER=$(gcloud projects describe google-project-id --format="value(projectNumber)")
392
+ - 'echo "GCLOUD_PROJECT_NUMBER: $GCLOUD_PROJECT_NUMBER"'
393
+ - collapseable_section_end "prepare"
394
+ - collapseable_section_start "writeenvvars" "Write env vars to file"
395
+ - |
396
+ cat > ____envvars.yaml <<EOF
397
+ ENV_SHORT: |-
398
+ dev
399
+ APP_DIR: |-
400
+ api
401
+ ENV_TYPE: |-
402
+ dev
403
+ BUILD_INFO_BUILD_ID: |-
404
+ $(printf %s "$(git describe --tags 2>/dev/null || git rev-parse HEAD)" | sed '1!s/^/ /')
405
+ BUILD_INFO_BUILD_TIME: |-
406
+ $(printf %s "$CI_JOB_STARTED_AT" | sed '1!s/^/ /')
407
+ BUILD_INFO_CURRENT_VERSION: |-
408
+ $(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/^/ /')
409
+ HOSTNAME: |-
410
+ $(printf %s "$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
411
+ ROOT_URL: |-
412
+ $(printf %s "https://$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
413
+ HOSTNAME_INTERNAL: |-
414
+ $(printf %s "$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
415
+ ROOT_URL_INTERNAL: |-
416
+ $(printf %s "https://$(printf %s "pan-test-app-dev-api-$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
417
+ CLOUD_SQL_INSTANCE_CONNECTION_NAME: |-
418
+ projectId:region:instancename
419
+ DB_NAME: |-
420
+ pan-test-app-dev-api
421
+ DB_USER: |-
422
+ my-user
423
+ DB_PASSWORD: |-
424
+ $(printf %s "$CL_dev_api_DB_PASSWORD" | sed '1!s/^/ /')
425
+ DATABASE_URL: |-
426
+ postgresql://$DB_USER:$DB_PASSWORD@localhost/$DB_NAME?host=/cloudsql/$CLOUD_SQL_INSTANCE_CONNECTION_NAME
427
+ DATABASE_JDBC_URL: |-
428
+ jdbc:postgresql:///$DB_NAME?cloudSqlInstance=$CLOUD_SQL_INSTANCE_CONNECTION_NAME&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=$DB_USER&password=$DB_PASSWORD
429
+ CLOUD_RUN_JOB_TRIGGER_URL_migration: |-
430
+ https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-dev-api-migration:run
431
+ CLOUD_RUN_JOB_TRIGGER_URL_send_reminders: |-
432
+ https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-dev-api-send-reminders:run
433
+ DEPLOY_CLOUD_RUN_PROJECT_ID: |-
434
+ google-project-id
435
+ DEPLOY_CLOUD_RUN_REGION: |-
436
+ europe-west6
437
+ GCLOUD_RUN_canonicalHostSuffix: |-
438
+ $(printf %s "$CL_dev_api_GCLOUD_RUN_canonicalHostSuffix" | sed '1!s/^/ /')
439
+ _ALL_ENV_VAR_KEYS: |-
440
+ ["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","CLOUD_SQL_INSTANCE_CONNECTION_NAME","DB_NAME","DB_USER","DB_PASSWORD","DATABASE_URL","DATABASE_JDBC_URL","CLOUD_RUN_JOB_TRIGGER_URL_migration","CLOUD_RUN_JOB_TRIGGER_URL_send_reminders","DEPLOY_CLOUD_RUN_PROJECT_ID","DEPLOY_CLOUD_RUN_REGION","GCLOUD_DEPLOY_credentialsKey","GCLOUD_RUN_canonicalHostSuffix"]
441
+
442
+ EOF
443
+ - collapseable_section_end "writeenvvars"
444
+ - collapseable_section_start "deploy" "Deploy to cloud run"
445
+ - set +e
446
+ - echo "ensuring Database..."
447
+ - gcloud sql databases create pan-test-app-dev-api --instance=instancename --project projectId
448
+ - set -e
449
+ - |-
450
+ exist_scheduler_names="$(
451
+ gcloud scheduler jobs list --filter='httpTarget.uri ~ dev.*api' --format='value(name)' --limit=999 --location='europe-west6' --project='google-project-id'
452
+ )"
453
+ current_job_uri="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-dev-api-send-reminders:run"
454
+ current_scheduler_name="pan-test-app-dev-api-send-reminders-scheduler"
455
+ if grep "$current_scheduler_name" <<<"$exist_scheduler_names" >/dev/null; then
456
+ gcloud scheduler jobs update http "$current_scheduler_name" --project=google-project-id --location=europe-west6 --uri="$current_job_uri" --http-method=POST --oauth-service-account-email="$GCLOUD_PROJECT_NUMBER-compute@developer.gserviceaccount.com" --schedule="0 * * * *" --max-retry-attempts=0
457
+ else
458
+ gcloud scheduler jobs create http "$current_scheduler_name" --project=google-project-id --location=europe-west6 --uri="$current_job_uri" --http-method=POST --oauth-service-account-email="$GCLOUD_PROJECT_NUMBER-compute@developer.gserviceaccount.com" --schedule="0 * * * *" --max-retry-attempts=0
459
+ fi
460
+ - |-
461
+ exist_job_names="$(
462
+ gcloud run jobs list --filter='metadata.name ~ dev.*api' --format='value(name)' --limit=999 --project='google-project-id' --region='europe-west6'
463
+ )"
464
+ current_job_name="pan-test-app-dev-api-migration"
465
+ if grep "$current_job_name" <<<"$exist_job_names" >/dev/null; then
466
+ gcloud run jobs update "$current_job_name" --command="yarn,migrate" --labels="customer-name=pan,component-name=api,app-name=test-app,env-type=dev,env-name=dev,build-type=node,cloud-run-job-name=$current_job_name" --image="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/dev/api:$DOCKER_IMAGE_TAG" --project=google-project-id --region=europe-west6 --memory=512Mi --parallelism=1 --task-timeout=10m --env-vars-file=____envvars.yaml --max-retries=0 --set-cloudsql-instances=projectId:region:instancename
467
+ else
468
+ gcloud run jobs create "$current_job_name" --command="yarn,migrate" --labels="customer-name=pan,component-name=api,app-name=test-app,env-type=dev,env-name=dev,build-type=node,cloud-run-job-name=$current_job_name" --image="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/dev/api:$DOCKER_IMAGE_TAG" --project=google-project-id --region=europe-west6 --memory=512Mi --parallelism=1 --task-timeout=10m --env-vars-file=____envvars.yaml --max-retries=0 --set-cloudsql-instances=projectId:region:instancename
469
+ fi
470
+ - |-
471
+ current_job_name="pan-test-app-dev-api-send-reminders"
472
+ if grep "$current_job_name" <<<"$exist_job_names" >/dev/null; then
473
+ gcloud run jobs update "$current_job_name" --command="yarn,job:send-reminders" --labels="customer-name=pan,component-name=api,app-name=test-app,env-type=dev,env-name=dev,build-type=node,cloud-run-job-name=$current_job_name" --image="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/dev/api:$DOCKER_IMAGE_TAG" --project=google-project-id --region=europe-west6 --memory=512Mi --parallelism=1 --task-timeout=15m --env-vars-file=____envvars.yaml --max-retries=0 --set-cloudsql-instances=projectId:region:instancename
474
+ else
475
+ gcloud run jobs create "$current_job_name" --command="yarn,job:send-reminders" --labels="customer-name=pan,component-name=api,app-name=test-app,env-type=dev,env-name=dev,build-type=node,cloud-run-job-name=$current_job_name" --image="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/dev/api:$DOCKER_IMAGE_TAG" --project=google-project-id --region=europe-west6 --memory=512Mi --parallelism=1 --task-timeout=15m --env-vars-file=____envvars.yaml --max-retries=0 --set-cloudsql-instances=projectId:region:instancename
476
+ fi
477
+ - gcloud run jobs execute pan-test-app-dev-api-migration --project=google-project-id --region=europe-west6 --wait
478
+ - gcloud run deploy pan-test-app-dev-api --command="yarn,start" --image=europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/dev/api:$DOCKER_IMAGE_TAG --project=google-project-id --region=europe-west6 --set-cloudsql-instances=projectId:region:instancename --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=5 --cpu-throttling --allow-unauthenticated --ingress=all --cpu-boost
479
+ - collapseable_section_end "deploy"
480
+ - collapseable_section_start "cleanup" "Cleanup"
481
+ - gcloud run revisions list --project=google-project-id --region=europe-west6 --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-west6 --quiet $revisionname ; done
482
+ - gcloud artifacts docker images list europe-west6-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-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/dev/api@$version --quiet --delete-tags; done
483
+ - gcloud artifacts docker images list europe-west6-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-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api@$version --quiet --delete-tags; done
484
+ - collapseable_section_end "cleanup"
485
+ - echo 'Uploading SBOM to Dependency Track'
486
+ - /dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" upload "pan-test-app/api" "$ROOT_URL" "__sbom.json" vex.json || true
487
+ - echo "CL_GITLAB_ENVIRONMENT_URL=$ROOT_URL" >> gitlab_environment.env
488
+ environment:
489
+ name: dev/api
490
+ url: $CL_GITLAB_ENVIRONMENT_URL
491
+ on_stop: 'api ๐Ÿ›‘ Stop โš ๏ธ | dev '
492
+ auto_stop_in: 4 weeks
493
+ artifacts:
494
+ reports:
495
+ dotenv: gitlab_environment.env
496
+ rules:
497
+ - when: on_success
498
+ if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_MESSAGE !~ /^chore\\(release\\).*/
499
+ needs:
500
+ - job: api ๐Ÿ‘ฎ lint
501
+ artifacts: false
502
+ - job: 'api ๐Ÿ”จ app | dev '
503
+ artifacts: false
504
+ - job: 'api ๐Ÿ”จ docker | dev '
505
+ artifacts: false
506
+ - job: api ๐Ÿงช test
507
+ artifacts: false
508
+ - job: 'api ๐Ÿงพ sbom | dev '
509
+ artifacts: true
510
+ - job: api ๐Ÿ›ก audit
511
+ artifacts: false
512
+ retry: *a1
513
+ interruptible: true
514
+ allow_failure: false
515
+ 'api ๐Ÿ›‘ Stop โš ๏ธ | dev ':
516
+ stage: stop dev
517
+ image: path/to/docker/gcloud:the-version
518
+ variables:
519
+ KUBERNETES_CPU_REQUEST: '0.22'
520
+ KUBERNETES_MEMORY_REQUEST: 200Mi
521
+ KUBERNETES_MEMORY_LIMIT: 400Mi
522
+ GIT_STRATEGY: none
523
+ script:
524
+ - collapseable_section_start "injectvars" "Injecting variables"
525
+ - export CLOUDSDK_CORE_DISABLE_PROMPTS="1"
526
+ - collapseable_section_end "injectvars"
527
+ - set +e
528
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_dev_api_GCLOUD_DEPLOY_credentialsKey")
529
+ - gcloud run services delete pan-test-app-dev-api --project=google-project-id --region=europe-west6
530
+ - gcloud scheduler jobs delete pan-test-app-dev-api-send-reminders-scheduler --project=google-project-id --location=europe-west6
531
+ - gcloud run jobs executions list --project=google-project-id --region=europe-west6 --job pan-test-app-dev-api-migration --format="value(name)" | xargs -I {} gcloud run jobs executions delete {} --quiet --project=google-project-id --region=europe-west6
532
+ - gcloud run jobs delete pan-test-app-dev-api-migration --project=google-project-id --region=europe-west6
533
+ - gcloud run jobs executions list --project=google-project-id --region=europe-west6 --job pan-test-app-dev-api-send-reminders --format="value(name)" | xargs -I {} gcloud run jobs executions delete {} --quiet --project=google-project-id --region=europe-west6
534
+ - gcloud run jobs delete pan-test-app-dev-api-send-reminders --project=google-project-id --region=europe-west6
535
+ - gcloud artifacts docker images delete europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/dev/api --quiet --delete-tags
536
+ - gcloud artifacts docker images list europe-west6-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-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api@$version --quiet --delete-tags; done
537
+ - echo 'Disabling component in Dependency Track'
538
+ - /dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" disable "pan-test-app/api" "$CI_ENVIRONMENT_URL" || true
539
+ - set -e
540
+ environment:
541
+ name: dev/api
542
+ action: stop
543
+ rules:
544
+ - if: $CI_COMMIT_BRANCH =~ /^[0-9]+\\.([0-9]+|x)\\.x$/
545
+ when: on_success
546
+ - when: manual
547
+ if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_MESSAGE !~ /^chore\\(release\\).*/
548
+ needs: []
549
+ retry: *a1
550
+ interruptible: true
551
+ allow_failure: true
552
+ 'api ๐Ÿ”จ app | review ':
553
+ stage: build
554
+ image: path/to/docker/jobs-default:the-version
555
+ variables:
556
+ KUBERNETES_CPU_REQUEST: '0.45'
557
+ KUBERNETES_MEMORY_REQUEST: 1Gi
558
+ KUBERNETES_MEMORY_LIMIT: 4Gi
559
+ script:
560
+ - collapseable_section_start "injectvars" "Injecting variables"
561
+ - export ENV_SHORT="review"
562
+ - export APP_DIR="api"
563
+ - export ENV_TYPE="review"
564
+ - export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"
565
+ - export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"
566
+ - 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")"
567
+ - 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)}')"
568
+ - 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)}')"
569
+ - 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)}')"
570
+ - 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)}')"
571
+ - export CLOUD_SQL_INSTANCE_CONNECTION_NAME="projectId:region:instancename"
572
+ - export DB_NAME="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"
573
+ - export DB_USER="my-user"
574
+ - export DB_PASSWORD="$CL_review_api_DB_PASSWORD"
575
+ - export DATABASE_URL="postgresql://$DB_USER:$DB_PASSWORD@localhost/$DB_NAME?host=/cloudsql/$CLOUD_SQL_INSTANCE_CONNECTION_NAME"
576
+ - export DATABASE_JDBC_URL="jdbc:postgresql:///$DB_NAME?cloudSqlInstance=$CLOUD_SQL_INSTANCE_CONNECTION_NAME&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=$DB_USER&password=$DB_PASSWORD"
577
+ - export CLOUD_RUN_JOB_TRIGGER_URL_migration="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/$(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)}')-migration:run"
578
+ - export CLOUD_RUN_JOB_TRIGGER_URL_send_reminders="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/$(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)}')-send-reminders:run"
579
+ - export DEPLOY_CLOUD_RUN_PROJECT_ID="google-project-id"
580
+ - export DEPLOY_CLOUD_RUN_REGION="europe-west6"
581
+ - export GCLOUD_DEPLOY_credentialsKey="$CL_review_api_GCLOUD_DEPLOY_credentialsKey"
582
+ - export GCLOUD_RUN_canonicalHostSuffix="$CL_review_api_GCLOUD_RUN_canonicalHostSuffix"
583
+ - 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\\",\\"CLOUD_SQL_INSTANCE_CONNECTION_NAME\\",\\"DB_NAME\\",\\"DB_USER\\",\\"DB_PASSWORD\\",\\"DATABASE_URL\\",\\"DATABASE_JDBC_URL\\",\\"CLOUD_RUN_JOB_TRIGGER_URL_migration\\",\\"CLOUD_RUN_JOB_TRIGGER_URL_send_reminders\\",\\"DEPLOY_CLOUD_RUN_PROJECT_ID\\",\\"DEPLOY_CLOUD_RUN_REGION\\",\\"GCLOUD_DEPLOY_credentialsKey\\",\\"GCLOUD_RUN_canonicalHostSuffix\\"]"
584
+ - collapseable_section_end "injectvars"
585
+ - collapseable_section_start "write-dotenv-api" "write dot env for api"
586
+ - |-
587
+ cat <<EOF > api/.env
588
+ ENV_SHORT=review
589
+ APP_DIR=api
590
+ ENV_TYPE=review
591
+ 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)
592
+ 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)
593
+ 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)
594
+ 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)
595
+ CLOUD_SQL_INSTANCE_CONNECTION_NAME=projectId:region:instancename
596
+ DB_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" | escapeForDotEnv)
597
+ DB_USER=my-user
598
+ DB_PASSWORD=$(printf %s "$CL_review_api_DB_PASSWORD" | escapeForDotEnv)
599
+ DATABASE_URL=postgresql://$DB_USER:$DB_PASSWORD@localhost/$DB_NAME?host=/cloudsql/$CLOUD_SQL_INSTANCE_CONNECTION_NAME
600
+ DATABASE_JDBC_URL=jdbc:postgresql:///$DB_NAME?cloudSqlInstance=$CLOUD_SQL_INSTANCE_CONNECTION_NAME&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=$DB_USER&password=$DB_PASSWORD
601
+ CLOUD_RUN_JOB_TRIGGER_URL_migration=https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/$(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)}')-migration:run
602
+ CLOUD_RUN_JOB_TRIGGER_URL_send_reminders=https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/$(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)}')-send-reminders:run
603
+ DEPLOY_CLOUD_RUN_PROJECT_ID=google-project-id
604
+ DEPLOY_CLOUD_RUN_REGION=europe-west6
605
+ GCLOUD_DEPLOY_credentialsKey=$(printf %s "$CL_review_api_GCLOUD_DEPLOY_credentialsKey" | escapeForDotEnv)
606
+ GCLOUD_RUN_canonicalHostSuffix=$(printf %s "$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | escapeForDotEnv)
607
+ _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","CLOUD_SQL_INSTANCE_CONNECTION_NAME","DB_NAME","DB_USER","DB_PASSWORD","DATABASE_URL","DATABASE_JDBC_URL","CLOUD_RUN_JOB_TRIGGER_URL_migration","CLOUD_RUN_JOB_TRIGGER_URL_send_reminders","DEPLOY_CLOUD_RUN_PROJECT_ID","DEPLOY_CLOUD_RUN_REGION","GCLOUD_DEPLOY_credentialsKey","GCLOUD_RUN_canonicalHostSuffix"]
608
+ EOF
609
+ - collapseable_section_end "write-dotenv-api"
610
+ - echo '{"id":"$(git describe --tags 2>/dev/null || git rev-parse HEAD)","time":"$CI_JOB_STARTED_AT"}' > api/__build_info.json
611
+ - collapseable_section_start "nodeinstall" "Ensure node version"
612
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
613
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
614
+ - collapseable_section_end "nodeinstall"
615
+ - cd api
616
+ - collapseable_section_start "nodeinstall" "Ensure node version"
617
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
618
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
619
+ - collapseable_section_end "nodeinstall"
620
+ - collapseable_section_start "yarninstall" "Yarn install"
621
+ - yarn install --immutable
622
+ - collapseable_section_end "yarninstall"
623
+ - yarn build
624
+ cache:
625
+ - key: api-yarn
626
+ policy: pull-push
627
+ paths:
628
+ - api/.yarn
629
+ - key: api-node-modules
630
+ policy: pull-push
631
+ paths:
632
+ - api/node_modules
633
+ artifacts:
634
+ paths:
635
+ - api/__build_info.json
636
+ - api/.next
637
+ - api/dist
638
+ exclude:
639
+ - api/.env
640
+ expire_in: 1 day
641
+ when: always
642
+ reports: {}
643
+ rules:
644
+ - if: $CI_MERGE_REQUEST_ID
645
+ needs: []
646
+ retry: *a1
647
+ interruptible: true
648
+ 'api ๐Ÿ”จ docker | review ':
649
+ stage: build
650
+ image: path/to/docker/docker-build:the-version
651
+ services:
652
+ - name: docker:24.0.6-dind
653
+ command:
654
+ - --tls=false
655
+ - --registry-mirror=https://mirror.gcr.io
656
+ variables:
657
+ DOCKER_HOST: tcp://0.0.0.0:2375
658
+ DOCKER_TLS_CERTDIR: ''
659
+ DOCKER_DRIVER: overlay2
660
+ DOCKER_BUILDKIT: '1'
661
+ KUBERNETES_CPU_REQUEST: '0.45'
662
+ KUBERNETES_MEMORY_REQUEST: 1Gi
663
+ KUBERNETES_MEMORY_LIMIT: 2Gi
664
+ script:
665
+ - collapseable_section_start "injectvars" "Injecting variables"
666
+ - export APP_DIR="api"
667
+ - export DOCKER_BUILD_CONTEXT="."
668
+ - export DOCKER_REGISTRY="europe-west6-docker.pkg.dev"
669
+ - export DOCKER_IMAGE="europe-west6-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"; })"
670
+ - export DOCKER_CACHE_IMAGE="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api"
671
+ - export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"
672
+ - |-
673
+ export DOCKER_COPY_AND_INSTALL_APP="COPY --chown=node:node $APP_DIR .
674
+ RUN yarn plugin import workspace-tools
675
+ RUN yarn workspaces focus --production && yarn rebuild"
676
+ - |-
677
+ export DOCKER_COPY_WORKSPACE_FILES="COPY --chown=node:node api/package.json /app/api/package.json
678
+ COPY --chown=node:node api/yarn.lock /app/api/yarn.lock
679
+ COPY --chown=node:node .yarnrc.yml /app/.yarnrc.yml
680
+ COPY --chown=node:node .yarn /app/.yarn"
681
+ - collapseable_section_end "injectvars"
682
+ - ensureNodeDockerfile
683
+ - collapseable_section_start "docker-login" "Docker Login"
684
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_review_api_GCLOUD_DEPLOY_credentialsKey")
685
+ - gcloud auth configure-docker europe-west6-docker.pkg.dev
686
+ - collapseable_section_end "docker-login"
687
+ - collapseable_section_start "docker-build" "Docker build"
688
+ - 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
689
+ - collapseable_section_end "docker-build"
690
+ - collapseable_section_start "docker-push" "Docker push and tag"
691
+ - docker push $DOCKER_IMAGE:$DOCKER_IMAGE_TAG
692
+ - docker tag $DOCKER_IMAGE:$DOCKER_IMAGE_TAG $DOCKER_CACHE_IMAGE
693
+ - docker push $DOCKER_CACHE_IMAGE
694
+ - collapseable_section_end "docker-push"
695
+ cache:
696
+ - key: api-yarn
697
+ policy: pull
698
+ paths:
699
+ - api/.yarn
700
+ rules:
701
+ - if: $CI_MERGE_REQUEST_ID
702
+ needs:
703
+ - 'api ๐Ÿ”จ app | review '
704
+ retry: *a1
705
+ interruptible: true
706
+ 'api ๐Ÿงพ sbom | review ':
707
+ stage: build
708
+ image: aquasec/trivy:0.38.3
709
+ variables: {}
710
+ script:
711
+ - collapseable_section_start "injectvars" "Injecting variables"
712
+ - collapseable_section_end "injectvars"
713
+ - trivy fs --quiet --format cyclonedx --output "__sbom.json" api
714
+ artifacts:
715
+ paths:
716
+ - __sbom.json
717
+ rules:
718
+ - if: $CI_MERGE_REQUEST_ID
719
+ needs: []
720
+ retry: *a1
721
+ interruptible: true
722
+ allow_failure: true
723
+ 'api ๐Ÿš€ Deploy | review ':
724
+ stage: deploy review
725
+ image: path/to/docker/gcloud:the-version
726
+ variables:
727
+ KUBERNETES_CPU_REQUEST: '0.22'
728
+ KUBERNETES_MEMORY_REQUEST: 200Mi
729
+ KUBERNETES_MEMORY_LIMIT: 400Mi
730
+ script:
731
+ - collapseable_section_start "injectvars" "Injecting variables"
732
+ - export ENV_SHORT="review"
733
+ - export APP_DIR="api"
734
+ - export ENV_TYPE="review"
735
+ - export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"
736
+ - export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"
737
+ - 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")"
738
+ - 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)}')"
739
+ - 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)}')"
740
+ - 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)}')"
741
+ - 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)}')"
742
+ - export CLOUD_SQL_INSTANCE_CONNECTION_NAME="projectId:region:instancename"
743
+ - export DB_NAME="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"
744
+ - export DB_USER="my-user"
745
+ - export DB_PASSWORD="$CL_review_api_DB_PASSWORD"
746
+ - export DATABASE_URL="postgresql://$DB_USER:$DB_PASSWORD@localhost/$DB_NAME?host=/cloudsql/$CLOUD_SQL_INSTANCE_CONNECTION_NAME"
747
+ - export DATABASE_JDBC_URL="jdbc:postgresql:///$DB_NAME?cloudSqlInstance=$CLOUD_SQL_INSTANCE_CONNECTION_NAME&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=$DB_USER&password=$DB_PASSWORD"
748
+ - export CLOUD_RUN_JOB_TRIGGER_URL_migration="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/$(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)}')-migration:run"
749
+ - export CLOUD_RUN_JOB_TRIGGER_URL_send_reminders="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/$(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)}')-send-reminders:run"
750
+ - export DEPLOY_CLOUD_RUN_PROJECT_ID="google-project-id"
751
+ - export DEPLOY_CLOUD_RUN_REGION="europe-west6"
752
+ - export GCLOUD_DEPLOY_credentialsKey="$CL_review_api_GCLOUD_DEPLOY_credentialsKey"
753
+ - export GCLOUD_RUN_canonicalHostSuffix="$CL_review_api_GCLOUD_RUN_canonicalHostSuffix"
754
+ - 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\\",\\"CLOUD_SQL_INSTANCE_CONNECTION_NAME\\",\\"DB_NAME\\",\\"DB_USER\\",\\"DB_PASSWORD\\",\\"DATABASE_URL\\",\\"DATABASE_JDBC_URL\\",\\"CLOUD_RUN_JOB_TRIGGER_URL_migration\\",\\"CLOUD_RUN_JOB_TRIGGER_URL_send_reminders\\",\\"DEPLOY_CLOUD_RUN_PROJECT_ID\\",\\"DEPLOY_CLOUD_RUN_REGION\\",\\"GCLOUD_DEPLOY_credentialsKey\\",\\"GCLOUD_RUN_canonicalHostSuffix\\"]"
755
+ - export DOCKER_REGISTRY="europe-west6-docker.pkg.dev"
756
+ - export DOCKER_IMAGE="europe-west6-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"; })"
757
+ - export DOCKER_CACHE_IMAGE="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api"
758
+ - export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"
759
+ - export CLOUDSDK_CORE_DISABLE_PROMPTS="1"
760
+ - collapseable_section_end "injectvars"
761
+ - collapseable_section_start "prepare" "Prepare..."
762
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_review_api_GCLOUD_DEPLOY_credentialsKey")
763
+ - export GCLOUD_PROJECT_NUMBER=$(gcloud projects describe google-project-id --format="value(projectNumber)")
764
+ - 'echo "GCLOUD_PROJECT_NUMBER: $GCLOUD_PROJECT_NUMBER"'
765
+ - collapseable_section_end "prepare"
766
+ - collapseable_section_start "writeenvvars" "Write env vars to file"
767
+ - |
768
+ cat > ____envvars.yaml <<EOF
769
+ ENV_SHORT: |-
770
+ review
771
+ APP_DIR: |-
772
+ api
773
+ ENV_TYPE: |-
774
+ review
775
+ BUILD_INFO_BUILD_ID: |-
776
+ $(printf %s "$(git describe --tags 2>/dev/null || git rev-parse HEAD)" | sed '1!s/^/ /')
777
+ BUILD_INFO_BUILD_TIME: |-
778
+ $(printf %s "$CI_JOB_STARTED_AT" | sed '1!s/^/ /')
779
+ BUILD_INFO_CURRENT_VERSION: |-
780
+ $(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/^/ /')
781
+ HOSTNAME: |-
782
+ $(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/^/ /')
783
+ ROOT_URL: |-
784
+ $(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/^/ /')
785
+ HOSTNAME_INTERNAL: |-
786
+ $(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/^/ /')
787
+ ROOT_URL_INTERNAL: |-
788
+ $(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/^/ /')
789
+ CLOUD_SQL_INSTANCE_CONNECTION_NAME: |-
790
+ projectId:region:instancename
791
+ DB_NAME: |-
792
+ $(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" | sed '1!s/^/ /')
793
+ DB_USER: |-
794
+ my-user
795
+ DB_PASSWORD: |-
796
+ $(printf %s "$CL_review_api_DB_PASSWORD" | sed '1!s/^/ /')
797
+ DATABASE_URL: |-
798
+ postgresql://$DB_USER:$DB_PASSWORD@localhost/$DB_NAME?host=/cloudsql/$CLOUD_SQL_INSTANCE_CONNECTION_NAME
799
+ DATABASE_JDBC_URL: |-
800
+ jdbc:postgresql:///$DB_NAME?cloudSqlInstance=$CLOUD_SQL_INSTANCE_CONNECTION_NAME&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=$DB_USER&password=$DB_PASSWORD
801
+ CLOUD_RUN_JOB_TRIGGER_URL_migration: |-
802
+ https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/$(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)}')-migration:run
803
+ CLOUD_RUN_JOB_TRIGGER_URL_send_reminders: |-
804
+ https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/$(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)}')-send-reminders:run
805
+ DEPLOY_CLOUD_RUN_PROJECT_ID: |-
806
+ google-project-id
807
+ DEPLOY_CLOUD_RUN_REGION: |-
808
+ europe-west6
809
+ GCLOUD_RUN_canonicalHostSuffix: |-
810
+ $(printf %s "$CL_review_api_GCLOUD_RUN_canonicalHostSuffix" | sed '1!s/^/ /')
811
+ _ALL_ENV_VAR_KEYS: |-
812
+ ["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","CLOUD_SQL_INSTANCE_CONNECTION_NAME","DB_NAME","DB_USER","DB_PASSWORD","DATABASE_URL","DATABASE_JDBC_URL","CLOUD_RUN_JOB_TRIGGER_URL_migration","CLOUD_RUN_JOB_TRIGGER_URL_send_reminders","DEPLOY_CLOUD_RUN_PROJECT_ID","DEPLOY_CLOUD_RUN_REGION","GCLOUD_DEPLOY_credentialsKey","GCLOUD_RUN_canonicalHostSuffix"]
813
+
814
+ EOF
815
+ - collapseable_section_end "writeenvvars"
816
+ - collapseable_section_start "deploy" "Deploy to cloud run"
817
+ - set +e
818
+ - echo "ensuring Database..."
819
+ - gcloud sql databases create 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 --instance=instancename --project projectId
820
+ - set -e
821
+ - |-
822
+ exist_scheduler_names="$(
823
+ gcloud scheduler jobs list --filter='httpTarget.uri ~ review.*api' --format='value(name)' --limit=999 --location='europe-west6' --project='google-project-id'
824
+ )"
825
+ current_job_uri="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/$(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)}')-send-reminders:run"
826
+ current_scheduler_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)}')-send-reminders-scheduler"
827
+ if grep "$current_scheduler_name" <<<"$exist_scheduler_names" >/dev/null; then
828
+ gcloud scheduler jobs update http "$current_scheduler_name" --project=google-project-id --location=europe-west6 --uri="$current_job_uri" --http-method=POST --oauth-service-account-email="$GCLOUD_PROJECT_NUMBER-compute@developer.gserviceaccount.com" --schedule="0 * * * *" --max-retry-attempts=0
829
+ else
830
+ gcloud scheduler jobs create http "$current_scheduler_name" --project=google-project-id --location=europe-west6 --uri="$current_job_uri" --http-method=POST --oauth-service-account-email="$GCLOUD_PROJECT_NUMBER-compute@developer.gserviceaccount.com" --schedule="0 * * * *" --max-retry-attempts=0
831
+ fi
832
+ - |-
833
+ exist_job_names="$(
834
+ gcloud run jobs list --filter='metadata.name ~ review.*api' --format='value(name)' --limit=999 --project='google-project-id' --region='europe-west6'
835
+ )"
836
+ current_job_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)}')-migration"
837
+ if grep "$current_job_name" <<<"$exist_job_names" >/dev/null; then
838
+ gcloud run jobs update "$current_job_name" --command="yarn,migrate" --labels="customer-name=pan,component-name=api,app-name=test-app,env-type=review,env-name=review,build-type=node,cloud-run-job-name=$current_job_name" --image="europe-west6-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-west6 --memory=512Mi --parallelism=1 --task-timeout=10m --env-vars-file=____envvars.yaml --max-retries=0 --set-cloudsql-instances=projectId:region:instancename
839
+ else
840
+ gcloud run jobs create "$current_job_name" --command="yarn,migrate" --labels="customer-name=pan,component-name=api,app-name=test-app,env-type=review,env-name=review,build-type=node,cloud-run-job-name=$current_job_name" --image="europe-west6-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-west6 --memory=512Mi --parallelism=1 --task-timeout=10m --env-vars-file=____envvars.yaml --max-retries=0 --set-cloudsql-instances=projectId:region:instancename
841
+ fi
842
+ - |-
843
+ current_job_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)}')-send-reminders"
844
+ if grep "$current_job_name" <<<"$exist_job_names" >/dev/null; then
845
+ gcloud run jobs update "$current_job_name" --command="yarn,job:send-reminders" --labels="customer-name=pan,component-name=api,app-name=test-app,env-type=review,env-name=review,build-type=node,cloud-run-job-name=$current_job_name" --image="europe-west6-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-west6 --memory=512Mi --parallelism=1 --task-timeout=15m --env-vars-file=____envvars.yaml --max-retries=0 --set-cloudsql-instances=projectId:region:instancename
846
+ else
847
+ gcloud run jobs create "$current_job_name" --command="yarn,job:send-reminders" --labels="customer-name=pan,component-name=api,app-name=test-app,env-type=review,env-name=review,build-type=node,cloud-run-job-name=$current_job_name" --image="europe-west6-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-west6 --memory=512Mi --parallelism=1 --task-timeout=15m --env-vars-file=____envvars.yaml --max-retries=0 --set-cloudsql-instances=projectId:region:instancename
848
+ fi
849
+ - gcloud run jobs execute $(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)}')-migration --project=google-project-id --region=europe-west6 --wait
850
+ - gcloud 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-west6-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-west6 --set-cloudsql-instances=projectId:region:instancename --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=5 --cpu-throttling --allow-unauthenticated --ingress=all --cpu-boost
851
+ - collapseable_section_end "deploy"
852
+ - collapseable_section_start "cleanup" "Cleanup"
853
+ - gcloud run revisions list --project=google-project-id --region=europe-west6 --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-west6 --quiet $revisionname ; done
854
+ - gcloud artifacts docker images list europe-west6-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-west6-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
855
+ - gcloud artifacts docker images list europe-west6-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-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api@$version --quiet --delete-tags; done
856
+ - set +e
857
+ - gcloud artifacts docker images delete europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/review/api --quiet --delete-tags
858
+ - set -e
859
+ - collapseable_section_end "cleanup"
860
+ - echo 'Uploading SBOM to Dependency Track'
861
+ - /dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" upload "pan-test-app/api" "$ROOT_URL" "__sbom.json" vex.json || true
862
+ - echo "CL_GITLAB_ENVIRONMENT_URL=$ROOT_URL" >> gitlab_environment.env
863
+ environment:
864
+ name: review/$CI_COMMIT_REF_NAME/api
865
+ url: $CL_GITLAB_ENVIRONMENT_URL
866
+ on_stop: 'api ๐Ÿ›‘ Stop โš ๏ธ | review '
867
+ auto_stop_in: 1 week
868
+ artifacts:
869
+ reports:
870
+ dotenv: gitlab_environment.env
871
+ rules:
872
+ - when: on_success
873
+ if: $CI_MERGE_REQUEST_ID
874
+ needs:
875
+ - job: api ๐Ÿ‘ฎ lint
876
+ artifacts: false
877
+ - job: 'api ๐Ÿ”จ app | review '
878
+ artifacts: false
879
+ - job: 'api ๐Ÿ”จ docker | review '
880
+ artifacts: false
881
+ - job: api ๐Ÿงช test
882
+ artifacts: false
883
+ - job: 'api ๐Ÿงพ sbom | review '
884
+ artifacts: true
885
+ - job: api ๐Ÿ›ก audit
886
+ artifacts: false
887
+ retry: *a1
888
+ interruptible: true
889
+ allow_failure: false
890
+ 'api ๐Ÿ›‘ Stop โš ๏ธ | review ':
891
+ stage: stop review
892
+ image: path/to/docker/gcloud:the-version
893
+ variables:
894
+ KUBERNETES_CPU_REQUEST: '0.22'
895
+ KUBERNETES_MEMORY_REQUEST: 200Mi
896
+ KUBERNETES_MEMORY_LIMIT: 400Mi
897
+ GIT_STRATEGY: none
898
+ script:
899
+ - collapseable_section_start "injectvars" "Injecting variables"
900
+ - export CLOUDSDK_CORE_DISABLE_PROMPTS="1"
901
+ - collapseable_section_end "injectvars"
902
+ - set +e
903
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_review_api_GCLOUD_DEPLOY_credentialsKey")
904
+ - 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-west6
905
+ - gcloud scheduler jobs 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)}')-send-reminders-scheduler --project=google-project-id --location=europe-west6
906
+ - gcloud run jobs executions list --project=google-project-id --region=europe-west6 --job $(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)}')-migration --format="value(name)" | xargs -I {} gcloud run jobs executions delete {} --quiet --project=google-project-id --region=europe-west6
907
+ - gcloud run jobs 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)}')-migration --project=google-project-id --region=europe-west6
908
+ - gcloud run jobs executions list --project=google-project-id --region=europe-west6 --job $(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)}')-send-reminders --format="value(name)" | xargs -I {} gcloud run jobs executions delete {} --quiet --project=google-project-id --region=europe-west6
909
+ - gcloud run jobs 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)}')-send-reminders --project=google-project-id --region=europe-west6
910
+ - echo "deleting database 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..."
911
+ - echo "๐Ÿ‘† this can take multiple attemps (3-5min), because google cloud run may still have a connection to the database after the cloud run service is shut down"
912
+ - "\\n until gcloud sql databases delete 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 --instance=instancename --project projectId\\n do\\n echo \\"Trying again.\\"\\n sleep 10\\n done\\n "
913
+ - gcloud artifacts docker images delete europe-west6-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
914
+ - gcloud artifacts docker images list europe-west6-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-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api@$version --quiet --delete-tags; done
915
+ - set +e
916
+ - gcloud artifacts docker images delete europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/review/api --quiet --delete-tags
917
+ - set -e
918
+ - echo 'Disabling component in Dependency Track'
919
+ - /dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" disable "pan-test-app/api" "$CI_ENVIRONMENT_URL" || true
920
+ - set -e
921
+ environment:
922
+ name: review/$CI_COMMIT_REF_NAME/api
923
+ action: stop
924
+ rules:
925
+ - if: $CI_COMMIT_BRANCH =~ /^[0-9]+\\.([0-9]+|x)\\.x$/
926
+ when: on_success
927
+ - when: manual
928
+ if: $CI_MERGE_REQUEST_ID
929
+ needs: []
930
+ retry: *a1
931
+ interruptible: true
932
+ allow_failure: true
933
+ 'api ๐Ÿ”จ app | stage ':
934
+ stage: build
935
+ image: path/to/docker/jobs-default:the-version
936
+ variables:
937
+ KUBERNETES_CPU_REQUEST: '0.45'
938
+ KUBERNETES_MEMORY_REQUEST: 1Gi
939
+ KUBERNETES_MEMORY_LIMIT: 4Gi
940
+ script:
941
+ - collapseable_section_start "injectvars" "Injecting variables"
942
+ - export ENV_SHORT="stage"
943
+ - export APP_DIR="api"
944
+ - export ENV_TYPE="stage"
945
+ - export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"
946
+ - export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"
947
+ - 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")"
948
+ - export HOSTNAME="$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
949
+ - export ROOT_URL="https://$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
950
+ - export HOSTNAME_INTERNAL="$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
951
+ - export ROOT_URL_INTERNAL="https://$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
952
+ - export CLOUD_SQL_INSTANCE_CONNECTION_NAME="projectId:region:instancename"
953
+ - export DB_NAME="pan-test-app-stage-api"
954
+ - export DB_USER="my-user"
955
+ - export DB_PASSWORD="$CL_stage_api_DB_PASSWORD"
956
+ - export DATABASE_URL="postgresql://$DB_USER:$DB_PASSWORD@localhost/$DB_NAME?host=/cloudsql/$CLOUD_SQL_INSTANCE_CONNECTION_NAME"
957
+ - export DATABASE_JDBC_URL="jdbc:postgresql:///$DB_NAME?cloudSqlInstance=$CLOUD_SQL_INSTANCE_CONNECTION_NAME&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=$DB_USER&password=$DB_PASSWORD"
958
+ - export CLOUD_RUN_JOB_TRIGGER_URL_migration="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-stage-api-migration:run"
959
+ - export CLOUD_RUN_JOB_TRIGGER_URL_send_reminders="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-stage-api-send-reminders:run"
960
+ - export DEPLOY_CLOUD_RUN_PROJECT_ID="google-project-id"
961
+ - export DEPLOY_CLOUD_RUN_REGION="europe-west6"
962
+ - export GCLOUD_DEPLOY_credentialsKey="$CL_stage_api_GCLOUD_DEPLOY_credentialsKey"
963
+ - export GCLOUD_RUN_canonicalHostSuffix="$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix"
964
+ - 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\\",\\"CLOUD_SQL_INSTANCE_CONNECTION_NAME\\",\\"DB_NAME\\",\\"DB_USER\\",\\"DB_PASSWORD\\",\\"DATABASE_URL\\",\\"DATABASE_JDBC_URL\\",\\"CLOUD_RUN_JOB_TRIGGER_URL_migration\\",\\"CLOUD_RUN_JOB_TRIGGER_URL_send_reminders\\",\\"DEPLOY_CLOUD_RUN_PROJECT_ID\\",\\"DEPLOY_CLOUD_RUN_REGION\\",\\"GCLOUD_DEPLOY_credentialsKey\\",\\"GCLOUD_RUN_canonicalHostSuffix\\"]"
965
+ - collapseable_section_end "injectvars"
966
+ - collapseable_section_start "write-dotenv-api" "write dot env for api"
967
+ - |-
968
+ cat <<EOF > api/.env
969
+ ENV_SHORT=stage
970
+ APP_DIR=api
971
+ ENV_TYPE=stage
972
+ HOSTNAME=$(printf %s "$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
973
+ ROOT_URL=$(printf %s "https://$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
974
+ HOSTNAME_INTERNAL=$(printf %s "$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
975
+ ROOT_URL_INTERNAL=$(printf %s "https://$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
976
+ CLOUD_SQL_INSTANCE_CONNECTION_NAME=projectId:region:instancename
977
+ DB_NAME=pan-test-app-stage-api
978
+ DB_USER=my-user
979
+ DB_PASSWORD=$(printf %s "$CL_stage_api_DB_PASSWORD" | escapeForDotEnv)
980
+ DATABASE_URL=postgresql://$DB_USER:$DB_PASSWORD@localhost/$DB_NAME?host=/cloudsql/$CLOUD_SQL_INSTANCE_CONNECTION_NAME
981
+ DATABASE_JDBC_URL=jdbc:postgresql:///$DB_NAME?cloudSqlInstance=$CLOUD_SQL_INSTANCE_CONNECTION_NAME&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=$DB_USER&password=$DB_PASSWORD
982
+ CLOUD_RUN_JOB_TRIGGER_URL_migration=https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-stage-api-migration:run
983
+ CLOUD_RUN_JOB_TRIGGER_URL_send_reminders=https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-stage-api-send-reminders:run
984
+ DEPLOY_CLOUD_RUN_PROJECT_ID=google-project-id
985
+ DEPLOY_CLOUD_RUN_REGION=europe-west6
986
+ GCLOUD_DEPLOY_credentialsKey=$(printf %s "$CL_stage_api_GCLOUD_DEPLOY_credentialsKey" | escapeForDotEnv)
987
+ GCLOUD_RUN_canonicalHostSuffix=$(printf %s "$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | escapeForDotEnv)
988
+ _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","CLOUD_SQL_INSTANCE_CONNECTION_NAME","DB_NAME","DB_USER","DB_PASSWORD","DATABASE_URL","DATABASE_JDBC_URL","CLOUD_RUN_JOB_TRIGGER_URL_migration","CLOUD_RUN_JOB_TRIGGER_URL_send_reminders","DEPLOY_CLOUD_RUN_PROJECT_ID","DEPLOY_CLOUD_RUN_REGION","GCLOUD_DEPLOY_credentialsKey","GCLOUD_RUN_canonicalHostSuffix"]
989
+ EOF
990
+ - collapseable_section_end "write-dotenv-api"
991
+ - echo '{"id":"$(git describe --tags 2>/dev/null || git rev-parse HEAD)","time":"$CI_JOB_STARTED_AT"}' > api/__build_info.json
992
+ - collapseable_section_start "nodeinstall" "Ensure node version"
993
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
994
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
995
+ - collapseable_section_end "nodeinstall"
996
+ - cd api
997
+ - collapseable_section_start "nodeinstall" "Ensure node version"
998
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
999
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
1000
+ - collapseable_section_end "nodeinstall"
1001
+ - collapseable_section_start "yarninstall" "Yarn install"
1002
+ - yarn install --immutable
1003
+ - collapseable_section_end "yarninstall"
1004
+ - yarn build
1005
+ cache:
1006
+ - key: api-yarn
1007
+ policy: pull-push
1008
+ paths:
1009
+ - api/.yarn
1010
+ - key: api-node-modules
1011
+ policy: pull-push
1012
+ paths:
1013
+ - api/node_modules
1014
+ artifacts:
1015
+ paths:
1016
+ - api/__build_info.json
1017
+ - api/.next
1018
+ - api/dist
1019
+ exclude:
1020
+ - api/.env
1021
+ expire_in: 1 day
1022
+ when: always
1023
+ reports: {}
1024
+ rules:
1025
+ - if: $CI_COMMIT_TAG
1026
+ needs: []
1027
+ retry: *a1
1028
+ interruptible: true
1029
+ 'api ๐Ÿ”จ docker | stage ':
1030
+ stage: build
1031
+ image: path/to/docker/docker-build:the-version
1032
+ services:
1033
+ - name: docker:24.0.6-dind
1034
+ command:
1035
+ - --tls=false
1036
+ - --registry-mirror=https://mirror.gcr.io
1037
+ variables:
1038
+ DOCKER_HOST: tcp://0.0.0.0:2375
1039
+ DOCKER_TLS_CERTDIR: ''
1040
+ DOCKER_DRIVER: overlay2
1041
+ DOCKER_BUILDKIT: '1'
1042
+ KUBERNETES_CPU_REQUEST: '0.45'
1043
+ KUBERNETES_MEMORY_REQUEST: 1Gi
1044
+ KUBERNETES_MEMORY_LIMIT: 2Gi
1045
+ script:
1046
+ - collapseable_section_start "injectvars" "Injecting variables"
1047
+ - export APP_DIR="api"
1048
+ - export DOCKER_BUILD_CONTEXT="."
1049
+ - export DOCKER_REGISTRY="europe-west6-docker.pkg.dev"
1050
+ - export DOCKER_IMAGE="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/stage/api"
1051
+ - export DOCKER_CACHE_IMAGE="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api"
1052
+ - export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"
1053
+ - |-
1054
+ export DOCKER_COPY_AND_INSTALL_APP="COPY --chown=node:node $APP_DIR .
1055
+ RUN yarn plugin import workspace-tools
1056
+ RUN yarn workspaces focus --production && yarn rebuild"
1057
+ - |-
1058
+ export DOCKER_COPY_WORKSPACE_FILES="COPY --chown=node:node api/package.json /app/api/package.json
1059
+ COPY --chown=node:node api/yarn.lock /app/api/yarn.lock
1060
+ COPY --chown=node:node .yarnrc.yml /app/.yarnrc.yml
1061
+ COPY --chown=node:node .yarn /app/.yarn"
1062
+ - collapseable_section_end "injectvars"
1063
+ - ensureNodeDockerfile
1064
+ - collapseable_section_start "docker-login" "Docker Login"
1065
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_stage_api_GCLOUD_DEPLOY_credentialsKey")
1066
+ - gcloud auth configure-docker europe-west6-docker.pkg.dev
1067
+ - collapseable_section_end "docker-login"
1068
+ - collapseable_section_start "docker-build" "Docker build"
1069
+ - 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
1070
+ - collapseable_section_end "docker-build"
1071
+ - collapseable_section_start "docker-push" "Docker push and tag"
1072
+ - docker push $DOCKER_IMAGE:$DOCKER_IMAGE_TAG
1073
+ - docker tag $DOCKER_IMAGE:$DOCKER_IMAGE_TAG $DOCKER_CACHE_IMAGE
1074
+ - docker push $DOCKER_CACHE_IMAGE
1075
+ - collapseable_section_end "docker-push"
1076
+ cache:
1077
+ - key: api-yarn
1078
+ policy: pull
1079
+ paths:
1080
+ - api/.yarn
1081
+ rules:
1082
+ - if: $CI_COMMIT_TAG
1083
+ needs:
1084
+ - 'api ๐Ÿ”จ app | stage '
1085
+ retry: *a1
1086
+ interruptible: true
1087
+ 'api ๐Ÿงพ sbom | stage ':
1088
+ stage: build
1089
+ image: aquasec/trivy:0.38.3
1090
+ variables: {}
1091
+ script:
1092
+ - collapseable_section_start "injectvars" "Injecting variables"
1093
+ - collapseable_section_end "injectvars"
1094
+ - trivy fs --quiet --format cyclonedx --output "__sbom.json" api
1095
+ artifacts:
1096
+ paths:
1097
+ - __sbom.json
1098
+ rules:
1099
+ - if: $CI_COMMIT_TAG
1100
+ needs: []
1101
+ retry: *a1
1102
+ interruptible: true
1103
+ allow_failure: true
1104
+ 'api ๐Ÿš€ Deploy | stage ':
1105
+ stage: deploy stage
1106
+ image: path/to/docker/gcloud:the-version
1107
+ variables:
1108
+ KUBERNETES_CPU_REQUEST: '0.22'
1109
+ KUBERNETES_MEMORY_REQUEST: 200Mi
1110
+ KUBERNETES_MEMORY_LIMIT: 400Mi
1111
+ script:
1112
+ - collapseable_section_start "injectvars" "Injecting variables"
1113
+ - export ENV_SHORT="stage"
1114
+ - export APP_DIR="api"
1115
+ - export ENV_TYPE="stage"
1116
+ - export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"
1117
+ - export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"
1118
+ - 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")"
1119
+ - export HOSTNAME="$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1120
+ - export ROOT_URL="https://$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1121
+ - export HOSTNAME_INTERNAL="$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1122
+ - export ROOT_URL_INTERNAL="https://$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1123
+ - export CLOUD_SQL_INSTANCE_CONNECTION_NAME="projectId:region:instancename"
1124
+ - export DB_NAME="pan-test-app-stage-api"
1125
+ - export DB_USER="my-user"
1126
+ - export DB_PASSWORD="$CL_stage_api_DB_PASSWORD"
1127
+ - export DATABASE_URL="postgresql://$DB_USER:$DB_PASSWORD@localhost/$DB_NAME?host=/cloudsql/$CLOUD_SQL_INSTANCE_CONNECTION_NAME"
1128
+ - export DATABASE_JDBC_URL="jdbc:postgresql:///$DB_NAME?cloudSqlInstance=$CLOUD_SQL_INSTANCE_CONNECTION_NAME&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=$DB_USER&password=$DB_PASSWORD"
1129
+ - export CLOUD_RUN_JOB_TRIGGER_URL_migration="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-stage-api-migration:run"
1130
+ - export CLOUD_RUN_JOB_TRIGGER_URL_send_reminders="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-stage-api-send-reminders:run"
1131
+ - export DEPLOY_CLOUD_RUN_PROJECT_ID="google-project-id"
1132
+ - export DEPLOY_CLOUD_RUN_REGION="europe-west6"
1133
+ - export GCLOUD_DEPLOY_credentialsKey="$CL_stage_api_GCLOUD_DEPLOY_credentialsKey"
1134
+ - export GCLOUD_RUN_canonicalHostSuffix="$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix"
1135
+ - 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\\",\\"CLOUD_SQL_INSTANCE_CONNECTION_NAME\\",\\"DB_NAME\\",\\"DB_USER\\",\\"DB_PASSWORD\\",\\"DATABASE_URL\\",\\"DATABASE_JDBC_URL\\",\\"CLOUD_RUN_JOB_TRIGGER_URL_migration\\",\\"CLOUD_RUN_JOB_TRIGGER_URL_send_reminders\\",\\"DEPLOY_CLOUD_RUN_PROJECT_ID\\",\\"DEPLOY_CLOUD_RUN_REGION\\",\\"GCLOUD_DEPLOY_credentialsKey\\",\\"GCLOUD_RUN_canonicalHostSuffix\\"]"
1136
+ - export DOCKER_REGISTRY="europe-west6-docker.pkg.dev"
1137
+ - export DOCKER_IMAGE="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/stage/api"
1138
+ - export DOCKER_CACHE_IMAGE="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api"
1139
+ - export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"
1140
+ - export CLOUDSDK_CORE_DISABLE_PROMPTS="1"
1141
+ - collapseable_section_end "injectvars"
1142
+ - collapseable_section_start "prepare" "Prepare..."
1143
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_stage_api_GCLOUD_DEPLOY_credentialsKey")
1144
+ - export GCLOUD_PROJECT_NUMBER=$(gcloud projects describe google-project-id --format="value(projectNumber)")
1145
+ - 'echo "GCLOUD_PROJECT_NUMBER: $GCLOUD_PROJECT_NUMBER"'
1146
+ - collapseable_section_end "prepare"
1147
+ - collapseable_section_start "writeenvvars" "Write env vars to file"
1148
+ - |
1149
+ cat > ____envvars.yaml <<EOF
1150
+ ENV_SHORT: |-
1151
+ stage
1152
+ APP_DIR: |-
1153
+ api
1154
+ ENV_TYPE: |-
1155
+ stage
1156
+ BUILD_INFO_BUILD_ID: |-
1157
+ $(printf %s "$(git describe --tags 2>/dev/null || git rev-parse HEAD)" | sed '1!s/^/ /')
1158
+ BUILD_INFO_BUILD_TIME: |-
1159
+ $(printf %s "$CI_JOB_STARTED_AT" | sed '1!s/^/ /')
1160
+ BUILD_INFO_CURRENT_VERSION: |-
1161
+ $(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/^/ /')
1162
+ HOSTNAME: |-
1163
+ $(printf %s "$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
1164
+ ROOT_URL: |-
1165
+ $(printf %s "https://$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
1166
+ HOSTNAME_INTERNAL: |-
1167
+ $(printf %s "$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
1168
+ ROOT_URL_INTERNAL: |-
1169
+ $(printf %s "https://$(printf %s "pan-test-app-stage-api-$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
1170
+ CLOUD_SQL_INSTANCE_CONNECTION_NAME: |-
1171
+ projectId:region:instancename
1172
+ DB_NAME: |-
1173
+ pan-test-app-stage-api
1174
+ DB_USER: |-
1175
+ my-user
1176
+ DB_PASSWORD: |-
1177
+ $(printf %s "$CL_stage_api_DB_PASSWORD" | sed '1!s/^/ /')
1178
+ DATABASE_URL: |-
1179
+ postgresql://$DB_USER:$DB_PASSWORD@localhost/$DB_NAME?host=/cloudsql/$CLOUD_SQL_INSTANCE_CONNECTION_NAME
1180
+ DATABASE_JDBC_URL: |-
1181
+ jdbc:postgresql:///$DB_NAME?cloudSqlInstance=$CLOUD_SQL_INSTANCE_CONNECTION_NAME&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=$DB_USER&password=$DB_PASSWORD
1182
+ CLOUD_RUN_JOB_TRIGGER_URL_migration: |-
1183
+ https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-stage-api-migration:run
1184
+ CLOUD_RUN_JOB_TRIGGER_URL_send_reminders: |-
1185
+ https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-stage-api-send-reminders:run
1186
+ DEPLOY_CLOUD_RUN_PROJECT_ID: |-
1187
+ google-project-id
1188
+ DEPLOY_CLOUD_RUN_REGION: |-
1189
+ europe-west6
1190
+ GCLOUD_RUN_canonicalHostSuffix: |-
1191
+ $(printf %s "$CL_stage_api_GCLOUD_RUN_canonicalHostSuffix" | sed '1!s/^/ /')
1192
+ _ALL_ENV_VAR_KEYS: |-
1193
+ ["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","CLOUD_SQL_INSTANCE_CONNECTION_NAME","DB_NAME","DB_USER","DB_PASSWORD","DATABASE_URL","DATABASE_JDBC_URL","CLOUD_RUN_JOB_TRIGGER_URL_migration","CLOUD_RUN_JOB_TRIGGER_URL_send_reminders","DEPLOY_CLOUD_RUN_PROJECT_ID","DEPLOY_CLOUD_RUN_REGION","GCLOUD_DEPLOY_credentialsKey","GCLOUD_RUN_canonicalHostSuffix"]
1194
+
1195
+ EOF
1196
+ - collapseable_section_end "writeenvvars"
1197
+ - collapseable_section_start "deploy" "Deploy to cloud run"
1198
+ - set +e
1199
+ - echo "ensuring Database..."
1200
+ - gcloud sql databases create pan-test-app-stage-api --instance=instancename --project projectId
1201
+ - set -e
1202
+ - |-
1203
+ exist_scheduler_names="$(
1204
+ gcloud scheduler jobs list --filter='httpTarget.uri ~ stage.*api' --format='value(name)' --limit=999 --location='europe-west6' --project='google-project-id'
1205
+ )"
1206
+ current_job_uri="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-stage-api-send-reminders:run"
1207
+ current_scheduler_name="pan-test-app-stage-api-send-reminders-scheduler"
1208
+ if grep "$current_scheduler_name" <<<"$exist_scheduler_names" >/dev/null; then
1209
+ gcloud scheduler jobs update http "$current_scheduler_name" --project=google-project-id --location=europe-west6 --uri="$current_job_uri" --http-method=POST --oauth-service-account-email="$GCLOUD_PROJECT_NUMBER-compute@developer.gserviceaccount.com" --schedule="0 * * * *" --max-retry-attempts=0
1210
+ else
1211
+ gcloud scheduler jobs create http "$current_scheduler_name" --project=google-project-id --location=europe-west6 --uri="$current_job_uri" --http-method=POST --oauth-service-account-email="$GCLOUD_PROJECT_NUMBER-compute@developer.gserviceaccount.com" --schedule="0 * * * *" --max-retry-attempts=0
1212
+ fi
1213
+ - |-
1214
+ exist_job_names="$(
1215
+ gcloud run jobs list --filter='metadata.name ~ stage.*api' --format='value(name)' --limit=999 --project='google-project-id' --region='europe-west6'
1216
+ )"
1217
+ current_job_name="pan-test-app-stage-api-migration"
1218
+ if grep "$current_job_name" <<<"$exist_job_names" >/dev/null; then
1219
+ gcloud run jobs update "$current_job_name" --command="yarn,migrate" --labels="customer-name=pan,component-name=api,app-name=test-app,env-type=stage,env-name=stage,build-type=node,cloud-run-job-name=$current_job_name" --image="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/stage/api:$DOCKER_IMAGE_TAG" --project=google-project-id --region=europe-west6 --memory=512Mi --parallelism=1 --task-timeout=10m --env-vars-file=____envvars.yaml --max-retries=0 --set-cloudsql-instances=projectId:region:instancename
1220
+ else
1221
+ gcloud run jobs create "$current_job_name" --command="yarn,migrate" --labels="customer-name=pan,component-name=api,app-name=test-app,env-type=stage,env-name=stage,build-type=node,cloud-run-job-name=$current_job_name" --image="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/stage/api:$DOCKER_IMAGE_TAG" --project=google-project-id --region=europe-west6 --memory=512Mi --parallelism=1 --task-timeout=10m --env-vars-file=____envvars.yaml --max-retries=0 --set-cloudsql-instances=projectId:region:instancename
1222
+ fi
1223
+ - |-
1224
+ current_job_name="pan-test-app-stage-api-send-reminders"
1225
+ if grep "$current_job_name" <<<"$exist_job_names" >/dev/null; then
1226
+ gcloud run jobs update "$current_job_name" --command="yarn,job:send-reminders" --labels="customer-name=pan,component-name=api,app-name=test-app,env-type=stage,env-name=stage,build-type=node,cloud-run-job-name=$current_job_name" --image="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/stage/api:$DOCKER_IMAGE_TAG" --project=google-project-id --region=europe-west6 --memory=512Mi --parallelism=1 --task-timeout=15m --env-vars-file=____envvars.yaml --max-retries=0 --set-cloudsql-instances=projectId:region:instancename
1227
+ else
1228
+ gcloud run jobs create "$current_job_name" --command="yarn,job:send-reminders" --labels="customer-name=pan,component-name=api,app-name=test-app,env-type=stage,env-name=stage,build-type=node,cloud-run-job-name=$current_job_name" --image="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/stage/api:$DOCKER_IMAGE_TAG" --project=google-project-id --region=europe-west6 --memory=512Mi --parallelism=1 --task-timeout=15m --env-vars-file=____envvars.yaml --max-retries=0 --set-cloudsql-instances=projectId:region:instancename
1229
+ fi
1230
+ - gcloud run jobs execute pan-test-app-stage-api-migration --project=google-project-id --region=europe-west6 --wait
1231
+ - gcloud run deploy pan-test-app-stage-api --command="yarn,start" --image=europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/stage/api:$DOCKER_IMAGE_TAG --project=google-project-id --region=europe-west6 --set-cloudsql-instances=projectId:region:instancename --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=5 --cpu-throttling --allow-unauthenticated --ingress=all --cpu-boost
1232
+ - collapseable_section_end "deploy"
1233
+ - collapseable_section_start "cleanup" "Cleanup"
1234
+ - gcloud run revisions list --project=google-project-id --region=europe-west6 --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-west6 --quiet $revisionname ; done
1235
+ - gcloud artifacts docker images list europe-west6-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-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/stage/api@$version --quiet --delete-tags; done
1236
+ - gcloud artifacts docker images list europe-west6-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-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api@$version --quiet --delete-tags; done
1237
+ - collapseable_section_end "cleanup"
1238
+ - echo 'Uploading SBOM to Dependency Track'
1239
+ - /dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" upload "pan-test-app/api" "$ROOT_URL" "__sbom.json" vex.json || true
1240
+ - echo "CL_GITLAB_ENVIRONMENT_URL=$ROOT_URL" >> gitlab_environment.env
1241
+ environment:
1242
+ name: stage/api
1243
+ url: $CL_GITLAB_ENVIRONMENT_URL
1244
+ on_stop: 'api ๐Ÿ›‘ Stop โš ๏ธ | stage '
1245
+ artifacts:
1246
+ reports:
1247
+ dotenv: gitlab_environment.env
1248
+ rules:
1249
+ - when: on_success
1250
+ if: $CI_COMMIT_TAG
1251
+ needs:
1252
+ - job: 'api ๐Ÿ”จ app | stage '
1253
+ artifacts: false
1254
+ - job: 'api ๐Ÿ”จ docker | stage '
1255
+ artifacts: false
1256
+ - job: 'api ๐Ÿงพ sbom | stage '
1257
+ artifacts: true
1258
+ retry: *a1
1259
+ interruptible: true
1260
+ allow_failure: false
1261
+ 'api ๐Ÿ›‘ Stop โš ๏ธ | stage ':
1262
+ stage: stop stage
1263
+ image: path/to/docker/gcloud:the-version
1264
+ variables:
1265
+ KUBERNETES_CPU_REQUEST: '0.22'
1266
+ KUBERNETES_MEMORY_REQUEST: 200Mi
1267
+ KUBERNETES_MEMORY_LIMIT: 400Mi
1268
+ GIT_STRATEGY: none
1269
+ script:
1270
+ - collapseable_section_start "injectvars" "Injecting variables"
1271
+ - export CLOUDSDK_CORE_DISABLE_PROMPTS="1"
1272
+ - collapseable_section_end "injectvars"
1273
+ - set +e
1274
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_stage_api_GCLOUD_DEPLOY_credentialsKey")
1275
+ - gcloud run services delete pan-test-app-stage-api --project=google-project-id --region=europe-west6
1276
+ - gcloud scheduler jobs delete pan-test-app-stage-api-send-reminders-scheduler --project=google-project-id --location=europe-west6
1277
+ - gcloud run jobs executions list --project=google-project-id --region=europe-west6 --job pan-test-app-stage-api-migration --format="value(name)" | xargs -I {} gcloud run jobs executions delete {} --quiet --project=google-project-id --region=europe-west6
1278
+ - gcloud run jobs delete pan-test-app-stage-api-migration --project=google-project-id --region=europe-west6
1279
+ - gcloud run jobs executions list --project=google-project-id --region=europe-west6 --job pan-test-app-stage-api-send-reminders --format="value(name)" | xargs -I {} gcloud run jobs executions delete {} --quiet --project=google-project-id --region=europe-west6
1280
+ - gcloud run jobs delete pan-test-app-stage-api-send-reminders --project=google-project-id --region=europe-west6
1281
+ - gcloud artifacts docker images delete europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/stage/api --quiet --delete-tags
1282
+ - gcloud artifacts docker images list europe-west6-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-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api@$version --quiet --delete-tags; done
1283
+ - echo 'Disabling component in Dependency Track'
1284
+ - /dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" disable "pan-test-app/api" "$CI_ENVIRONMENT_URL" || true
1285
+ - set -e
1286
+ environment:
1287
+ name: stage/api
1288
+ action: stop
1289
+ rules:
1290
+ - if: $CI_COMMIT_BRANCH =~ /^[0-9]+\\.([0-9]+|x)\\.x$/
1291
+ when: on_success
1292
+ - when: manual
1293
+ if: $CI_COMMIT_TAG
1294
+ needs: []
1295
+ retry: *a1
1296
+ interruptible: true
1297
+ allow_failure: true
1298
+ 'api ๐Ÿ”จ app | prod ':
1299
+ stage: build
1300
+ image: path/to/docker/jobs-default:the-version
1301
+ variables:
1302
+ KUBERNETES_CPU_REQUEST: '0.45'
1303
+ KUBERNETES_MEMORY_REQUEST: 1Gi
1304
+ KUBERNETES_MEMORY_LIMIT: 4Gi
1305
+ script:
1306
+ - collapseable_section_start "injectvars" "Injecting variables"
1307
+ - export ENV_SHORT="prod"
1308
+ - export APP_DIR="api"
1309
+ - export ENV_TYPE="prod"
1310
+ - export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"
1311
+ - export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"
1312
+ - 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")"
1313
+ - export HOSTNAME="$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1314
+ - export ROOT_URL="https://$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1315
+ - export HOSTNAME_INTERNAL="$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1316
+ - export ROOT_URL_INTERNAL="https://$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1317
+ - export CLOUD_SQL_INSTANCE_CONNECTION_NAME="projectId:region:instancename"
1318
+ - export DB_NAME="pan-test-app-prod-api"
1319
+ - export DB_USER="my-user"
1320
+ - export DB_PASSWORD="$CL_prod_api_DB_PASSWORD"
1321
+ - export DATABASE_URL="postgresql://$DB_USER:$DB_PASSWORD@localhost/$DB_NAME?host=/cloudsql/$CLOUD_SQL_INSTANCE_CONNECTION_NAME"
1322
+ - export DATABASE_JDBC_URL="jdbc:postgresql:///$DB_NAME?cloudSqlInstance=$CLOUD_SQL_INSTANCE_CONNECTION_NAME&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=$DB_USER&password=$DB_PASSWORD"
1323
+ - export CLOUD_RUN_JOB_TRIGGER_URL_migration="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-prod-api-migration:run"
1324
+ - export CLOUD_RUN_JOB_TRIGGER_URL_send_reminders="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-prod-api-send-reminders:run"
1325
+ - export DEPLOY_CLOUD_RUN_PROJECT_ID="google-project-id"
1326
+ - export DEPLOY_CLOUD_RUN_REGION="europe-west6"
1327
+ - export GCLOUD_DEPLOY_credentialsKey="$CL_prod_api_GCLOUD_DEPLOY_credentialsKey"
1328
+ - export GCLOUD_RUN_canonicalHostSuffix="$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix"
1329
+ - 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\\",\\"CLOUD_SQL_INSTANCE_CONNECTION_NAME\\",\\"DB_NAME\\",\\"DB_USER\\",\\"DB_PASSWORD\\",\\"DATABASE_URL\\",\\"DATABASE_JDBC_URL\\",\\"CLOUD_RUN_JOB_TRIGGER_URL_migration\\",\\"CLOUD_RUN_JOB_TRIGGER_URL_send_reminders\\",\\"DEPLOY_CLOUD_RUN_PROJECT_ID\\",\\"DEPLOY_CLOUD_RUN_REGION\\",\\"GCLOUD_DEPLOY_credentialsKey\\",\\"GCLOUD_RUN_canonicalHostSuffix\\"]"
1330
+ - collapseable_section_end "injectvars"
1331
+ - collapseable_section_start "write-dotenv-api" "write dot env for api"
1332
+ - |-
1333
+ cat <<EOF > api/.env
1334
+ ENV_SHORT=prod
1335
+ APP_DIR=api
1336
+ ENV_TYPE=prod
1337
+ HOSTNAME=$(printf %s "$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
1338
+ ROOT_URL=$(printf %s "https://$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
1339
+ HOSTNAME_INTERNAL=$(printf %s "$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
1340
+ ROOT_URL_INTERNAL=$(printf %s "https://$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | escapeForDotEnv)
1341
+ CLOUD_SQL_INSTANCE_CONNECTION_NAME=projectId:region:instancename
1342
+ DB_NAME=pan-test-app-prod-api
1343
+ DB_USER=my-user
1344
+ DB_PASSWORD=$(printf %s "$CL_prod_api_DB_PASSWORD" | escapeForDotEnv)
1345
+ DATABASE_URL=postgresql://$DB_USER:$DB_PASSWORD@localhost/$DB_NAME?host=/cloudsql/$CLOUD_SQL_INSTANCE_CONNECTION_NAME
1346
+ DATABASE_JDBC_URL=jdbc:postgresql:///$DB_NAME?cloudSqlInstance=$CLOUD_SQL_INSTANCE_CONNECTION_NAME&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=$DB_USER&password=$DB_PASSWORD
1347
+ CLOUD_RUN_JOB_TRIGGER_URL_migration=https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-prod-api-migration:run
1348
+ CLOUD_RUN_JOB_TRIGGER_URL_send_reminders=https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-prod-api-send-reminders:run
1349
+ DEPLOY_CLOUD_RUN_PROJECT_ID=google-project-id
1350
+ DEPLOY_CLOUD_RUN_REGION=europe-west6
1351
+ GCLOUD_DEPLOY_credentialsKey=$(printf %s "$CL_prod_api_GCLOUD_DEPLOY_credentialsKey" | escapeForDotEnv)
1352
+ GCLOUD_RUN_canonicalHostSuffix=$(printf %s "$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | escapeForDotEnv)
1353
+ _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","CLOUD_SQL_INSTANCE_CONNECTION_NAME","DB_NAME","DB_USER","DB_PASSWORD","DATABASE_URL","DATABASE_JDBC_URL","CLOUD_RUN_JOB_TRIGGER_URL_migration","CLOUD_RUN_JOB_TRIGGER_URL_send_reminders","DEPLOY_CLOUD_RUN_PROJECT_ID","DEPLOY_CLOUD_RUN_REGION","GCLOUD_DEPLOY_credentialsKey","GCLOUD_RUN_canonicalHostSuffix"]
1354
+ EOF
1355
+ - collapseable_section_end "write-dotenv-api"
1356
+ - echo '{"id":"$(git describe --tags 2>/dev/null || git rev-parse HEAD)","time":"$CI_JOB_STARTED_AT"}' > api/__build_info.json
1357
+ - collapseable_section_start "nodeinstall" "Ensure node version"
1358
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
1359
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
1360
+ - collapseable_section_end "nodeinstall"
1361
+ - cd api
1362
+ - collapseable_section_start "nodeinstall" "Ensure node version"
1363
+ - if [ -f ~/.nvm/nvm.sh ]; then source ~/.nvm/nvm.sh; fi
1364
+ - if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi
1365
+ - collapseable_section_end "nodeinstall"
1366
+ - collapseable_section_start "yarninstall" "Yarn install"
1367
+ - yarn install --immutable
1368
+ - collapseable_section_end "yarninstall"
1369
+ - yarn build
1370
+ cache:
1371
+ - key: api-yarn
1372
+ policy: pull-push
1373
+ paths:
1374
+ - api/.yarn
1375
+ - key: api-node-modules
1376
+ policy: pull-push
1377
+ paths:
1378
+ - api/node_modules
1379
+ artifacts:
1380
+ paths:
1381
+ - api/__build_info.json
1382
+ - api/.next
1383
+ - api/dist
1384
+ exclude:
1385
+ - api/.env
1386
+ expire_in: 1 day
1387
+ when: always
1388
+ reports: {}
1389
+ rules:
1390
+ - if: $CI_COMMIT_TAG
1391
+ needs: []
1392
+ retry: *a1
1393
+ interruptible: true
1394
+ 'api ๐Ÿ”จ docker | prod ':
1395
+ stage: build
1396
+ image: path/to/docker/docker-build:the-version
1397
+ services:
1398
+ - name: docker:24.0.6-dind
1399
+ command:
1400
+ - --tls=false
1401
+ - --registry-mirror=https://mirror.gcr.io
1402
+ variables:
1403
+ DOCKER_HOST: tcp://0.0.0.0:2375
1404
+ DOCKER_TLS_CERTDIR: ''
1405
+ DOCKER_DRIVER: overlay2
1406
+ DOCKER_BUILDKIT: '1'
1407
+ KUBERNETES_CPU_REQUEST: '0.45'
1408
+ KUBERNETES_MEMORY_REQUEST: 1Gi
1409
+ KUBERNETES_MEMORY_LIMIT: 2Gi
1410
+ script:
1411
+ - collapseable_section_start "injectvars" "Injecting variables"
1412
+ - export APP_DIR="api"
1413
+ - export DOCKER_BUILD_CONTEXT="."
1414
+ - export DOCKER_REGISTRY="europe-west6-docker.pkg.dev"
1415
+ - export DOCKER_IMAGE="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/prod/api"
1416
+ - export DOCKER_CACHE_IMAGE="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api"
1417
+ - export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"
1418
+ - |-
1419
+ export DOCKER_COPY_AND_INSTALL_APP="COPY --chown=node:node $APP_DIR .
1420
+ RUN yarn plugin import workspace-tools
1421
+ RUN yarn workspaces focus --production && yarn rebuild"
1422
+ - |-
1423
+ export DOCKER_COPY_WORKSPACE_FILES="COPY --chown=node:node api/package.json /app/api/package.json
1424
+ COPY --chown=node:node api/yarn.lock /app/api/yarn.lock
1425
+ COPY --chown=node:node .yarnrc.yml /app/.yarnrc.yml
1426
+ COPY --chown=node:node .yarn /app/.yarn"
1427
+ - collapseable_section_end "injectvars"
1428
+ - ensureNodeDockerfile
1429
+ - collapseable_section_start "docker-login" "Docker Login"
1430
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_prod_api_GCLOUD_DEPLOY_credentialsKey")
1431
+ - gcloud auth configure-docker europe-west6-docker.pkg.dev
1432
+ - collapseable_section_end "docker-login"
1433
+ - collapseable_section_start "docker-build" "Docker build"
1434
+ - 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
1435
+ - collapseable_section_end "docker-build"
1436
+ - collapseable_section_start "docker-push" "Docker push and tag"
1437
+ - docker push $DOCKER_IMAGE:$DOCKER_IMAGE_TAG
1438
+ - docker tag $DOCKER_IMAGE:$DOCKER_IMAGE_TAG $DOCKER_CACHE_IMAGE
1439
+ - docker push $DOCKER_CACHE_IMAGE
1440
+ - collapseable_section_end "docker-push"
1441
+ cache:
1442
+ - key: api-yarn
1443
+ policy: pull
1444
+ paths:
1445
+ - api/.yarn
1446
+ rules:
1447
+ - if: $CI_COMMIT_TAG
1448
+ needs:
1449
+ - 'api ๐Ÿ”จ app | prod '
1450
+ retry: *a1
1451
+ interruptible: true
1452
+ 'api ๐Ÿงพ sbom | prod ':
1453
+ stage: build
1454
+ image: aquasec/trivy:0.38.3
1455
+ variables: {}
1456
+ script:
1457
+ - collapseable_section_start "injectvars" "Injecting variables"
1458
+ - collapseable_section_end "injectvars"
1459
+ - trivy fs --quiet --format cyclonedx --output "__sbom.json" api
1460
+ artifacts:
1461
+ paths:
1462
+ - __sbom.json
1463
+ rules:
1464
+ - if: $CI_COMMIT_TAG
1465
+ needs: []
1466
+ retry: *a1
1467
+ interruptible: true
1468
+ allow_failure: true
1469
+ 'api ๐Ÿš€ Deploy | prod ':
1470
+ stage: deploy prod
1471
+ image: path/to/docker/gcloud:the-version
1472
+ variables:
1473
+ KUBERNETES_CPU_REQUEST: '0.22'
1474
+ KUBERNETES_MEMORY_REQUEST: 200Mi
1475
+ KUBERNETES_MEMORY_LIMIT: 400Mi
1476
+ script:
1477
+ - collapseable_section_start "injectvars" "Injecting variables"
1478
+ - export ENV_SHORT="prod"
1479
+ - export APP_DIR="api"
1480
+ - export ENV_TYPE="prod"
1481
+ - export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"
1482
+ - export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"
1483
+ - 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")"
1484
+ - export HOSTNAME="$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1485
+ - export ROOT_URL="https://$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1486
+ - export HOSTNAME_INTERNAL="$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1487
+ - export ROOT_URL_INTERNAL="https://$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')"
1488
+ - export CLOUD_SQL_INSTANCE_CONNECTION_NAME="projectId:region:instancename"
1489
+ - export DB_NAME="pan-test-app-prod-api"
1490
+ - export DB_USER="my-user"
1491
+ - export DB_PASSWORD="$CL_prod_api_DB_PASSWORD"
1492
+ - export DATABASE_URL="postgresql://$DB_USER:$DB_PASSWORD@localhost/$DB_NAME?host=/cloudsql/$CLOUD_SQL_INSTANCE_CONNECTION_NAME"
1493
+ - export DATABASE_JDBC_URL="jdbc:postgresql:///$DB_NAME?cloudSqlInstance=$CLOUD_SQL_INSTANCE_CONNECTION_NAME&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=$DB_USER&password=$DB_PASSWORD"
1494
+ - export CLOUD_RUN_JOB_TRIGGER_URL_migration="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-prod-api-migration:run"
1495
+ - export CLOUD_RUN_JOB_TRIGGER_URL_send_reminders="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-prod-api-send-reminders:run"
1496
+ - export DEPLOY_CLOUD_RUN_PROJECT_ID="google-project-id"
1497
+ - export DEPLOY_CLOUD_RUN_REGION="europe-west6"
1498
+ - export GCLOUD_DEPLOY_credentialsKey="$CL_prod_api_GCLOUD_DEPLOY_credentialsKey"
1499
+ - export GCLOUD_RUN_canonicalHostSuffix="$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix"
1500
+ - 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\\",\\"CLOUD_SQL_INSTANCE_CONNECTION_NAME\\",\\"DB_NAME\\",\\"DB_USER\\",\\"DB_PASSWORD\\",\\"DATABASE_URL\\",\\"DATABASE_JDBC_URL\\",\\"CLOUD_RUN_JOB_TRIGGER_URL_migration\\",\\"CLOUD_RUN_JOB_TRIGGER_URL_send_reminders\\",\\"DEPLOY_CLOUD_RUN_PROJECT_ID\\",\\"DEPLOY_CLOUD_RUN_REGION\\",\\"GCLOUD_DEPLOY_credentialsKey\\",\\"GCLOUD_RUN_canonicalHostSuffix\\"]"
1501
+ - export DOCKER_REGISTRY="europe-west6-docker.pkg.dev"
1502
+ - export DOCKER_IMAGE="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/prod/api"
1503
+ - export DOCKER_CACHE_IMAGE="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api"
1504
+ - export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"
1505
+ - export CLOUDSDK_CORE_DISABLE_PROMPTS="1"
1506
+ - collapseable_section_end "injectvars"
1507
+ - collapseable_section_start "prepare" "Prepare..."
1508
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_prod_api_GCLOUD_DEPLOY_credentialsKey")
1509
+ - export GCLOUD_PROJECT_NUMBER=$(gcloud projects describe google-project-id --format="value(projectNumber)")
1510
+ - 'echo "GCLOUD_PROJECT_NUMBER: $GCLOUD_PROJECT_NUMBER"'
1511
+ - collapseable_section_end "prepare"
1512
+ - collapseable_section_start "writeenvvars" "Write env vars to file"
1513
+ - |
1514
+ cat > ____envvars.yaml <<EOF
1515
+ ENV_SHORT: |-
1516
+ prod
1517
+ APP_DIR: |-
1518
+ api
1519
+ ENV_TYPE: |-
1520
+ prod
1521
+ BUILD_INFO_BUILD_ID: |-
1522
+ $(printf %s "$(git describe --tags 2>/dev/null || git rev-parse HEAD)" | sed '1!s/^/ /')
1523
+ BUILD_INFO_BUILD_TIME: |-
1524
+ $(printf %s "$CI_JOB_STARTED_AT" | sed '1!s/^/ /')
1525
+ BUILD_INFO_CURRENT_VERSION: |-
1526
+ $(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/^/ /')
1527
+ HOSTNAME: |-
1528
+ $(printf %s "$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
1529
+ ROOT_URL: |-
1530
+ $(printf %s "https://$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
1531
+ HOSTNAME_INTERNAL: |-
1532
+ $(printf %s "$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
1533
+ ROOT_URL_INTERNAL: |-
1534
+ $(printf %s "https://$(printf %s "pan-test-app-prod-api-$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | awk '{print tolower($0)}')" | sed '1!s/^/ /')
1535
+ CLOUD_SQL_INSTANCE_CONNECTION_NAME: |-
1536
+ projectId:region:instancename
1537
+ DB_NAME: |-
1538
+ pan-test-app-prod-api
1539
+ DB_USER: |-
1540
+ my-user
1541
+ DB_PASSWORD: |-
1542
+ $(printf %s "$CL_prod_api_DB_PASSWORD" | sed '1!s/^/ /')
1543
+ DATABASE_URL: |-
1544
+ postgresql://$DB_USER:$DB_PASSWORD@localhost/$DB_NAME?host=/cloudsql/$CLOUD_SQL_INSTANCE_CONNECTION_NAME
1545
+ DATABASE_JDBC_URL: |-
1546
+ jdbc:postgresql:///$DB_NAME?cloudSqlInstance=$CLOUD_SQL_INSTANCE_CONNECTION_NAME&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=$DB_USER&password=$DB_PASSWORD
1547
+ CLOUD_RUN_JOB_TRIGGER_URL_migration: |-
1548
+ https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-prod-api-migration:run
1549
+ CLOUD_RUN_JOB_TRIGGER_URL_send_reminders: |-
1550
+ https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-prod-api-send-reminders:run
1551
+ DEPLOY_CLOUD_RUN_PROJECT_ID: |-
1552
+ google-project-id
1553
+ DEPLOY_CLOUD_RUN_REGION: |-
1554
+ europe-west6
1555
+ GCLOUD_RUN_canonicalHostSuffix: |-
1556
+ $(printf %s "$CL_prod_api_GCLOUD_RUN_canonicalHostSuffix" | sed '1!s/^/ /')
1557
+ _ALL_ENV_VAR_KEYS: |-
1558
+ ["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","CLOUD_SQL_INSTANCE_CONNECTION_NAME","DB_NAME","DB_USER","DB_PASSWORD","DATABASE_URL","DATABASE_JDBC_URL","CLOUD_RUN_JOB_TRIGGER_URL_migration","CLOUD_RUN_JOB_TRIGGER_URL_send_reminders","DEPLOY_CLOUD_RUN_PROJECT_ID","DEPLOY_CLOUD_RUN_REGION","GCLOUD_DEPLOY_credentialsKey","GCLOUD_RUN_canonicalHostSuffix"]
1559
+
1560
+ EOF
1561
+ - collapseable_section_end "writeenvvars"
1562
+ - collapseable_section_start "deploy" "Deploy to cloud run"
1563
+ - set +e
1564
+ - echo "ensuring Database..."
1565
+ - gcloud sql databases create pan-test-app-prod-api --instance=instancename --project projectId
1566
+ - set -e
1567
+ - |-
1568
+ exist_scheduler_names="$(
1569
+ gcloud scheduler jobs list --filter='httpTarget.uri ~ prod.*api' --format='value(name)' --limit=999 --location='europe-west6' --project='google-project-id'
1570
+ )"
1571
+ current_job_uri="https://europe-west6-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/google-project-id/jobs/pan-test-app-prod-api-send-reminders:run"
1572
+ current_scheduler_name="pan-test-app-prod-api-send-reminders-scheduler"
1573
+ if grep "$current_scheduler_name" <<<"$exist_scheduler_names" >/dev/null; then
1574
+ gcloud scheduler jobs update http "$current_scheduler_name" --project=google-project-id --location=europe-west6 --uri="$current_job_uri" --http-method=POST --oauth-service-account-email="$GCLOUD_PROJECT_NUMBER-compute@developer.gserviceaccount.com" --schedule="0 * * * *" --max-retry-attempts=0
1575
+ else
1576
+ gcloud scheduler jobs create http "$current_scheduler_name" --project=google-project-id --location=europe-west6 --uri="$current_job_uri" --http-method=POST --oauth-service-account-email="$GCLOUD_PROJECT_NUMBER-compute@developer.gserviceaccount.com" --schedule="0 * * * *" --max-retry-attempts=0
1577
+ fi
1578
+ - |-
1579
+ exist_job_names="$(
1580
+ gcloud run jobs list --filter='metadata.name ~ prod.*api' --format='value(name)' --limit=999 --project='google-project-id' --region='europe-west6'
1581
+ )"
1582
+ current_job_name="pan-test-app-prod-api-migration"
1583
+ if grep "$current_job_name" <<<"$exist_job_names" >/dev/null; then
1584
+ gcloud run jobs update "$current_job_name" --command="yarn,migrate" --labels="customer-name=pan,component-name=api,app-name=test-app,env-type=prod,env-name=prod,build-type=node,cloud-run-job-name=$current_job_name" --image="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/prod/api:$DOCKER_IMAGE_TAG" --project=google-project-id --region=europe-west6 --memory=512Mi --parallelism=1 --task-timeout=10m --env-vars-file=____envvars.yaml --max-retries=0 --set-cloudsql-instances=projectId:region:instancename
1585
+ else
1586
+ gcloud run jobs create "$current_job_name" --command="yarn,migrate" --labels="customer-name=pan,component-name=api,app-name=test-app,env-type=prod,env-name=prod,build-type=node,cloud-run-job-name=$current_job_name" --image="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/prod/api:$DOCKER_IMAGE_TAG" --project=google-project-id --region=europe-west6 --memory=512Mi --parallelism=1 --task-timeout=10m --env-vars-file=____envvars.yaml --max-retries=0 --set-cloudsql-instances=projectId:region:instancename
1587
+ fi
1588
+ - |-
1589
+ current_job_name="pan-test-app-prod-api-send-reminders"
1590
+ if grep "$current_job_name" <<<"$exist_job_names" >/dev/null; then
1591
+ gcloud run jobs update "$current_job_name" --command="yarn,job:send-reminders" --labels="customer-name=pan,component-name=api,app-name=test-app,env-type=prod,env-name=prod,build-type=node,cloud-run-job-name=$current_job_name" --image="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/prod/api:$DOCKER_IMAGE_TAG" --project=google-project-id --region=europe-west6 --memory=512Mi --parallelism=1 --task-timeout=15m --env-vars-file=____envvars.yaml --max-retries=0 --set-cloudsql-instances=projectId:region:instancename
1592
+ else
1593
+ gcloud run jobs create "$current_job_name" --command="yarn,job:send-reminders" --labels="customer-name=pan,component-name=api,app-name=test-app,env-type=prod,env-name=prod,build-type=node,cloud-run-job-name=$current_job_name" --image="europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/prod/api:$DOCKER_IMAGE_TAG" --project=google-project-id --region=europe-west6 --memory=512Mi --parallelism=1 --task-timeout=15m --env-vars-file=____envvars.yaml --max-retries=0 --set-cloudsql-instances=projectId:region:instancename
1594
+ fi
1595
+ - gcloud run jobs execute pan-test-app-prod-api-migration --project=google-project-id --region=europe-west6 --wait
1596
+ - gcloud run deploy pan-test-app-prod-api --command="yarn,start" --image=europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/prod/api:$DOCKER_IMAGE_TAG --project=google-project-id --region=europe-west6 --set-cloudsql-instances=projectId:region:instancename --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=5 --cpu-throttling --allow-unauthenticated --ingress=all --cpu-boost
1597
+ - collapseable_section_end "deploy"
1598
+ - collapseable_section_start "cleanup" "Cleanup"
1599
+ - gcloud run revisions list --project=google-project-id --region=europe-west6 --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-west6 --quiet $revisionname ; done
1600
+ - gcloud artifacts docker images list europe-west6-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-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/prod/api@$version --quiet --delete-tags; done
1601
+ - gcloud artifacts docker images list europe-west6-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-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api@$version --quiet --delete-tags; done
1602
+ - collapseable_section_end "cleanup"
1603
+ - echo 'Uploading SBOM to Dependency Track'
1604
+ - /dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" upload "pan-test-app/api" "$ROOT_URL" "__sbom.json" vex.json || true
1605
+ - echo "CL_GITLAB_ENVIRONMENT_URL=$ROOT_URL" >> gitlab_environment.env
1606
+ environment:
1607
+ name: prod/api
1608
+ url: $CL_GITLAB_ENVIRONMENT_URL
1609
+ on_stop: 'api ๐Ÿ›‘ Stop โš ๏ธ | prod '
1610
+ artifacts:
1611
+ reports:
1612
+ dotenv: gitlab_environment.env
1613
+ rules:
1614
+ - when: manual
1615
+ if: $CI_COMMIT_TAG
1616
+ needs:
1617
+ - job: 'api ๐Ÿ”จ app | prod '
1618
+ artifacts: false
1619
+ - job: 'api ๐Ÿ”จ docker | prod '
1620
+ artifacts: false
1621
+ - job: 'api ๐Ÿงพ sbom | prod '
1622
+ artifacts: true
1623
+ retry: *a1
1624
+ interruptible: true
1625
+ allow_failure: true
1626
+ 'api ๐Ÿ›‘ Stop โš ๏ธ | prod ':
1627
+ stage: stop prod
1628
+ image: path/to/docker/gcloud:the-version
1629
+ variables:
1630
+ KUBERNETES_CPU_REQUEST: '0.22'
1631
+ KUBERNETES_MEMORY_REQUEST: 200Mi
1632
+ KUBERNETES_MEMORY_LIMIT: 400Mi
1633
+ GIT_STRATEGY: none
1634
+ script:
1635
+ - collapseable_section_start "injectvars" "Injecting variables"
1636
+ - export CLOUDSDK_CORE_DISABLE_PROMPTS="1"
1637
+ - collapseable_section_end "injectvars"
1638
+ - set +e
1639
+ - gcloud auth activate-service-account --key-file=<(echo "$CL_prod_api_GCLOUD_DEPLOY_credentialsKey")
1640
+ - gcloud run services delete pan-test-app-prod-api --project=google-project-id --region=europe-west6
1641
+ - gcloud scheduler jobs delete pan-test-app-prod-api-send-reminders-scheduler --project=google-project-id --location=europe-west6
1642
+ - gcloud run jobs executions list --project=google-project-id --region=europe-west6 --job pan-test-app-prod-api-migration --format="value(name)" | xargs -I {} gcloud run jobs executions delete {} --quiet --project=google-project-id --region=europe-west6
1643
+ - gcloud run jobs delete pan-test-app-prod-api-migration --project=google-project-id --region=europe-west6
1644
+ - gcloud run jobs executions list --project=google-project-id --region=europe-west6 --job pan-test-app-prod-api-send-reminders --format="value(name)" | xargs -I {} gcloud run jobs executions delete {} --quiet --project=google-project-id --region=europe-west6
1645
+ - gcloud run jobs delete pan-test-app-prod-api-send-reminders --project=google-project-id --region=europe-west6
1646
+ - gcloud artifacts docker images delete europe-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/prod/api --quiet --delete-tags
1647
+ - gcloud artifacts docker images list europe-west6-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-west6-docker.pkg.dev/google-project-id/catladder-deploy/pan-test-app/caches/api@$version --quiet --delete-tags; done
1648
+ - echo 'Disabling component in Dependency Track'
1649
+ - /dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" disable "pan-test-app/api" "$CI_ENVIRONMENT_URL" || true
1650
+ - set -e
1651
+ environment:
1652
+ name: prod/api
1653
+ action: stop
1654
+ rules:
1655
+ - if: $CI_COMMIT_BRANCH =~ /^[0-9]+\\.([0-9]+|x)\\.x$/
1656
+ when: on_success
1657
+ - when: manual
1658
+ if: $CI_COMMIT_TAG
1659
+ needs: []
1660
+ retry: *a1
1661
+ interruptible: true
1662
+ allow_failure: true
1663
+ create release:
1664
+ stage: release
1665
+ image: path/to/docker/semantic-release:the-version
1666
+ script:
1667
+ - semanticRelease
1668
+ - echo '๐Ÿ‘‰ The project access token might be invald - run \`project-renew-token\` in catladder CLI to fix.'
1669
+ rules:
1670
+ - &a2
1671
+ if: $CI_COMMIT_MESSAGE =~ /^chore\\(release\\).*/
1672
+ when: never
1673
+ - &a3
1674
+ if: $CI_PIPELINE_SOURCE == "schedule"
1675
+ when: never
1676
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $AUTO_RELEASE == "true"
1677
+ when: on_success
1678
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
1679
+ when: manual
1680
+ - if: $CI_COMMIT_BRANCH =~ /^[0-9]+.([0-9]+|x).x$/
1681
+ when: manual
1682
+ โš ๏ธ force create release:
1683
+ stage: release
1684
+ image: path/to/docker/semantic-release:the-version
1685
+ script:
1686
+ - semanticRelease
1687
+ - echo '๐Ÿ‘‰ The project access token might be invald - run \`project-renew-token\` in catladder CLI to fix.'
1688
+ rules:
1689
+ - *a2
1690
+ - *a3
1691
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
1692
+ when: manual
1693
+ - if: $CI_COMMIT_BRANCH =~ /^[0-9]+.([0-9]+|x).x$/
1694
+ when: manual
1695
+ needs: []
1696
+ "
1697
+ `;