@catladder/pipeline 1.159.1 → 1.161.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 (109) hide show
  1. package/dist/bundles/catladder-gitlab/index.js +2 -2
  2. package/dist/constants.js +1 -1
  3. package/dist/tsconfig.tsbuildinfo +1 -1
  4. package/examples/.test-gen-ignore +1 -0
  5. package/examples/__snapshots__/{cloud-run-memory-limit.ts.snap → cloud-run-memory-limit.test.ts.snap} +1 -1
  6. package/examples/__snapshots__/{cloud-run-meteor-with-worker.ts.snap → cloud-run-meteor-with-worker.test.ts.snap} +1 -1
  7. package/examples/__snapshots__/{cloud-run-no-cpu-throttling.ts.snap → cloud-run-no-cpu-throttling.test.ts.snap} +1 -1
  8. package/examples/__snapshots__/{cloud-run-no-service.ts.snap → cloud-run-no-service.test.ts.snap} +1 -1
  9. package/examples/__snapshots__/{cloud-run-non-public.ts.snap → cloud-run-non-public.test.ts.snap} +1 -1
  10. package/examples/__snapshots__/{cloud-run-post-stop-job.ts.snap → cloud-run-post-stop-job.test.ts.snap} +1 -1
  11. package/examples/__snapshots__/{cloud-run-service-gen2.ts.snap → cloud-run-service-gen2.test.ts.snap} +1 -1
  12. package/examples/__snapshots__/{cloud-run-service-increase-timout.ts.snap → cloud-run-service-increase-timout.test.ts.snap} +1 -1
  13. package/examples/__snapshots__/{cloud-run-service-with-volumes.ts.snap → cloud-run-service-with-volumes.test.ts.snap} +1 -1
  14. package/examples/__snapshots__/{cloud-run-storybook.ts.snap → cloud-run-storybook.test.ts.snap} +1 -1
  15. package/examples/__snapshots__/{cloud-run-with-ngnix.ts.snap → cloud-run-with-ngnix.test.ts.snap} +1 -1
  16. package/examples/__snapshots__/{cloud-run-with-sql-reuse-db.ts.snap → cloud-run-with-sql-reuse-db.test.ts.snap} +1 -1
  17. package/examples/__snapshots__/{cloud-run-with-sql.ts.snap → cloud-run-with-sql.test.ts.snap} +1 -1
  18. package/examples/__snapshots__/{cloud-run-with-worker.ts.snap → cloud-run-with-worker.test.ts.snap} +1 -1
  19. package/examples/__snapshots__/{custom-build-job-with-tests.ts.snap → custom-build-job-with-tests.test.ts.snap} +1 -1
  20. package/examples/__snapshots__/{custom-build-job.ts.snap → custom-build-job.test.ts.snap} +1 -1
  21. package/examples/__snapshots__/{custom-deploy.ts.snap → custom-deploy.test.ts.snap} +1 -1
  22. package/examples/__snapshots__/{custom-envs.ts.snap → custom-envs.test.ts.snap} +1 -1
  23. package/examples/__snapshots__/{custom-sbom-java.ts.snap → custom-sbom-java.test.ts.snap} +1 -1
  24. package/examples/__snapshots__/{git-submodule.ts.snap → git-submodule.test.ts.snap} +1 -1
  25. package/examples/__snapshots__/{kubernetes-application-customization.ts.snap → kubernetes-application-customization.test.ts.snap} +1 -1
  26. package/examples/__snapshots__/{kubernetes-with-cloud-sql-legacy.ts.snap → kubernetes-with-cloud-sql-legacy.test.ts.snap} +1 -1
  27. package/examples/__snapshots__/{kubernetes-with-cloud-sql.ts.snap → kubernetes-with-cloud-sql.test.ts.snap} +1 -1
  28. package/examples/__snapshots__/{kubernetes-with-jobs.ts.snap → kubernetes-with-jobs.test.ts.snap} +1 -1
  29. package/examples/__snapshots__/{kubernetes-with-mongodb.ts.snap → kubernetes-with-mongodb.test.ts.snap} +1 -1
  30. package/examples/__snapshots__/{local-dot-env.ts.snap → local-dot-env.test.ts.snap} +1 -1
  31. package/examples/__snapshots__/{meteor-kubernetes.ts.snap → meteor-kubernetes.test.ts.snap} +1 -1
  32. package/examples/__snapshots__/{multiline-var.ts.snap → multiline-var.test.ts.snap} +1 -1
  33. package/examples/__snapshots__/{native-app.ts.snap → native-app.test.ts.snap} +1 -1
  34. package/examples/__snapshots__/{node-build-with-custom-image.ts.snap → node-build-with-custom-image.test.ts.snap} +1 -1
  35. package/examples/__snapshots__/{node-build-with-docker-additions.ts.snap → node-build-with-docker-additions.test.ts.snap} +1 -1
  36. package/examples/__snapshots__/rails-k8s-with-worker-dockerfile.test.ts.snap +2011 -0
  37. package/examples/__snapshots__/rails-k8s-with-worker.test.ts.snap +1995 -0
  38. package/examples/__snapshots__/{wait-for-other-deploy.ts.snap → wait-for-other-deploy.test.ts.snap} +1 -1
  39. package/examples/cloud-run-memory-limit.test.ts +10 -0
  40. package/examples/cloud-run-memory-limit.ts +6 -4
  41. package/examples/cloud-run-meteor-with-worker.test.ts +10 -0
  42. package/examples/cloud-run-meteor-with-worker.ts +6 -4
  43. package/examples/cloud-run-no-cpu-throttling.test.ts +10 -0
  44. package/examples/cloud-run-no-cpu-throttling.ts +6 -4
  45. package/examples/cloud-run-no-service.test.ts +10 -0
  46. package/examples/cloud-run-no-service.ts +5 -4
  47. package/examples/cloud-run-non-public.test.ts +10 -0
  48. package/examples/cloud-run-non-public.ts +5 -4
  49. package/examples/cloud-run-post-stop-job.test.ts +10 -0
  50. package/examples/cloud-run-post-stop-job.ts +6 -4
  51. package/examples/cloud-run-service-gen2.test.ts +10 -0
  52. package/examples/cloud-run-service-gen2.ts +6 -4
  53. package/examples/cloud-run-service-increase-timout.test.ts +10 -0
  54. package/examples/cloud-run-service-increase-timout.ts +6 -4
  55. package/examples/cloud-run-service-with-volumes.test.ts +10 -0
  56. package/examples/cloud-run-service-with-volumes.ts +6 -4
  57. package/examples/cloud-run-storybook.test.ts +10 -0
  58. package/examples/cloud-run-storybook.ts +5 -4
  59. package/examples/cloud-run-with-ngnix.test.ts +10 -0
  60. package/examples/cloud-run-with-ngnix.ts +5 -4
  61. package/examples/cloud-run-with-sql-reuse-db.test.ts +10 -0
  62. package/examples/cloud-run-with-sql-reuse-db.ts +5 -4
  63. package/examples/cloud-run-with-sql.test.ts +10 -0
  64. package/examples/cloud-run-with-sql.ts +6 -4
  65. package/examples/cloud-run-with-worker.test.ts +10 -0
  66. package/examples/cloud-run-with-worker.ts +6 -4
  67. package/examples/custom-build-job-with-tests.test.ts +10 -0
  68. package/examples/custom-build-job-with-tests.ts +5 -4
  69. package/examples/custom-build-job.test.ts +10 -0
  70. package/examples/custom-build-job.ts +5 -4
  71. package/examples/custom-deploy.test.ts +10 -0
  72. package/examples/custom-deploy.ts +5 -4
  73. package/examples/custom-envs.test.ts +10 -0
  74. package/examples/custom-envs.ts +5 -4
  75. package/examples/custom-sbom-java.test.ts +10 -0
  76. package/examples/custom-sbom-java.ts +5 -4
  77. package/examples/git-submodule.test.ts +10 -0
  78. package/examples/git-submodule.ts +5 -4
  79. package/examples/kubernetes-application-customization.test.ts +10 -0
  80. package/examples/kubernetes-application-customization.ts +6 -4
  81. package/examples/kubernetes-with-cloud-sql-legacy.test.ts +10 -0
  82. package/examples/kubernetes-with-cloud-sql-legacy.ts +6 -4
  83. package/examples/kubernetes-with-cloud-sql.test.ts +10 -0
  84. package/examples/kubernetes-with-cloud-sql.ts +6 -4
  85. package/examples/kubernetes-with-jobs.test.ts +10 -0
  86. package/examples/kubernetes-with-jobs.ts +6 -4
  87. package/examples/kubernetes-with-mongodb.test.ts +10 -0
  88. package/examples/kubernetes-with-mongodb.ts +6 -4
  89. package/examples/local-dot-env.test.ts +10 -0
  90. package/examples/local-dot-env.ts +6 -4
  91. package/examples/meteor-kubernetes.test.ts +10 -0
  92. package/examples/meteor-kubernetes.ts +3 -4
  93. package/examples/multiline-var.test.ts +10 -0
  94. package/examples/multiline-var.ts +5 -4
  95. package/examples/native-app.test.ts +10 -0
  96. package/examples/native-app.ts +6 -4
  97. package/examples/node-build-with-custom-image.test.ts +10 -0
  98. package/examples/node-build-with-custom-image.ts +5 -4
  99. package/examples/node-build-with-docker-additions.test.ts +10 -0
  100. package/examples/node-build-with-docker-additions.ts +5 -4
  101. package/examples/rails-k8s-with-worker-dockerfile.test.ts +9 -0
  102. package/examples/rails-k8s-with-worker.test.ts +10 -0
  103. package/examples/rails-k8s-with-worker.ts +4 -10
  104. package/examples/wait-for-other-deploy.test.ts +10 -0
  105. package/examples/wait-for-other-deploy.ts +5 -4
  106. package/package.json +5 -2
  107. package/scripts/generate-examples-test.ts +91 -0
  108. package/scripts/tsconfig.json +7 -0
  109. package/examples/__snapshots__/rails-k8s-with-worker.ts.snap +0 -4005
@@ -0,0 +1,2011 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`matches snapshot with a Dockerfile 1`] = `
4
+ {
5
+ "mainBranch": {
6
+ "image": "path/to/docker/jobs-default:the-version",
7
+ "jobs": {
8
+ "app ↩️ Rollback ⚠️ | dev ": {
9
+ "allow_failure": true,
10
+ "artifacts": {
11
+ "reports": {
12
+ "dotenv": "gitlab_environment.env",
13
+ },
14
+ },
15
+ "environment": {
16
+ "action": "access",
17
+ "name": "dev/app",
18
+ "url": "$CL_GITLAB_ENVIRONMENT_URL",
19
+ },
20
+ "image": "path/to/docker/kubernetes:the-version",
21
+ "interruptible": true,
22
+ "needs": [],
23
+ "retry": {
24
+ "max": 2,
25
+ "when": [
26
+ "runner_system_failure",
27
+ "stuck_or_timeout_failure",
28
+ ],
29
+ },
30
+ "rules": [
31
+ {
32
+ "when": "manual",
33
+ },
34
+ ],
35
+ "script": [
36
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
37
+ "export ENV_SHORT="dev"",
38
+ "export APP_DIR="."",
39
+ "export ENV_TYPE="dev"",
40
+ "export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
41
+ "export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"",
42
+ "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")"",
43
+ "export ROOT_URL="https://app.dev.test-app.pan.panter.cloud"",
44
+ "export HOST_INTERNAL="app.dev.test-app.pan.panter.cloud"",
45
+ "export HOST_CANONICAL="app.dev.test-app.pan.panter.cloud"",
46
+ "export ROOT_URL_INTERNAL="https://app.dev.test-app.pan.panter.cloud"",
47
+ "export KUBE_NAMESPACE="pan-test-app-dev"",
48
+ "export KUBE_APP_NAME="app"",
49
+ "export KUBE_APP_NAME_PREFIX=""",
50
+ "export SECRET_KEY_BASE="$CL_dev_app_SECRET_KEY_BASE"",
51
+ "export POSTGRESQL_PASSWORD="$CL_dev_app_POSTGRESQL_PASSWORD"",
52
+ "export cloudsqlProxyCredentials="$CL_dev_app_cloudsqlProxyCredentials"",
53
+ "export RAILS_ENV="production"",
54
+ "export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"ROOT_URL\\",\\"HOST_INTERNAL\\",\\"HOST_CANONICAL\\",\\"ROOT_URL_INTERNAL\\",\\"KUBE_NAMESPACE\\",\\"KUBE_APP_NAME\\",\\"KUBE_APP_NAME_PREFIX\\",\\"SECRET_KEY_BASE\\",\\"POSTGRESQL_PASSWORD\\",\\"cloudsqlProxyCredentials\\",\\"RAILS_ENV\\"]"",
55
+ "export RELEASE_NAME="pan-test-app-dev-app"",
56
+ "export HELM_EXPERIMENTAL_OCI="1"",
57
+ "export KUBE_DOCKER_IMAGE_PULL_SECRET="gitlab-registry-app"",
58
+ "export HELM_GITLAB_CHART_NAME="/helm-charts/the-panter-chart"",
59
+ "export HELM_ARGS=""",
60
+ "export COMPONENT_NAME="app"",
61
+ "export BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
62
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
63
+ "kubectl config set-cluster "kube-pan-test-app-dev-app" --server="$CL_dev_app_KUBE_URL" --certificate-authority <(echo $CL_dev_app_KUBE_CA_PEM | base64 -d) --embed-certs=true",
64
+ "kubectl config set-credentials "kube-pan-test-app-dev-app" --token="$CL_dev_app_KUBE_TOKEN"",
65
+ "kubectl config set-context "kube-pan-test-app-dev-app" --cluster="kube-pan-test-app-dev-app" --user="kube-pan-test-app-dev-app" --namespace="pan-test-app-dev"",
66
+ "kubectl config use-context "kube-pan-test-app-dev-app"",
67
+ "kubernetesRollback",
68
+ "echo "CL_GITLAB_ENVIRONMENT_URL=https://app.dev.test-app.pan.panter.cloud" >> gitlab_environment.env",
69
+ ],
70
+ "stage": "rollback dev",
71
+ "variables": {
72
+ "GIT_STRATEGY": "none",
73
+ "KUBERNETES_CPU_REQUEST": "0.22",
74
+ "KUBERNETES_MEMORY_LIMIT": "400Mi",
75
+ "KUBERNETES_MEMORY_REQUEST": "200Mi",
76
+ },
77
+ },
78
+ "app 👮 lint": {
79
+ "cache": {
80
+ "key": {
81
+ "files": [
82
+ "Gemfile.lock",
83
+ ],
84
+ "prefix": "$CI_JOB_IMAGE",
85
+ },
86
+ "paths": [
87
+ "tmp/cache",
88
+ ],
89
+ },
90
+ "image": "ruby:3.2.1",
91
+ "interruptible": true,
92
+ "needs": [],
93
+ "retry": {
94
+ "max": 2,
95
+ "when": [
96
+ "runner_system_failure",
97
+ "stuck_or_timeout_failure",
98
+ ],
99
+ },
100
+ "script": [
101
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
102
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
103
+ "cd .",
104
+ "bundle config set path 'tmp/cache'",
105
+ "bundle install -j $(nproc)",
106
+ "bundle exec rubocop",
107
+ ],
108
+ "stage": "test",
109
+ "variables": {},
110
+ },
111
+ "app 🔨 docker | dev ": {
112
+ "image": "path/to/docker/docker-build:the-version",
113
+ "interruptible": true,
114
+ "needs": [],
115
+ "retry": {
116
+ "max": 2,
117
+ "when": [
118
+ "runner_system_failure",
119
+ "stuck_or_timeout_failure",
120
+ ],
121
+ },
122
+ "script": [
123
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
124
+ "export APP_DIR="."",
125
+ "export DOCKER_BUILD_CONTEXT="."",
126
+ "export DOCKER_REGISTRY="$CI_REGISTRY"",
127
+ "export DOCKER_CACHE_IMAGE="$CI_REGISTRY_IMAGE/caches/app"",
128
+ "export DOCKER_IMAGE_NAME="dev/app"",
129
+ "export DOCKER_IMAGE="$CI_REGISTRY_IMAGE/$DOCKER_IMAGE_NAME"",
130
+ "export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"",
131
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
132
+ "echo -e "\\e[0Ksection_start:$(date +%s):docker-login[collapsed=true]\\r\\e[0KDocker Login"",
133
+ "docker login --username gitlab-ci-token --password $CI_JOB_TOKEN $CI_REGISTRY",
134
+ "echo -e "\\e[0Ksection_end:$(date +%s):docker-login\\r\\e[0K"",
135
+ "echo -e "\\e[0Ksection_start:$(date +%s):docker-build[collapsed=true]\\r\\e[0KDocker build"",
136
+ "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",
137
+ "echo -e "\\e[0Ksection_end:$(date +%s):docker-build\\r\\e[0K"",
138
+ "echo -e "\\e[0Ksection_start:$(date +%s):docker-push[collapsed=true]\\r\\e[0KDocker push and tag"",
139
+ "docker push $DOCKER_IMAGE:$DOCKER_IMAGE_TAG",
140
+ "docker tag $DOCKER_IMAGE:$DOCKER_IMAGE_TAG $DOCKER_CACHE_IMAGE",
141
+ "docker push $DOCKER_CACHE_IMAGE",
142
+ "echo -e "\\e[0Ksection_end:$(date +%s):docker-push\\r\\e[0K"",
143
+ ],
144
+ "services": [
145
+ {
146
+ "command": [
147
+ "--tls=false",
148
+ ],
149
+ "name": "docker:24.0.6-dind",
150
+ },
151
+ ],
152
+ "stage": "build",
153
+ "variables": {
154
+ "DOCKER_BUILDKIT": "1",
155
+ "DOCKER_DRIVER": "overlay2",
156
+ "DOCKER_HOST": "tcp://0.0.0.0:2375",
157
+ "DOCKER_TLS_CERTDIR": "",
158
+ "KUBERNETES_CPU_REQUEST": "0.45",
159
+ "KUBERNETES_MEMORY_LIMIT": "2Gi",
160
+ "KUBERNETES_MEMORY_REQUEST": "1Gi",
161
+ },
162
+ },
163
+ "app 🚀 Deploy | dev ": {
164
+ "allow_failure": false,
165
+ "artifacts": {
166
+ "reports": {
167
+ "dotenv": "gitlab_environment.env",
168
+ },
169
+ },
170
+ "environment": {
171
+ "auto_stop_in": "4 weeks",
172
+ "name": "dev/app",
173
+ "on_stop": "app 🛑 Stop ⚠️ | dev ",
174
+ "url": "$CL_GITLAB_ENVIRONMENT_URL",
175
+ },
176
+ "image": "path/to/docker/kubernetes:the-version",
177
+ "interruptible": true,
178
+ "needs": [
179
+ {
180
+ "artifacts": false,
181
+ "job": "app 👮 lint",
182
+ },
183
+ {
184
+ "artifacts": false,
185
+ "job": "app 🔨 docker | dev ",
186
+ },
187
+ {
188
+ "artifacts": false,
189
+ "job": "app 🧪 test",
190
+ },
191
+ {
192
+ "artifacts": true,
193
+ "job": "app 🧾 sbom | dev ",
194
+ },
195
+ {
196
+ "artifacts": false,
197
+ "job": "app 🛡 audit",
198
+ },
199
+ ],
200
+ "retry": {
201
+ "max": 2,
202
+ "when": [
203
+ "runner_system_failure",
204
+ "stuck_or_timeout_failure",
205
+ ],
206
+ },
207
+ "rules": [
208
+ {
209
+ "when": "on_success",
210
+ },
211
+ ],
212
+ "script": [
213
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
214
+ "export ENV_SHORT="dev"",
215
+ "export APP_DIR="."",
216
+ "export ENV_TYPE="dev"",
217
+ "export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
218
+ "export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"",
219
+ "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")"",
220
+ "export ROOT_URL="https://app.dev.test-app.pan.panter.cloud"",
221
+ "export HOST_INTERNAL="app.dev.test-app.pan.panter.cloud"",
222
+ "export HOST_CANONICAL="app.dev.test-app.pan.panter.cloud"",
223
+ "export ROOT_URL_INTERNAL="https://app.dev.test-app.pan.panter.cloud"",
224
+ "export KUBE_NAMESPACE="pan-test-app-dev"",
225
+ "export KUBE_APP_NAME="app"",
226
+ "export KUBE_APP_NAME_PREFIX=""",
227
+ "export SECRET_KEY_BASE="$CL_dev_app_SECRET_KEY_BASE"",
228
+ "export POSTGRESQL_PASSWORD="$CL_dev_app_POSTGRESQL_PASSWORD"",
229
+ "export cloudsqlProxyCredentials="$CL_dev_app_cloudsqlProxyCredentials"",
230
+ "export RAILS_ENV="production"",
231
+ "export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"ROOT_URL\\",\\"HOST_INTERNAL\\",\\"HOST_CANONICAL\\",\\"ROOT_URL_INTERNAL\\",\\"KUBE_NAMESPACE\\",\\"KUBE_APP_NAME\\",\\"KUBE_APP_NAME_PREFIX\\",\\"SECRET_KEY_BASE\\",\\"POSTGRESQL_PASSWORD\\",\\"cloudsqlProxyCredentials\\",\\"RAILS_ENV\\"]"",
232
+ "export DOCKER_REGISTRY="$CI_REGISTRY"",
233
+ "export DOCKER_CACHE_IMAGE="$CI_REGISTRY_IMAGE/caches/app"",
234
+ "export DOCKER_IMAGE_NAME="dev/app"",
235
+ "export DOCKER_IMAGE="$CI_REGISTRY_IMAGE/$DOCKER_IMAGE_NAME"",
236
+ "export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"",
237
+ "export RELEASE_NAME="pan-test-app-dev-app"",
238
+ "export HELM_EXPERIMENTAL_OCI="1"",
239
+ "export KUBE_DOCKER_IMAGE_PULL_SECRET="gitlab-registry-app"",
240
+ "export HELM_GITLAB_CHART_NAME="/helm-charts/the-panter-chart"",
241
+ "export HELM_ARGS=""",
242
+ "export COMPONENT_NAME="app"",
243
+ "export BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
244
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
245
+ "kubectl config set-cluster "kube-pan-test-app-dev-app" --server="$CL_dev_app_KUBE_URL" --certificate-authority <(echo $CL_dev_app_KUBE_CA_PEM | base64 -d) --embed-certs=true",
246
+ "kubectl config set-credentials "kube-pan-test-app-dev-app" --token="$CL_dev_app_KUBE_TOKEN"",
247
+ "kubectl config set-context "kube-pan-test-app-dev-app" --cluster="kube-pan-test-app-dev-app" --user="kube-pan-test-app-dev-app" --namespace="pan-test-app-dev"",
248
+ "kubectl config use-context "kube-pan-test-app-dev-app"",
249
+ "echo -e "\\e[0Ksection_start:$(date +%s):writeallvalues[collapsed=true]\\r\\e[0KWrite __all_values.yml for helm deployment"",
250
+ "cat > __all_values.yml <<EOF
251
+ env:
252
+ secret:
253
+ SECRET_KEY_BASE: |-
254
+ $(printf %s "$CL_dev_app_SECRET_KEY_BASE" | sed 's/^/ /')
255
+ POSTGRESQL_PASSWORD: |-
256
+ $(printf %s "$CL_dev_app_POSTGRESQL_PASSWORD" | sed 's/^/ /')
257
+ cloudsqlProxyCredentials: |-
258
+ $(printf %s "$CL_dev_app_cloudsqlProxyCredentials" | sed 's/^/ /')
259
+ public:
260
+ ENV_SHORT: |-
261
+ dev
262
+ APP_DIR: |-
263
+ .
264
+ ENV_TYPE: |-
265
+ dev
266
+ BUILD_INFO_BUILD_ID: |-
267
+ $(printf %s "$(git describe --tags 2>/dev/null || git rev-parse HEAD)" | sed 's/^/ /')
268
+ BUILD_INFO_BUILD_TIME: |-
269
+ $(printf %s "$CI_JOB_STARTED_AT" | sed 's/^/ /')
270
+ BUILD_INFO_CURRENT_VERSION: |-
271
+ $(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 's/^/ /')
272
+ ROOT_URL: |-
273
+ https://app.dev.test-app.pan.panter.cloud
274
+ HOST_INTERNAL: |-
275
+ app.dev.test-app.pan.panter.cloud
276
+ HOST_CANONICAL: |-
277
+ app.dev.test-app.pan.panter.cloud
278
+ ROOT_URL_INTERNAL: |-
279
+ https://app.dev.test-app.pan.panter.cloud
280
+ KUBE_NAMESPACE: |-
281
+ pan-test-app-dev
282
+ KUBE_APP_NAME: |-
283
+ app
284
+ KUBE_APP_NAME_PREFIX: ""
285
+ RAILS_ENV: |-
286
+ production
287
+ _ALL_ENV_VAR_KEYS: |-
288
+ ["ENV_SHORT","APP_DIR","ENV_TYPE","BUILD_INFO_BUILD_ID","BUILD_INFO_BUILD_TIME","BUILD_INFO_CURRENT_VERSION","ROOT_URL","HOST_INTERNAL","HOST_CANONICAL","ROOT_URL_INTERNAL","KUBE_NAMESPACE","KUBE_APP_NAME","KUBE_APP_NAME_PREFIX","SECRET_KEY_BASE","POSTGRESQL_PASSWORD","cloudsqlProxyCredentials","RAILS_ENV"]
289
+ application:
290
+ host: |-
291
+ app.dev.test-app.pan.panter.cloud
292
+ command: |-
293
+ /cnb/process/web
294
+ livenessProbe:
295
+ httpGet:
296
+ path: |-
297
+ __health
298
+ readinessProbe:
299
+ httpGet:
300
+ path: |-
301
+ __health
302
+ startupProbe:
303
+ httpGet:
304
+ path: |-
305
+ __health
306
+ worker:
307
+ enabled: true
308
+ command: |-
309
+ launcher bundle exec rake jobs:work
310
+ livenessProbe: false
311
+ cloudsql:
312
+ enabled: true
313
+ dbUser: |-
314
+ postgres
315
+ instanceConnectionName: |-
316
+ some-project-id:europe-west6:pan-test-app-dev
317
+ proxyCredentials: |-
318
+ $CL_dev_app_cloudsqlProxyCredentials
319
+ fullDbName: |-
320
+ app
321
+ projectId: |-
322
+ some-project-id
323
+ jobs:
324
+ db-migrate:
325
+ hook: |-
326
+ post-install,post-upgrade
327
+ command: |-
328
+ launcher bundle exec rake db:migrate
329
+
330
+ EOF
331
+ ",
332
+ "echo -e "\\e[0Ksection_end:$(date +%s):writeallvalues\\r\\e[0K"",
333
+ "kubernetesCreateSecret",
334
+ "kubernetesDeploy",
335
+ "echo 'Uploading SBOM to Dependency Track'",
336
+ "/dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" upload "pan-test-app/app" "https://app.dev.test-app.pan.panter.cloud" "__sbom.json" vex.json || true",
337
+ "echo deployment successful 😻",
338
+ "echo "CL_GITLAB_ENVIRONMENT_URL=https://app.dev.test-app.pan.panter.cloud" >> gitlab_environment.env",
339
+ ],
340
+ "stage": "deploy dev",
341
+ "variables": {
342
+ "KUBERNETES_CPU_REQUEST": "0.22",
343
+ "KUBERNETES_MEMORY_LIMIT": "400Mi",
344
+ "KUBERNETES_MEMORY_REQUEST": "200Mi",
345
+ },
346
+ },
347
+ "app 🛑 Stop ⚠️ | dev ": {
348
+ "allow_failure": true,
349
+ "artifacts": {
350
+ "reports": {
351
+ "dotenv": "gitlab_environment.env",
352
+ },
353
+ },
354
+ "environment": {
355
+ "action": "stop",
356
+ "name": "dev/app",
357
+ "url": "$CL_GITLAB_ENVIRONMENT_URL",
358
+ },
359
+ "image": "path/to/docker/kubernetes:the-version",
360
+ "interruptible": true,
361
+ "needs": [],
362
+ "retry": {
363
+ "max": 2,
364
+ "when": [
365
+ "runner_system_failure",
366
+ "stuck_or_timeout_failure",
367
+ ],
368
+ },
369
+ "rules": [
370
+ {
371
+ "if": "$CI_COMMIT_BRANCH =~ /^[0-9]+\\.([0-9]+|x)\\.x$/",
372
+ "when": "on_success",
373
+ },
374
+ {
375
+ "when": "manual",
376
+ },
377
+ ],
378
+ "script": [
379
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
380
+ "export ENV_SHORT="dev"",
381
+ "export APP_DIR="."",
382
+ "export ENV_TYPE="dev"",
383
+ "export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
384
+ "export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"",
385
+ "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")"",
386
+ "export ROOT_URL="https://app.dev.test-app.pan.panter.cloud"",
387
+ "export HOST_INTERNAL="app.dev.test-app.pan.panter.cloud"",
388
+ "export HOST_CANONICAL="app.dev.test-app.pan.panter.cloud"",
389
+ "export ROOT_URL_INTERNAL="https://app.dev.test-app.pan.panter.cloud"",
390
+ "export KUBE_NAMESPACE="pan-test-app-dev"",
391
+ "export KUBE_APP_NAME="app"",
392
+ "export KUBE_APP_NAME_PREFIX=""",
393
+ "export SECRET_KEY_BASE="$CL_dev_app_SECRET_KEY_BASE"",
394
+ "export POSTGRESQL_PASSWORD="$CL_dev_app_POSTGRESQL_PASSWORD"",
395
+ "export cloudsqlProxyCredentials="$CL_dev_app_cloudsqlProxyCredentials"",
396
+ "export RAILS_ENV="production"",
397
+ "export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"ROOT_URL\\",\\"HOST_INTERNAL\\",\\"HOST_CANONICAL\\",\\"ROOT_URL_INTERNAL\\",\\"KUBE_NAMESPACE\\",\\"KUBE_APP_NAME\\",\\"KUBE_APP_NAME_PREFIX\\",\\"SECRET_KEY_BASE\\",\\"POSTGRESQL_PASSWORD\\",\\"cloudsqlProxyCredentials\\",\\"RAILS_ENV\\"]"",
398
+ "export RELEASE_NAME="pan-test-app-dev-app"",
399
+ "export HELM_EXPERIMENTAL_OCI="1"",
400
+ "export KUBE_DOCKER_IMAGE_PULL_SECRET="gitlab-registry-app"",
401
+ "export HELM_GITLAB_CHART_NAME="/helm-charts/the-panter-chart"",
402
+ "export HELM_ARGS=""",
403
+ "export COMPONENT_NAME="app"",
404
+ "export BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
405
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
406
+ "kubectl config set-cluster "kube-pan-test-app-dev-app" --server="$CL_dev_app_KUBE_URL" --certificate-authority <(echo $CL_dev_app_KUBE_CA_PEM | base64 -d) --embed-certs=true",
407
+ "kubectl config set-credentials "kube-pan-test-app-dev-app" --token="$CL_dev_app_KUBE_TOKEN"",
408
+ "kubectl config set-context "kube-pan-test-app-dev-app" --cluster="kube-pan-test-app-dev-app" --user="kube-pan-test-app-dev-app" --namespace="pan-test-app-dev"",
409
+ "kubectl config use-context "kube-pan-test-app-dev-app"",
410
+ "kubernetesDelete",
411
+ "echo 'Disabling component in Dependency Track'",
412
+ "/dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" disable "pan-test-app/app" "https://app.dev.test-app.pan.panter.cloud" || true",
413
+ "echo "CL_GITLAB_ENVIRONMENT_URL=https://app.dev.test-app.pan.panter.cloud" >> gitlab_environment.env",
414
+ ],
415
+ "stage": "stop dev",
416
+ "variables": {
417
+ "GIT_STRATEGY": "none",
418
+ "KUBERNETES_CPU_REQUEST": "0.22",
419
+ "KUBERNETES_MEMORY_LIMIT": "400Mi",
420
+ "KUBERNETES_MEMORY_REQUEST": "200Mi",
421
+ },
422
+ },
423
+ "app 🛡 audit": {
424
+ "allow_failure": true,
425
+ "image": "ruby:3.2.1",
426
+ "interruptible": true,
427
+ "needs": [],
428
+ "retry": {
429
+ "max": 2,
430
+ "when": [
431
+ "runner_system_failure",
432
+ "stuck_or_timeout_failure",
433
+ ],
434
+ },
435
+ "script": [
436
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
437
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
438
+ "cd .",
439
+ "gem install bundler-audit",
440
+ "bundle audit check",
441
+ ],
442
+ "stage": "test",
443
+ "variables": {},
444
+ },
445
+ "app 🧪 test": {
446
+ "cache": {
447
+ "key": {
448
+ "files": [
449
+ "Gemfile.lock",
450
+ ],
451
+ "prefix": "$CI_JOB_IMAGE",
452
+ },
453
+ "paths": [
454
+ "tmp/cache",
455
+ ],
456
+ },
457
+ "image": "ruby:3.2.1",
458
+ "interruptible": true,
459
+ "needs": [],
460
+ "retry": {
461
+ "max": 2,
462
+ "when": [
463
+ "runner_system_failure",
464
+ "stuck_or_timeout_failure",
465
+ ],
466
+ },
467
+ "script": [
468
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
469
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
470
+ "cd .",
471
+ "bundle config set path 'tmp/cache'",
472
+ "bundle install -j $(nproc)",
473
+ "bundle exec rspec",
474
+ ],
475
+ "stage": "test",
476
+ "variables": {},
477
+ },
478
+ "app 🧾 sbom | dev ": {
479
+ "allow_failure": true,
480
+ "artifacts": {
481
+ "paths": [
482
+ "__sbom.json",
483
+ ],
484
+ },
485
+ "image": "aquasec/trivy:0.38.3",
486
+ "interruptible": true,
487
+ "needs": [],
488
+ "retry": {
489
+ "max": 2,
490
+ "when": [
491
+ "runner_system_failure",
492
+ "stuck_or_timeout_failure",
493
+ ],
494
+ },
495
+ "script": [
496
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
497
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
498
+ "trivy fs --quiet --format cyclonedx --output "__sbom.json" .",
499
+ ],
500
+ "stage": "build",
501
+ "variables": {},
502
+ },
503
+ },
504
+ "stages": [
505
+ "setup",
506
+ "setup dev",
507
+ "setup review",
508
+ "setup stage",
509
+ "setup prod",
510
+ "test",
511
+ "test dev",
512
+ "test review",
513
+ "test stage",
514
+ "test prod",
515
+ "build",
516
+ "build dev",
517
+ "build review",
518
+ "build stage",
519
+ "build prod",
520
+ "deploy",
521
+ "deploy dev",
522
+ "deploy review",
523
+ "deploy stage",
524
+ "deploy prod",
525
+ "verify",
526
+ "verify dev",
527
+ "verify review",
528
+ "verify stage",
529
+ "verify prod",
530
+ "rollback",
531
+ "rollback dev",
532
+ "rollback review",
533
+ "rollback stage",
534
+ "rollback prod",
535
+ "stop",
536
+ "stop dev",
537
+ "stop review",
538
+ "stop stage",
539
+ "stop prod",
540
+ ],
541
+ "variables": {
542
+ "ARTIFACT_COMPRESSION_LEVEL": "fast",
543
+ "CACHE_COMPRESSION_LEVEL": "fast",
544
+ "FF_USE_FASTZIP": "true",
545
+ "GIT_DEPTH": "1",
546
+ "TRANSFER_METER_FREQUENCY": "5s",
547
+ },
548
+ "workflow": {
549
+ "rules": [
550
+ {
551
+ "if": "$CI_COMMIT_TAG",
552
+ },
553
+ {
554
+ "if": "$CI_COMMIT_MESSAGE =~ /^chore\\(release\\).*/",
555
+ "when": "never",
556
+ },
557
+ {
558
+ "if": "$CI_PIPELINE_SOURCE == "schedule"",
559
+ "when": "never",
560
+ },
561
+ {
562
+ "if": "$CI_COMMIT_BRANCH =~ /^[0-9]+.([0-9]+|x).x$/",
563
+ },
564
+ {
565
+ "if": "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH",
566
+ },
567
+ {
568
+ "if": "$CI_MERGE_REQUEST_ID",
569
+ },
570
+ ],
571
+ },
572
+ },
573
+ "mr": {
574
+ "image": "path/to/docker/jobs-default:the-version",
575
+ "jobs": {
576
+ "app ↩️ Rollback ⚠️ | review ": {
577
+ "allow_failure": true,
578
+ "artifacts": {
579
+ "reports": {
580
+ "dotenv": "gitlab_environment.env",
581
+ },
582
+ },
583
+ "environment": {
584
+ "action": "access",
585
+ "name": "review/$CI_COMMIT_REF_NAME/app",
586
+ "url": "$CL_GITLAB_ENVIRONMENT_URL",
587
+ },
588
+ "image": "path/to/docker/kubernetes:the-version",
589
+ "interruptible": true,
590
+ "needs": [],
591
+ "retry": {
592
+ "max": 2,
593
+ "when": [
594
+ "runner_system_failure",
595
+ "stuck_or_timeout_failure",
596
+ ],
597
+ },
598
+ "rules": [
599
+ {
600
+ "when": "manual",
601
+ },
602
+ ],
603
+ "script": [
604
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
605
+ "export ENV_SHORT="review"",
606
+ "export APP_DIR="."",
607
+ "export ENV_TYPE="review"",
608
+ "export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
609
+ "export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"",
610
+ "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")"",
611
+ "export ROOT_URL="https://app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud"",
612
+ "export HOST_INTERNAL="app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud"",
613
+ "export HOST_CANONICAL="app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud"",
614
+ "export ROOT_URL_INTERNAL="https://app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud"",
615
+ "export KUBE_NAMESPACE="pan-test-app-review"",
616
+ "export KUBE_APP_NAME="$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-app"",
617
+ "export KUBE_APP_NAME_PREFIX="$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-"",
618
+ "export SECRET_KEY_BASE="$CL_review_app_SECRET_KEY_BASE"",
619
+ "export POSTGRESQL_PASSWORD="$CL_review_app_POSTGRESQL_PASSWORD"",
620
+ "export cloudsqlProxyCredentials="$CL_review_app_cloudsqlProxyCredentials"",
621
+ "export RAILS_ENV="production"",
622
+ "export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"ROOT_URL\\",\\"HOST_INTERNAL\\",\\"HOST_CANONICAL\\",\\"ROOT_URL_INTERNAL\\",\\"KUBE_NAMESPACE\\",\\"KUBE_APP_NAME\\",\\"KUBE_APP_NAME_PREFIX\\",\\"SECRET_KEY_BASE\\",\\"POSTGRESQL_PASSWORD\\",\\"cloudsqlProxyCredentials\\",\\"RAILS_ENV\\"]"",
623
+ "export RELEASE_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"; })-app"",
624
+ "export HELM_EXPERIMENTAL_OCI="1"",
625
+ "export KUBE_DOCKER_IMAGE_PULL_SECRET="gitlab-registry-app"",
626
+ "export HELM_GITLAB_CHART_NAME="/helm-charts/the-panter-chart"",
627
+ "export HELM_ARGS=""",
628
+ "export COMPONENT_NAME="app"",
629
+ "export BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
630
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
631
+ "kubectl config set-cluster "kube-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"; })-app" --server="$CL_review_app_KUBE_URL" --certificate-authority <(echo $CL_review_app_KUBE_CA_PEM | base64 -d) --embed-certs=true",
632
+ "kubectl config set-credentials "kube-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"; })-app" --token="$CL_review_app_KUBE_TOKEN"",
633
+ "kubectl config set-context "kube-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"; })-app" --cluster="kube-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"; })-app" --user="kube-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"; })-app" --namespace="pan-test-app-review"",
634
+ "kubectl config use-context "kube-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"; })-app"",
635
+ "kubernetesRollback",
636
+ "echo "CL_GITLAB_ENVIRONMENT_URL=https://app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud" >> gitlab_environment.env",
637
+ ],
638
+ "stage": "rollback review",
639
+ "variables": {
640
+ "GIT_STRATEGY": "none",
641
+ "KUBERNETES_CPU_REQUEST": "0.22",
642
+ "KUBERNETES_MEMORY_LIMIT": "400Mi",
643
+ "KUBERNETES_MEMORY_REQUEST": "200Mi",
644
+ },
645
+ },
646
+ "app 👮 lint": {
647
+ "cache": {
648
+ "key": {
649
+ "files": [
650
+ "Gemfile.lock",
651
+ ],
652
+ "prefix": "$CI_JOB_IMAGE",
653
+ },
654
+ "paths": [
655
+ "tmp/cache",
656
+ ],
657
+ },
658
+ "image": "ruby:3.2.1",
659
+ "interruptible": true,
660
+ "needs": [],
661
+ "retry": {
662
+ "max": 2,
663
+ "when": [
664
+ "runner_system_failure",
665
+ "stuck_or_timeout_failure",
666
+ ],
667
+ },
668
+ "script": [
669
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
670
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
671
+ "cd .",
672
+ "bundle config set path 'tmp/cache'",
673
+ "bundle install -j $(nproc)",
674
+ "bundle exec rubocop",
675
+ ],
676
+ "stage": "test",
677
+ "variables": {},
678
+ },
679
+ "app 🔨 docker | review ": {
680
+ "image": "path/to/docker/docker-build:the-version",
681
+ "interruptible": true,
682
+ "needs": [],
683
+ "retry": {
684
+ "max": 2,
685
+ "when": [
686
+ "runner_system_failure",
687
+ "stuck_or_timeout_failure",
688
+ ],
689
+ },
690
+ "script": [
691
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
692
+ "export APP_DIR="."",
693
+ "export DOCKER_BUILD_CONTEXT="."",
694
+ "export DOCKER_REGISTRY="$CI_REGISTRY"",
695
+ "export DOCKER_CACHE_IMAGE="$CI_REGISTRY_IMAGE/caches/app"",
696
+ "export DOCKER_IMAGE_NAME="review/app"",
697
+ "export DOCKER_IMAGE="$CI_REGISTRY_IMAGE/$DOCKER_IMAGE_NAME"",
698
+ "export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"",
699
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
700
+ "echo -e "\\e[0Ksection_start:$(date +%s):docker-login[collapsed=true]\\r\\e[0KDocker Login"",
701
+ "docker login --username gitlab-ci-token --password $CI_JOB_TOKEN $CI_REGISTRY",
702
+ "echo -e "\\e[0Ksection_end:$(date +%s):docker-login\\r\\e[0K"",
703
+ "echo -e "\\e[0Ksection_start:$(date +%s):docker-build[collapsed=true]\\r\\e[0KDocker build"",
704
+ "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",
705
+ "echo -e "\\e[0Ksection_end:$(date +%s):docker-build\\r\\e[0K"",
706
+ "echo -e "\\e[0Ksection_start:$(date +%s):docker-push[collapsed=true]\\r\\e[0KDocker push and tag"",
707
+ "docker push $DOCKER_IMAGE:$DOCKER_IMAGE_TAG",
708
+ "docker tag $DOCKER_IMAGE:$DOCKER_IMAGE_TAG $DOCKER_CACHE_IMAGE",
709
+ "docker push $DOCKER_CACHE_IMAGE",
710
+ "echo -e "\\e[0Ksection_end:$(date +%s):docker-push\\r\\e[0K"",
711
+ ],
712
+ "services": [
713
+ {
714
+ "command": [
715
+ "--tls=false",
716
+ ],
717
+ "name": "docker:24.0.6-dind",
718
+ },
719
+ ],
720
+ "stage": "build",
721
+ "variables": {
722
+ "DOCKER_BUILDKIT": "1",
723
+ "DOCKER_DRIVER": "overlay2",
724
+ "DOCKER_HOST": "tcp://0.0.0.0:2375",
725
+ "DOCKER_TLS_CERTDIR": "",
726
+ "KUBERNETES_CPU_REQUEST": "0.45",
727
+ "KUBERNETES_MEMORY_LIMIT": "2Gi",
728
+ "KUBERNETES_MEMORY_REQUEST": "1Gi",
729
+ },
730
+ },
731
+ "app 🚀 Deploy | review ": {
732
+ "allow_failure": false,
733
+ "artifacts": {
734
+ "reports": {
735
+ "dotenv": "gitlab_environment.env",
736
+ },
737
+ },
738
+ "environment": {
739
+ "auto_stop_in": "1 week",
740
+ "name": "review/$CI_COMMIT_REF_NAME/app",
741
+ "on_stop": "app 🛑 Stop ⚠️ | review ",
742
+ "url": "$CL_GITLAB_ENVIRONMENT_URL",
743
+ },
744
+ "image": "path/to/docker/kubernetes:the-version",
745
+ "interruptible": true,
746
+ "needs": [
747
+ {
748
+ "artifacts": false,
749
+ "job": "app 👮 lint",
750
+ },
751
+ {
752
+ "artifacts": false,
753
+ "job": "app 🔨 docker | review ",
754
+ },
755
+ {
756
+ "artifacts": false,
757
+ "job": "app 🧪 test",
758
+ },
759
+ {
760
+ "artifacts": true,
761
+ "job": "app 🧾 sbom | review ",
762
+ },
763
+ {
764
+ "artifacts": false,
765
+ "job": "app 🛡 audit",
766
+ },
767
+ ],
768
+ "retry": {
769
+ "max": 2,
770
+ "when": [
771
+ "runner_system_failure",
772
+ "stuck_or_timeout_failure",
773
+ ],
774
+ },
775
+ "rules": [
776
+ {
777
+ "when": "on_success",
778
+ },
779
+ ],
780
+ "script": [
781
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
782
+ "export ENV_SHORT="review"",
783
+ "export APP_DIR="."",
784
+ "export ENV_TYPE="review"",
785
+ "export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
786
+ "export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"",
787
+ "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")"",
788
+ "export ROOT_URL="https://app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud"",
789
+ "export HOST_INTERNAL="app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud"",
790
+ "export HOST_CANONICAL="app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud"",
791
+ "export ROOT_URL_INTERNAL="https://app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud"",
792
+ "export KUBE_NAMESPACE="pan-test-app-review"",
793
+ "export KUBE_APP_NAME="$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-app"",
794
+ "export KUBE_APP_NAME_PREFIX="$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-"",
795
+ "export SECRET_KEY_BASE="$CL_review_app_SECRET_KEY_BASE"",
796
+ "export POSTGRESQL_PASSWORD="$CL_review_app_POSTGRESQL_PASSWORD"",
797
+ "export cloudsqlProxyCredentials="$CL_review_app_cloudsqlProxyCredentials"",
798
+ "export RAILS_ENV="production"",
799
+ "export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"ROOT_URL\\",\\"HOST_INTERNAL\\",\\"HOST_CANONICAL\\",\\"ROOT_URL_INTERNAL\\",\\"KUBE_NAMESPACE\\",\\"KUBE_APP_NAME\\",\\"KUBE_APP_NAME_PREFIX\\",\\"SECRET_KEY_BASE\\",\\"POSTGRESQL_PASSWORD\\",\\"cloudsqlProxyCredentials\\",\\"RAILS_ENV\\"]"",
800
+ "export DOCKER_REGISTRY="$CI_REGISTRY"",
801
+ "export DOCKER_CACHE_IMAGE="$CI_REGISTRY_IMAGE/caches/app"",
802
+ "export DOCKER_IMAGE_NAME="review/app"",
803
+ "export DOCKER_IMAGE="$CI_REGISTRY_IMAGE/$DOCKER_IMAGE_NAME"",
804
+ "export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"",
805
+ "export RELEASE_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"; })-app"",
806
+ "export HELM_EXPERIMENTAL_OCI="1"",
807
+ "export KUBE_DOCKER_IMAGE_PULL_SECRET="gitlab-registry-app"",
808
+ "export HELM_GITLAB_CHART_NAME="/helm-charts/the-panter-chart"",
809
+ "export HELM_ARGS=""",
810
+ "export COMPONENT_NAME="app"",
811
+ "export BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
812
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
813
+ "kubectl config set-cluster "kube-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"; })-app" --server="$CL_review_app_KUBE_URL" --certificate-authority <(echo $CL_review_app_KUBE_CA_PEM | base64 -d) --embed-certs=true",
814
+ "kubectl config set-credentials "kube-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"; })-app" --token="$CL_review_app_KUBE_TOKEN"",
815
+ "kubectl config set-context "kube-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"; })-app" --cluster="kube-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"; })-app" --user="kube-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"; })-app" --namespace="pan-test-app-review"",
816
+ "kubectl config use-context "kube-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"; })-app"",
817
+ "echo -e "\\e[0Ksection_start:$(date +%s):writeallvalues[collapsed=true]\\r\\e[0KWrite __all_values.yml for helm deployment"",
818
+ "cat > __all_values.yml <<EOF
819
+ env:
820
+ secret:
821
+ SECRET_KEY_BASE: |-
822
+ $(printf %s "$CL_review_app_SECRET_KEY_BASE" | sed 's/^/ /')
823
+ POSTGRESQL_PASSWORD: |-
824
+ $(printf %s "$CL_review_app_POSTGRESQL_PASSWORD" | sed 's/^/ /')
825
+ cloudsqlProxyCredentials: |-
826
+ $(printf %s "$CL_review_app_cloudsqlProxyCredentials" | sed 's/^/ /')
827
+ public:
828
+ ENV_SHORT: |-
829
+ review
830
+ APP_DIR: |-
831
+ .
832
+ ENV_TYPE: |-
833
+ review
834
+ BUILD_INFO_BUILD_ID: |-
835
+ $(printf %s "$(git describe --tags 2>/dev/null || git rev-parse HEAD)" | sed 's/^/ /')
836
+ BUILD_INFO_BUILD_TIME: |-
837
+ $(printf %s "$CI_JOB_STARTED_AT" | sed 's/^/ /')
838
+ BUILD_INFO_CURRENT_VERSION: |-
839
+ $(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 's/^/ /')
840
+ ROOT_URL: |-
841
+ $(printf %s "https://app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud" | sed 's/^/ /')
842
+ HOST_INTERNAL: |-
843
+ $(printf %s "app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud" | sed 's/^/ /')
844
+ HOST_CANONICAL: |-
845
+ $(printf %s "app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud" | sed 's/^/ /')
846
+ ROOT_URL_INTERNAL: |-
847
+ $(printf %s "https://app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud" | sed 's/^/ /')
848
+ KUBE_NAMESPACE: |-
849
+ pan-test-app-review
850
+ KUBE_APP_NAME: |-
851
+ $(printf %s "$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-app" | sed 's/^/ /')
852
+ KUBE_APP_NAME_PREFIX: |-
853
+ $(printf %s "$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-" | sed 's/^/ /')
854
+ RAILS_ENV: |-
855
+ production
856
+ _ALL_ENV_VAR_KEYS: |-
857
+ ["ENV_SHORT","APP_DIR","ENV_TYPE","BUILD_INFO_BUILD_ID","BUILD_INFO_BUILD_TIME","BUILD_INFO_CURRENT_VERSION","ROOT_URL","HOST_INTERNAL","HOST_CANONICAL","ROOT_URL_INTERNAL","KUBE_NAMESPACE","KUBE_APP_NAME","KUBE_APP_NAME_PREFIX","SECRET_KEY_BASE","POSTGRESQL_PASSWORD","cloudsqlProxyCredentials","RAILS_ENV"]
858
+ application:
859
+ host: |-
860
+ $(printf %s "app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud" | sed 's/^/ /')
861
+ command: |-
862
+ /cnb/process/web
863
+ livenessProbe:
864
+ httpGet:
865
+ path: |-
866
+ __health
867
+ readinessProbe:
868
+ httpGet:
869
+ path: |-
870
+ __health
871
+ startupProbe:
872
+ httpGet:
873
+ path: |-
874
+ __health
875
+ worker:
876
+ enabled: true
877
+ command: |-
878
+ launcher bundle exec rake jobs:work
879
+ livenessProbe: false
880
+ cloudsql:
881
+ enabled: true
882
+ dbUser: |-
883
+ postgres
884
+ instanceConnectionName: |-
885
+ some-project-id:europe-west6:pan-test-app-review
886
+ proxyCredentials: |-
887
+ $CL_review_app_cloudsqlProxyCredentials
888
+ fullDbName: |-
889
+ $(printf %s "$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-app" | sed 's/^/ /')
890
+ projectId: |-
891
+ some-project-id
892
+ jobs:
893
+ db-migrate:
894
+ hook: |-
895
+ post-upgrade
896
+ command: |-
897
+ launcher bundle exec rake db:migrate
898
+ db-prepare-seed:
899
+ hook: |-
900
+ post-install
901
+ command: |-
902
+ launcher bundle exec rake db:prepare db:seed
903
+
904
+ EOF
905
+ ",
906
+ "echo -e "\\e[0Ksection_end:$(date +%s):writeallvalues\\r\\e[0K"",
907
+ "kubernetesCreateSecret",
908
+ "kubernetesDeploy",
909
+ "echo 'Uploading SBOM to Dependency Track'",
910
+ "/dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" upload "pan-test-app/app" "https://app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud" "__sbom.json" vex.json || true",
911
+ "echo deployment successful 😻",
912
+ "echo "CL_GITLAB_ENVIRONMENT_URL=https://app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud" >> gitlab_environment.env",
913
+ ],
914
+ "stage": "deploy review",
915
+ "variables": {
916
+ "KUBERNETES_CPU_REQUEST": "0.22",
917
+ "KUBERNETES_MEMORY_LIMIT": "400Mi",
918
+ "KUBERNETES_MEMORY_REQUEST": "200Mi",
919
+ },
920
+ },
921
+ "app 🛑 Stop ⚠️ | review ": {
922
+ "allow_failure": true,
923
+ "artifacts": {
924
+ "reports": {
925
+ "dotenv": "gitlab_environment.env",
926
+ },
927
+ },
928
+ "environment": {
929
+ "action": "stop",
930
+ "name": "review/$CI_COMMIT_REF_NAME/app",
931
+ "url": "$CL_GITLAB_ENVIRONMENT_URL",
932
+ },
933
+ "image": "path/to/docker/kubernetes:the-version",
934
+ "interruptible": true,
935
+ "needs": [],
936
+ "retry": {
937
+ "max": 2,
938
+ "when": [
939
+ "runner_system_failure",
940
+ "stuck_or_timeout_failure",
941
+ ],
942
+ },
943
+ "rules": [
944
+ {
945
+ "if": "$CI_COMMIT_BRANCH =~ /^[0-9]+\\.([0-9]+|x)\\.x$/",
946
+ "when": "on_success",
947
+ },
948
+ {
949
+ "when": "manual",
950
+ },
951
+ ],
952
+ "script": [
953
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
954
+ "export ENV_SHORT="review"",
955
+ "export APP_DIR="."",
956
+ "export ENV_TYPE="review"",
957
+ "export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
958
+ "export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"",
959
+ "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")"",
960
+ "export ROOT_URL="https://app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud"",
961
+ "export HOST_INTERNAL="app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud"",
962
+ "export HOST_CANONICAL="app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud"",
963
+ "export ROOT_URL_INTERNAL="https://app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud"",
964
+ "export KUBE_NAMESPACE="pan-test-app-review"",
965
+ "export KUBE_APP_NAME="$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-app"",
966
+ "export KUBE_APP_NAME_PREFIX="$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })-"",
967
+ "export SECRET_KEY_BASE="$CL_review_app_SECRET_KEY_BASE"",
968
+ "export POSTGRESQL_PASSWORD="$CL_review_app_POSTGRESQL_PASSWORD"",
969
+ "export cloudsqlProxyCredentials="$CL_review_app_cloudsqlProxyCredentials"",
970
+ "export RAILS_ENV="production"",
971
+ "export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"ROOT_URL\\",\\"HOST_INTERNAL\\",\\"HOST_CANONICAL\\",\\"ROOT_URL_INTERNAL\\",\\"KUBE_NAMESPACE\\",\\"KUBE_APP_NAME\\",\\"KUBE_APP_NAME_PREFIX\\",\\"SECRET_KEY_BASE\\",\\"POSTGRESQL_PASSWORD\\",\\"cloudsqlProxyCredentials\\",\\"RAILS_ENV\\"]"",
972
+ "export RELEASE_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"; })-app"",
973
+ "export HELM_EXPERIMENTAL_OCI="1"",
974
+ "export KUBE_DOCKER_IMAGE_PULL_SECRET="gitlab-registry-app"",
975
+ "export HELM_GITLAB_CHART_NAME="/helm-charts/the-panter-chart"",
976
+ "export HELM_ARGS=""",
977
+ "export COMPONENT_NAME="app"",
978
+ "export BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
979
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
980
+ "kubectl config set-cluster "kube-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"; })-app" --server="$CL_review_app_KUBE_URL" --certificate-authority <(echo $CL_review_app_KUBE_CA_PEM | base64 -d) --embed-certs=true",
981
+ "kubectl config set-credentials "kube-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"; })-app" --token="$CL_review_app_KUBE_TOKEN"",
982
+ "kubectl config set-context "kube-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"; })-app" --cluster="kube-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"; })-app" --user="kube-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"; })-app" --namespace="pan-test-app-review"",
983
+ "kubectl config use-context "kube-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"; })-app"",
984
+ "kubernetesDelete",
985
+ "echo 'Disabling component in Dependency Track'",
986
+ "/dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" disable "pan-test-app/app" "https://app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud" || true",
987
+ "echo "CL_GITLAB_ENVIRONMENT_URL=https://app.$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; }).review.test-app.pan.panter.cloud" >> gitlab_environment.env",
988
+ ],
989
+ "stage": "stop review",
990
+ "variables": {
991
+ "GIT_STRATEGY": "none",
992
+ "KUBERNETES_CPU_REQUEST": "0.22",
993
+ "KUBERNETES_MEMORY_LIMIT": "400Mi",
994
+ "KUBERNETES_MEMORY_REQUEST": "200Mi",
995
+ },
996
+ },
997
+ "app 🛡 audit": {
998
+ "allow_failure": true,
999
+ "image": "ruby:3.2.1",
1000
+ "interruptible": true,
1001
+ "needs": [],
1002
+ "retry": {
1003
+ "max": 2,
1004
+ "when": [
1005
+ "runner_system_failure",
1006
+ "stuck_or_timeout_failure",
1007
+ ],
1008
+ },
1009
+ "script": [
1010
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
1011
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
1012
+ "cd .",
1013
+ "gem install bundler-audit",
1014
+ "bundle audit check",
1015
+ ],
1016
+ "stage": "test",
1017
+ "variables": {},
1018
+ },
1019
+ "app 🧪 test": {
1020
+ "cache": {
1021
+ "key": {
1022
+ "files": [
1023
+ "Gemfile.lock",
1024
+ ],
1025
+ "prefix": "$CI_JOB_IMAGE",
1026
+ },
1027
+ "paths": [
1028
+ "tmp/cache",
1029
+ ],
1030
+ },
1031
+ "image": "ruby:3.2.1",
1032
+ "interruptible": true,
1033
+ "needs": [],
1034
+ "retry": {
1035
+ "max": 2,
1036
+ "when": [
1037
+ "runner_system_failure",
1038
+ "stuck_or_timeout_failure",
1039
+ ],
1040
+ },
1041
+ "script": [
1042
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
1043
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
1044
+ "cd .",
1045
+ "bundle config set path 'tmp/cache'",
1046
+ "bundle install -j $(nproc)",
1047
+ "bundle exec rspec",
1048
+ ],
1049
+ "stage": "test",
1050
+ "variables": {},
1051
+ },
1052
+ "app 🧾 sbom | review ": {
1053
+ "allow_failure": true,
1054
+ "artifacts": {
1055
+ "paths": [
1056
+ "__sbom.json",
1057
+ ],
1058
+ },
1059
+ "image": "aquasec/trivy:0.38.3",
1060
+ "interruptible": true,
1061
+ "needs": [],
1062
+ "retry": {
1063
+ "max": 2,
1064
+ "when": [
1065
+ "runner_system_failure",
1066
+ "stuck_or_timeout_failure",
1067
+ ],
1068
+ },
1069
+ "script": [
1070
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
1071
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
1072
+ "trivy fs --quiet --format cyclonedx --output "__sbom.json" .",
1073
+ ],
1074
+ "stage": "build",
1075
+ "variables": {},
1076
+ },
1077
+ },
1078
+ "stages": [
1079
+ "setup",
1080
+ "setup dev",
1081
+ "setup review",
1082
+ "setup stage",
1083
+ "setup prod",
1084
+ "test",
1085
+ "test dev",
1086
+ "test review",
1087
+ "test stage",
1088
+ "test prod",
1089
+ "build",
1090
+ "build dev",
1091
+ "build review",
1092
+ "build stage",
1093
+ "build prod",
1094
+ "deploy",
1095
+ "deploy dev",
1096
+ "deploy review",
1097
+ "deploy stage",
1098
+ "deploy prod",
1099
+ "verify",
1100
+ "verify dev",
1101
+ "verify review",
1102
+ "verify stage",
1103
+ "verify prod",
1104
+ "rollback",
1105
+ "rollback dev",
1106
+ "rollback review",
1107
+ "rollback stage",
1108
+ "rollback prod",
1109
+ "stop",
1110
+ "stop dev",
1111
+ "stop review",
1112
+ "stop stage",
1113
+ "stop prod",
1114
+ ],
1115
+ "variables": {
1116
+ "ARTIFACT_COMPRESSION_LEVEL": "fast",
1117
+ "CACHE_COMPRESSION_LEVEL": "fast",
1118
+ "FF_USE_FASTZIP": "true",
1119
+ "GIT_DEPTH": "1",
1120
+ "TRANSFER_METER_FREQUENCY": "5s",
1121
+ },
1122
+ "workflow": {
1123
+ "rules": [
1124
+ {
1125
+ "if": "$CI_COMMIT_TAG",
1126
+ },
1127
+ {
1128
+ "if": "$CI_COMMIT_MESSAGE =~ /^chore\\(release\\).*/",
1129
+ "when": "never",
1130
+ },
1131
+ {
1132
+ "if": "$CI_PIPELINE_SOURCE == "schedule"",
1133
+ "when": "never",
1134
+ },
1135
+ {
1136
+ "if": "$CI_COMMIT_BRANCH =~ /^[0-9]+.([0-9]+|x).x$/",
1137
+ },
1138
+ {
1139
+ "if": "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH",
1140
+ },
1141
+ {
1142
+ "if": "$CI_MERGE_REQUEST_ID",
1143
+ },
1144
+ ],
1145
+ },
1146
+ },
1147
+ "taggedRelease": {
1148
+ "image": "path/to/docker/jobs-default:the-version",
1149
+ "jobs": {
1150
+ "app ↩️ Rollback ⚠️ | prod ": {
1151
+ "allow_failure": true,
1152
+ "artifacts": {
1153
+ "reports": {
1154
+ "dotenv": "gitlab_environment.env",
1155
+ },
1156
+ },
1157
+ "environment": {
1158
+ "action": "access",
1159
+ "name": "prod/app",
1160
+ "url": "$CL_GITLAB_ENVIRONMENT_URL",
1161
+ },
1162
+ "image": "path/to/docker/kubernetes:the-version",
1163
+ "interruptible": true,
1164
+ "needs": [],
1165
+ "retry": {
1166
+ "max": 2,
1167
+ "when": [
1168
+ "runner_system_failure",
1169
+ "stuck_or_timeout_failure",
1170
+ ],
1171
+ },
1172
+ "rules": [
1173
+ {
1174
+ "when": "manual",
1175
+ },
1176
+ ],
1177
+ "script": [
1178
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
1179
+ "export ENV_SHORT="prod"",
1180
+ "export APP_DIR="."",
1181
+ "export ENV_TYPE="prod"",
1182
+ "export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
1183
+ "export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"",
1184
+ "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")"",
1185
+ "export ROOT_URL="https://my-fancy-website.com"",
1186
+ "export HOST_INTERNAL="app.prod.test-app.pan.panter.cloud"",
1187
+ "export HOST_CANONICAL="app.prod.test-app.pan.panter.cloud"",
1188
+ "export ROOT_URL_INTERNAL="https://app.prod.test-app.pan.panter.cloud"",
1189
+ "export KUBE_NAMESPACE="pan-test-app-prod"",
1190
+ "export KUBE_APP_NAME="app"",
1191
+ "export KUBE_APP_NAME_PREFIX=""",
1192
+ "export SECRET_KEY_BASE="$CL_prod_app_SECRET_KEY_BASE"",
1193
+ "export POSTGRESQL_PASSWORD="$CL_prod_app_POSTGRESQL_PASSWORD"",
1194
+ "export cloudsqlProxyCredentials="$CL_prod_app_cloudsqlProxyCredentials"",
1195
+ "export RAILS_ENV="production"",
1196
+ "export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"ROOT_URL\\",\\"HOST_INTERNAL\\",\\"HOST_CANONICAL\\",\\"ROOT_URL_INTERNAL\\",\\"KUBE_NAMESPACE\\",\\"KUBE_APP_NAME\\",\\"KUBE_APP_NAME_PREFIX\\",\\"SECRET_KEY_BASE\\",\\"POSTGRESQL_PASSWORD\\",\\"cloudsqlProxyCredentials\\",\\"RAILS_ENV\\"]"",
1197
+ "export RELEASE_NAME="pan-test-app-prod-app"",
1198
+ "export HELM_EXPERIMENTAL_OCI="1"",
1199
+ "export KUBE_DOCKER_IMAGE_PULL_SECRET="gitlab-registry-app"",
1200
+ "export HELM_GITLAB_CHART_NAME="/helm-charts/the-panter-chart"",
1201
+ "export HELM_ARGS=""",
1202
+ "export COMPONENT_NAME="app"",
1203
+ "export BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
1204
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
1205
+ "kubectl config set-cluster "kube-pan-test-app-prod-app" --server="$CL_prod_app_KUBE_URL" --certificate-authority <(echo $CL_prod_app_KUBE_CA_PEM | base64 -d) --embed-certs=true",
1206
+ "kubectl config set-credentials "kube-pan-test-app-prod-app" --token="$CL_prod_app_KUBE_TOKEN"",
1207
+ "kubectl config set-context "kube-pan-test-app-prod-app" --cluster="kube-pan-test-app-prod-app" --user="kube-pan-test-app-prod-app" --namespace="pan-test-app-prod"",
1208
+ "kubectl config use-context "kube-pan-test-app-prod-app"",
1209
+ "kubernetesRollback",
1210
+ "echo "CL_GITLAB_ENVIRONMENT_URL=https://my-fancy-website.com" >> gitlab_environment.env",
1211
+ ],
1212
+ "stage": "rollback prod",
1213
+ "variables": {
1214
+ "GIT_STRATEGY": "none",
1215
+ "KUBERNETES_CPU_REQUEST": "0.22",
1216
+ "KUBERNETES_MEMORY_LIMIT": "400Mi",
1217
+ "KUBERNETES_MEMORY_REQUEST": "200Mi",
1218
+ },
1219
+ },
1220
+ "app ↩️ Rollback ⚠️ | stage ": {
1221
+ "allow_failure": true,
1222
+ "artifacts": {
1223
+ "reports": {
1224
+ "dotenv": "gitlab_environment.env",
1225
+ },
1226
+ },
1227
+ "environment": {
1228
+ "action": "access",
1229
+ "name": "stage/app",
1230
+ "url": "$CL_GITLAB_ENVIRONMENT_URL",
1231
+ },
1232
+ "image": "path/to/docker/kubernetes:the-version",
1233
+ "interruptible": true,
1234
+ "needs": [],
1235
+ "retry": {
1236
+ "max": 2,
1237
+ "when": [
1238
+ "runner_system_failure",
1239
+ "stuck_or_timeout_failure",
1240
+ ],
1241
+ },
1242
+ "rules": [
1243
+ {
1244
+ "when": "manual",
1245
+ },
1246
+ ],
1247
+ "script": [
1248
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
1249
+ "export ENV_SHORT="stage"",
1250
+ "export APP_DIR="."",
1251
+ "export ENV_TYPE="stage"",
1252
+ "export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
1253
+ "export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"",
1254
+ "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")"",
1255
+ "export ROOT_URL="https://app.stage.test-app.pan.panter.cloud"",
1256
+ "export HOST_INTERNAL="app.stage.test-app.pan.panter.cloud"",
1257
+ "export HOST_CANONICAL="app.stage.test-app.pan.panter.cloud"",
1258
+ "export ROOT_URL_INTERNAL="https://app.stage.test-app.pan.panter.cloud"",
1259
+ "export KUBE_NAMESPACE="pan-test-app-stage"",
1260
+ "export KUBE_APP_NAME="app"",
1261
+ "export KUBE_APP_NAME_PREFIX=""",
1262
+ "export SECRET_KEY_BASE="$CL_stage_app_SECRET_KEY_BASE"",
1263
+ "export POSTGRESQL_PASSWORD="$CL_stage_app_POSTGRESQL_PASSWORD"",
1264
+ "export cloudsqlProxyCredentials="$CL_stage_app_cloudsqlProxyCredentials"",
1265
+ "export RAILS_ENV="production"",
1266
+ "export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"ROOT_URL\\",\\"HOST_INTERNAL\\",\\"HOST_CANONICAL\\",\\"ROOT_URL_INTERNAL\\",\\"KUBE_NAMESPACE\\",\\"KUBE_APP_NAME\\",\\"KUBE_APP_NAME_PREFIX\\",\\"SECRET_KEY_BASE\\",\\"POSTGRESQL_PASSWORD\\",\\"cloudsqlProxyCredentials\\",\\"RAILS_ENV\\"]"",
1267
+ "export RELEASE_NAME="pan-test-app-stage-app"",
1268
+ "export HELM_EXPERIMENTAL_OCI="1"",
1269
+ "export KUBE_DOCKER_IMAGE_PULL_SECRET="gitlab-registry-app"",
1270
+ "export HELM_GITLAB_CHART_NAME="/helm-charts/the-panter-chart"",
1271
+ "export HELM_ARGS=""",
1272
+ "export COMPONENT_NAME="app"",
1273
+ "export BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
1274
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
1275
+ "kubectl config set-cluster "kube-pan-test-app-stage-app" --server="$CL_stage_app_KUBE_URL" --certificate-authority <(echo $CL_stage_app_KUBE_CA_PEM | base64 -d) --embed-certs=true",
1276
+ "kubectl config set-credentials "kube-pan-test-app-stage-app" --token="$CL_stage_app_KUBE_TOKEN"",
1277
+ "kubectl config set-context "kube-pan-test-app-stage-app" --cluster="kube-pan-test-app-stage-app" --user="kube-pan-test-app-stage-app" --namespace="pan-test-app-stage"",
1278
+ "kubectl config use-context "kube-pan-test-app-stage-app"",
1279
+ "kubernetesRollback",
1280
+ "echo "CL_GITLAB_ENVIRONMENT_URL=https://app.stage.test-app.pan.panter.cloud" >> gitlab_environment.env",
1281
+ ],
1282
+ "stage": "rollback stage",
1283
+ "variables": {
1284
+ "GIT_STRATEGY": "none",
1285
+ "KUBERNETES_CPU_REQUEST": "0.22",
1286
+ "KUBERNETES_MEMORY_LIMIT": "400Mi",
1287
+ "KUBERNETES_MEMORY_REQUEST": "200Mi",
1288
+ },
1289
+ },
1290
+ "app 🔨 docker | prod ": {
1291
+ "image": "path/to/docker/docker-build:the-version",
1292
+ "interruptible": true,
1293
+ "needs": [],
1294
+ "retry": {
1295
+ "max": 2,
1296
+ "when": [
1297
+ "runner_system_failure",
1298
+ "stuck_or_timeout_failure",
1299
+ ],
1300
+ },
1301
+ "script": [
1302
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
1303
+ "export APP_DIR="."",
1304
+ "export DOCKER_BUILD_CONTEXT="."",
1305
+ "export DOCKER_REGISTRY="$CI_REGISTRY"",
1306
+ "export DOCKER_CACHE_IMAGE="$CI_REGISTRY_IMAGE/caches/app"",
1307
+ "export DOCKER_IMAGE_NAME="prod/app"",
1308
+ "export DOCKER_IMAGE="$CI_REGISTRY_IMAGE/$DOCKER_IMAGE_NAME"",
1309
+ "export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"",
1310
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
1311
+ "echo -e "\\e[0Ksection_start:$(date +%s):docker-login[collapsed=true]\\r\\e[0KDocker Login"",
1312
+ "docker login --username gitlab-ci-token --password $CI_JOB_TOKEN $CI_REGISTRY",
1313
+ "echo -e "\\e[0Ksection_end:$(date +%s):docker-login\\r\\e[0K"",
1314
+ "echo -e "\\e[0Ksection_start:$(date +%s):docker-build[collapsed=true]\\r\\e[0KDocker build"",
1315
+ "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",
1316
+ "echo -e "\\e[0Ksection_end:$(date +%s):docker-build\\r\\e[0K"",
1317
+ "echo -e "\\e[0Ksection_start:$(date +%s):docker-push[collapsed=true]\\r\\e[0KDocker push and tag"",
1318
+ "docker push $DOCKER_IMAGE:$DOCKER_IMAGE_TAG",
1319
+ "docker tag $DOCKER_IMAGE:$DOCKER_IMAGE_TAG $DOCKER_CACHE_IMAGE",
1320
+ "docker push $DOCKER_CACHE_IMAGE",
1321
+ "echo -e "\\e[0Ksection_end:$(date +%s):docker-push\\r\\e[0K"",
1322
+ ],
1323
+ "services": [
1324
+ {
1325
+ "command": [
1326
+ "--tls=false",
1327
+ ],
1328
+ "name": "docker:24.0.6-dind",
1329
+ },
1330
+ ],
1331
+ "stage": "build",
1332
+ "variables": {
1333
+ "DOCKER_BUILDKIT": "1",
1334
+ "DOCKER_DRIVER": "overlay2",
1335
+ "DOCKER_HOST": "tcp://0.0.0.0:2375",
1336
+ "DOCKER_TLS_CERTDIR": "",
1337
+ "KUBERNETES_CPU_REQUEST": "0.45",
1338
+ "KUBERNETES_MEMORY_LIMIT": "2Gi",
1339
+ "KUBERNETES_MEMORY_REQUEST": "1Gi",
1340
+ },
1341
+ },
1342
+ "app 🔨 docker | stage ": {
1343
+ "image": "path/to/docker/docker-build:the-version",
1344
+ "interruptible": true,
1345
+ "needs": [],
1346
+ "retry": {
1347
+ "max": 2,
1348
+ "when": [
1349
+ "runner_system_failure",
1350
+ "stuck_or_timeout_failure",
1351
+ ],
1352
+ },
1353
+ "script": [
1354
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
1355
+ "export APP_DIR="."",
1356
+ "export DOCKER_BUILD_CONTEXT="."",
1357
+ "export DOCKER_REGISTRY="$CI_REGISTRY"",
1358
+ "export DOCKER_CACHE_IMAGE="$CI_REGISTRY_IMAGE/caches/app"",
1359
+ "export DOCKER_IMAGE_NAME="stage/app"",
1360
+ "export DOCKER_IMAGE="$CI_REGISTRY_IMAGE/$DOCKER_IMAGE_NAME"",
1361
+ "export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"",
1362
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
1363
+ "echo -e "\\e[0Ksection_start:$(date +%s):docker-login[collapsed=true]\\r\\e[0KDocker Login"",
1364
+ "docker login --username gitlab-ci-token --password $CI_JOB_TOKEN $CI_REGISTRY",
1365
+ "echo -e "\\e[0Ksection_end:$(date +%s):docker-login\\r\\e[0K"",
1366
+ "echo -e "\\e[0Ksection_start:$(date +%s):docker-build[collapsed=true]\\r\\e[0KDocker build"",
1367
+ "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",
1368
+ "echo -e "\\e[0Ksection_end:$(date +%s):docker-build\\r\\e[0K"",
1369
+ "echo -e "\\e[0Ksection_start:$(date +%s):docker-push[collapsed=true]\\r\\e[0KDocker push and tag"",
1370
+ "docker push $DOCKER_IMAGE:$DOCKER_IMAGE_TAG",
1371
+ "docker tag $DOCKER_IMAGE:$DOCKER_IMAGE_TAG $DOCKER_CACHE_IMAGE",
1372
+ "docker push $DOCKER_CACHE_IMAGE",
1373
+ "echo -e "\\e[0Ksection_end:$(date +%s):docker-push\\r\\e[0K"",
1374
+ ],
1375
+ "services": [
1376
+ {
1377
+ "command": [
1378
+ "--tls=false",
1379
+ ],
1380
+ "name": "docker:24.0.6-dind",
1381
+ },
1382
+ ],
1383
+ "stage": "build",
1384
+ "variables": {
1385
+ "DOCKER_BUILDKIT": "1",
1386
+ "DOCKER_DRIVER": "overlay2",
1387
+ "DOCKER_HOST": "tcp://0.0.0.0:2375",
1388
+ "DOCKER_TLS_CERTDIR": "",
1389
+ "KUBERNETES_CPU_REQUEST": "0.45",
1390
+ "KUBERNETES_MEMORY_LIMIT": "2Gi",
1391
+ "KUBERNETES_MEMORY_REQUEST": "1Gi",
1392
+ },
1393
+ },
1394
+ "app 🚀 Deploy | prod ": {
1395
+ "allow_failure": true,
1396
+ "artifacts": {
1397
+ "reports": {
1398
+ "dotenv": "gitlab_environment.env",
1399
+ },
1400
+ },
1401
+ "environment": {
1402
+ "auto_stop_in": undefined,
1403
+ "name": "prod/app",
1404
+ "on_stop": "app 🛑 Stop ⚠️ | prod ",
1405
+ "url": "$CL_GITLAB_ENVIRONMENT_URL",
1406
+ },
1407
+ "image": "path/to/docker/kubernetes:the-version",
1408
+ "interruptible": true,
1409
+ "needs": [
1410
+ {
1411
+ "artifacts": false,
1412
+ "job": "app 🔨 docker | prod ",
1413
+ },
1414
+ {
1415
+ "artifacts": true,
1416
+ "job": "app 🧾 sbom | prod ",
1417
+ },
1418
+ ],
1419
+ "retry": {
1420
+ "max": 2,
1421
+ "when": [
1422
+ "runner_system_failure",
1423
+ "stuck_or_timeout_failure",
1424
+ ],
1425
+ },
1426
+ "rules": [
1427
+ {
1428
+ "when": "manual",
1429
+ },
1430
+ ],
1431
+ "script": [
1432
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
1433
+ "export ENV_SHORT="prod"",
1434
+ "export APP_DIR="."",
1435
+ "export ENV_TYPE="prod"",
1436
+ "export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
1437
+ "export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"",
1438
+ "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")"",
1439
+ "export ROOT_URL="https://my-fancy-website.com"",
1440
+ "export HOST_INTERNAL="app.prod.test-app.pan.panter.cloud"",
1441
+ "export HOST_CANONICAL="app.prod.test-app.pan.panter.cloud"",
1442
+ "export ROOT_URL_INTERNAL="https://app.prod.test-app.pan.panter.cloud"",
1443
+ "export KUBE_NAMESPACE="pan-test-app-prod"",
1444
+ "export KUBE_APP_NAME="app"",
1445
+ "export KUBE_APP_NAME_PREFIX=""",
1446
+ "export SECRET_KEY_BASE="$CL_prod_app_SECRET_KEY_BASE"",
1447
+ "export POSTGRESQL_PASSWORD="$CL_prod_app_POSTGRESQL_PASSWORD"",
1448
+ "export cloudsqlProxyCredentials="$CL_prod_app_cloudsqlProxyCredentials"",
1449
+ "export RAILS_ENV="production"",
1450
+ "export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"ROOT_URL\\",\\"HOST_INTERNAL\\",\\"HOST_CANONICAL\\",\\"ROOT_URL_INTERNAL\\",\\"KUBE_NAMESPACE\\",\\"KUBE_APP_NAME\\",\\"KUBE_APP_NAME_PREFIX\\",\\"SECRET_KEY_BASE\\",\\"POSTGRESQL_PASSWORD\\",\\"cloudsqlProxyCredentials\\",\\"RAILS_ENV\\"]"",
1451
+ "export DOCKER_REGISTRY="$CI_REGISTRY"",
1452
+ "export DOCKER_CACHE_IMAGE="$CI_REGISTRY_IMAGE/caches/app"",
1453
+ "export DOCKER_IMAGE_NAME="prod/app"",
1454
+ "export DOCKER_IMAGE="$CI_REGISTRY_IMAGE/$DOCKER_IMAGE_NAME"",
1455
+ "export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"",
1456
+ "export RELEASE_NAME="pan-test-app-prod-app"",
1457
+ "export HELM_EXPERIMENTAL_OCI="1"",
1458
+ "export KUBE_DOCKER_IMAGE_PULL_SECRET="gitlab-registry-app"",
1459
+ "export HELM_GITLAB_CHART_NAME="/helm-charts/the-panter-chart"",
1460
+ "export HELM_ARGS=""",
1461
+ "export COMPONENT_NAME="app"",
1462
+ "export BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
1463
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
1464
+ "kubectl config set-cluster "kube-pan-test-app-prod-app" --server="$CL_prod_app_KUBE_URL" --certificate-authority <(echo $CL_prod_app_KUBE_CA_PEM | base64 -d) --embed-certs=true",
1465
+ "kubectl config set-credentials "kube-pan-test-app-prod-app" --token="$CL_prod_app_KUBE_TOKEN"",
1466
+ "kubectl config set-context "kube-pan-test-app-prod-app" --cluster="kube-pan-test-app-prod-app" --user="kube-pan-test-app-prod-app" --namespace="pan-test-app-prod"",
1467
+ "kubectl config use-context "kube-pan-test-app-prod-app"",
1468
+ "echo -e "\\e[0Ksection_start:$(date +%s):writeallvalues[collapsed=true]\\r\\e[0KWrite __all_values.yml for helm deployment"",
1469
+ "cat > __all_values.yml <<EOF
1470
+ env:
1471
+ secret:
1472
+ SECRET_KEY_BASE: |-
1473
+ $(printf %s "$CL_prod_app_SECRET_KEY_BASE" | sed 's/^/ /')
1474
+ POSTGRESQL_PASSWORD: |-
1475
+ $(printf %s "$CL_prod_app_POSTGRESQL_PASSWORD" | sed 's/^/ /')
1476
+ cloudsqlProxyCredentials: |-
1477
+ $(printf %s "$CL_prod_app_cloudsqlProxyCredentials" | sed 's/^/ /')
1478
+ public:
1479
+ ENV_SHORT: |-
1480
+ prod
1481
+ APP_DIR: |-
1482
+ .
1483
+ ENV_TYPE: |-
1484
+ prod
1485
+ BUILD_INFO_BUILD_ID: |-
1486
+ $(printf %s "$(git describe --tags 2>/dev/null || git rev-parse HEAD)" | sed 's/^/ /')
1487
+ BUILD_INFO_BUILD_TIME: |-
1488
+ $(printf %s "$CI_JOB_STARTED_AT" | sed 's/^/ /')
1489
+ BUILD_INFO_CURRENT_VERSION: |-
1490
+ $(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 's/^/ /')
1491
+ ROOT_URL: |-
1492
+ https://my-fancy-website.com
1493
+ HOST_INTERNAL: |-
1494
+ app.prod.test-app.pan.panter.cloud
1495
+ HOST_CANONICAL: |-
1496
+ app.prod.test-app.pan.panter.cloud
1497
+ ROOT_URL_INTERNAL: |-
1498
+ https://app.prod.test-app.pan.panter.cloud
1499
+ KUBE_NAMESPACE: |-
1500
+ pan-test-app-prod
1501
+ KUBE_APP_NAME: |-
1502
+ app
1503
+ KUBE_APP_NAME_PREFIX: ""
1504
+ RAILS_ENV: |-
1505
+ production
1506
+ _ALL_ENV_VAR_KEYS: |-
1507
+ ["ENV_SHORT","APP_DIR","ENV_TYPE","BUILD_INFO_BUILD_ID","BUILD_INFO_BUILD_TIME","BUILD_INFO_CURRENT_VERSION","ROOT_URL","HOST_INTERNAL","HOST_CANONICAL","ROOT_URL_INTERNAL","KUBE_NAMESPACE","KUBE_APP_NAME","KUBE_APP_NAME_PREFIX","SECRET_KEY_BASE","POSTGRESQL_PASSWORD","cloudsqlProxyCredentials","RAILS_ENV"]
1508
+ application:
1509
+ host: |-
1510
+ my-fancy-website.com
1511
+ command: |-
1512
+ /cnb/process/web
1513
+ livenessProbe:
1514
+ httpGet:
1515
+ path: |-
1516
+ __health
1517
+ readinessProbe:
1518
+ httpGet:
1519
+ path: |-
1520
+ __health
1521
+ startupProbe:
1522
+ httpGet:
1523
+ path: |-
1524
+ __health
1525
+ worker:
1526
+ enabled: true
1527
+ command: |-
1528
+ launcher bundle exec rake jobs:work
1529
+ livenessProbe: false
1530
+ cloudsql:
1531
+ enabled: true
1532
+ dbUser: |-
1533
+ postgres
1534
+ instanceConnectionName: |-
1535
+ some-project-id:europe-west6:pan-test-app-prod
1536
+ proxyCredentials: |-
1537
+ $CL_prod_app_cloudsqlProxyCredentials
1538
+ fullDbName: |-
1539
+ app
1540
+ projectId: |-
1541
+ some-project-id
1542
+ jobs:
1543
+ db-migrate:
1544
+ hook: |-
1545
+ post-install,post-upgrade
1546
+ command: |-
1547
+ launcher bundle exec rake db:migrate
1548
+
1549
+ EOF
1550
+ ",
1551
+ "echo -e "\\e[0Ksection_end:$(date +%s):writeallvalues\\r\\e[0K"",
1552
+ "kubernetesCreateSecret",
1553
+ "kubernetesDeploy",
1554
+ "echo 'Uploading SBOM to Dependency Track'",
1555
+ "/dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" upload "pan-test-app/app" "https://my-fancy-website.com" "__sbom.json" vex.json || true",
1556
+ "echo deployment successful 😻",
1557
+ "echo "CL_GITLAB_ENVIRONMENT_URL=https://my-fancy-website.com" >> gitlab_environment.env",
1558
+ ],
1559
+ "stage": "deploy prod",
1560
+ "variables": {
1561
+ "KUBERNETES_CPU_REQUEST": "0.22",
1562
+ "KUBERNETES_MEMORY_LIMIT": "400Mi",
1563
+ "KUBERNETES_MEMORY_REQUEST": "200Mi",
1564
+ },
1565
+ },
1566
+ "app 🚀 Deploy | stage ": {
1567
+ "allow_failure": false,
1568
+ "artifacts": {
1569
+ "reports": {
1570
+ "dotenv": "gitlab_environment.env",
1571
+ },
1572
+ },
1573
+ "environment": {
1574
+ "auto_stop_in": undefined,
1575
+ "name": "stage/app",
1576
+ "on_stop": "app 🛑 Stop ⚠️ | stage ",
1577
+ "url": "$CL_GITLAB_ENVIRONMENT_URL",
1578
+ },
1579
+ "image": "path/to/docker/kubernetes:the-version",
1580
+ "interruptible": true,
1581
+ "needs": [
1582
+ {
1583
+ "artifacts": false,
1584
+ "job": "app 🔨 docker | stage ",
1585
+ },
1586
+ {
1587
+ "artifacts": true,
1588
+ "job": "app 🧾 sbom | stage ",
1589
+ },
1590
+ ],
1591
+ "retry": {
1592
+ "max": 2,
1593
+ "when": [
1594
+ "runner_system_failure",
1595
+ "stuck_or_timeout_failure",
1596
+ ],
1597
+ },
1598
+ "rules": [
1599
+ {
1600
+ "when": "on_success",
1601
+ },
1602
+ ],
1603
+ "script": [
1604
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
1605
+ "export ENV_SHORT="stage"",
1606
+ "export APP_DIR="."",
1607
+ "export ENV_TYPE="stage"",
1608
+ "export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
1609
+ "export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"",
1610
+ "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")"",
1611
+ "export ROOT_URL="https://app.stage.test-app.pan.panter.cloud"",
1612
+ "export HOST_INTERNAL="app.stage.test-app.pan.panter.cloud"",
1613
+ "export HOST_CANONICAL="app.stage.test-app.pan.panter.cloud"",
1614
+ "export ROOT_URL_INTERNAL="https://app.stage.test-app.pan.panter.cloud"",
1615
+ "export KUBE_NAMESPACE="pan-test-app-stage"",
1616
+ "export KUBE_APP_NAME="app"",
1617
+ "export KUBE_APP_NAME_PREFIX=""",
1618
+ "export SECRET_KEY_BASE="$CL_stage_app_SECRET_KEY_BASE"",
1619
+ "export POSTGRESQL_PASSWORD="$CL_stage_app_POSTGRESQL_PASSWORD"",
1620
+ "export cloudsqlProxyCredentials="$CL_stage_app_cloudsqlProxyCredentials"",
1621
+ "export RAILS_ENV="production"",
1622
+ "export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"ROOT_URL\\",\\"HOST_INTERNAL\\",\\"HOST_CANONICAL\\",\\"ROOT_URL_INTERNAL\\",\\"KUBE_NAMESPACE\\",\\"KUBE_APP_NAME\\",\\"KUBE_APP_NAME_PREFIX\\",\\"SECRET_KEY_BASE\\",\\"POSTGRESQL_PASSWORD\\",\\"cloudsqlProxyCredentials\\",\\"RAILS_ENV\\"]"",
1623
+ "export DOCKER_REGISTRY="$CI_REGISTRY"",
1624
+ "export DOCKER_CACHE_IMAGE="$CI_REGISTRY_IMAGE/caches/app"",
1625
+ "export DOCKER_IMAGE_NAME="stage/app"",
1626
+ "export DOCKER_IMAGE="$CI_REGISTRY_IMAGE/$DOCKER_IMAGE_NAME"",
1627
+ "export DOCKER_IMAGE_TAG="$CI_COMMIT_SHA"",
1628
+ "export RELEASE_NAME="pan-test-app-stage-app"",
1629
+ "export HELM_EXPERIMENTAL_OCI="1"",
1630
+ "export KUBE_DOCKER_IMAGE_PULL_SECRET="gitlab-registry-app"",
1631
+ "export HELM_GITLAB_CHART_NAME="/helm-charts/the-panter-chart"",
1632
+ "export HELM_ARGS=""",
1633
+ "export COMPONENT_NAME="app"",
1634
+ "export BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
1635
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
1636
+ "kubectl config set-cluster "kube-pan-test-app-stage-app" --server="$CL_stage_app_KUBE_URL" --certificate-authority <(echo $CL_stage_app_KUBE_CA_PEM | base64 -d) --embed-certs=true",
1637
+ "kubectl config set-credentials "kube-pan-test-app-stage-app" --token="$CL_stage_app_KUBE_TOKEN"",
1638
+ "kubectl config set-context "kube-pan-test-app-stage-app" --cluster="kube-pan-test-app-stage-app" --user="kube-pan-test-app-stage-app" --namespace="pan-test-app-stage"",
1639
+ "kubectl config use-context "kube-pan-test-app-stage-app"",
1640
+ "echo -e "\\e[0Ksection_start:$(date +%s):writeallvalues[collapsed=true]\\r\\e[0KWrite __all_values.yml for helm deployment"",
1641
+ "cat > __all_values.yml <<EOF
1642
+ env:
1643
+ secret:
1644
+ SECRET_KEY_BASE: |-
1645
+ $(printf %s "$CL_stage_app_SECRET_KEY_BASE" | sed 's/^/ /')
1646
+ POSTGRESQL_PASSWORD: |-
1647
+ $(printf %s "$CL_stage_app_POSTGRESQL_PASSWORD" | sed 's/^/ /')
1648
+ cloudsqlProxyCredentials: |-
1649
+ $(printf %s "$CL_stage_app_cloudsqlProxyCredentials" | sed 's/^/ /')
1650
+ public:
1651
+ ENV_SHORT: |-
1652
+ stage
1653
+ APP_DIR: |-
1654
+ .
1655
+ ENV_TYPE: |-
1656
+ stage
1657
+ BUILD_INFO_BUILD_ID: |-
1658
+ $(printf %s "$(git describe --tags 2>/dev/null || git rev-parse HEAD)" | sed 's/^/ /')
1659
+ BUILD_INFO_BUILD_TIME: |-
1660
+ $(printf %s "$CI_JOB_STARTED_AT" | sed 's/^/ /')
1661
+ BUILD_INFO_CURRENT_VERSION: |-
1662
+ $(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 's/^/ /')
1663
+ ROOT_URL: |-
1664
+ https://app.stage.test-app.pan.panter.cloud
1665
+ HOST_INTERNAL: |-
1666
+ app.stage.test-app.pan.panter.cloud
1667
+ HOST_CANONICAL: |-
1668
+ app.stage.test-app.pan.panter.cloud
1669
+ ROOT_URL_INTERNAL: |-
1670
+ https://app.stage.test-app.pan.panter.cloud
1671
+ KUBE_NAMESPACE: |-
1672
+ pan-test-app-stage
1673
+ KUBE_APP_NAME: |-
1674
+ app
1675
+ KUBE_APP_NAME_PREFIX: ""
1676
+ RAILS_ENV: |-
1677
+ production
1678
+ _ALL_ENV_VAR_KEYS: |-
1679
+ ["ENV_SHORT","APP_DIR","ENV_TYPE","BUILD_INFO_BUILD_ID","BUILD_INFO_BUILD_TIME","BUILD_INFO_CURRENT_VERSION","ROOT_URL","HOST_INTERNAL","HOST_CANONICAL","ROOT_URL_INTERNAL","KUBE_NAMESPACE","KUBE_APP_NAME","KUBE_APP_NAME_PREFIX","SECRET_KEY_BASE","POSTGRESQL_PASSWORD","cloudsqlProxyCredentials","RAILS_ENV"]
1680
+ application:
1681
+ host: |-
1682
+ app.stage.test-app.pan.panter.cloud
1683
+ command: |-
1684
+ /cnb/process/web
1685
+ livenessProbe:
1686
+ httpGet:
1687
+ path: |-
1688
+ __health
1689
+ readinessProbe:
1690
+ httpGet:
1691
+ path: |-
1692
+ __health
1693
+ startupProbe:
1694
+ httpGet:
1695
+ path: |-
1696
+ __health
1697
+ worker:
1698
+ enabled: true
1699
+ command: |-
1700
+ launcher bundle exec rake jobs:work
1701
+ livenessProbe: false
1702
+ cloudsql:
1703
+ enabled: true
1704
+ dbUser: |-
1705
+ postgres
1706
+ instanceConnectionName: |-
1707
+ some-project-id:europe-west6:pan-test-app-stage
1708
+ proxyCredentials: |-
1709
+ $CL_stage_app_cloudsqlProxyCredentials
1710
+ fullDbName: |-
1711
+ app
1712
+ projectId: |-
1713
+ some-project-id
1714
+ jobs:
1715
+ db-migrate:
1716
+ hook: |-
1717
+ post-install,post-upgrade
1718
+ command: |-
1719
+ launcher bundle exec rake db:migrate
1720
+
1721
+ EOF
1722
+ ",
1723
+ "echo -e "\\e[0Ksection_end:$(date +%s):writeallvalues\\r\\e[0K"",
1724
+ "kubernetesCreateSecret",
1725
+ "kubernetesDeploy",
1726
+ "echo 'Uploading SBOM to Dependency Track'",
1727
+ "/dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" upload "pan-test-app/app" "https://app.stage.test-app.pan.panter.cloud" "__sbom.json" vex.json || true",
1728
+ "echo deployment successful 😻",
1729
+ "echo "CL_GITLAB_ENVIRONMENT_URL=https://app.stage.test-app.pan.panter.cloud" >> gitlab_environment.env",
1730
+ ],
1731
+ "stage": "deploy stage",
1732
+ "variables": {
1733
+ "KUBERNETES_CPU_REQUEST": "0.22",
1734
+ "KUBERNETES_MEMORY_LIMIT": "400Mi",
1735
+ "KUBERNETES_MEMORY_REQUEST": "200Mi",
1736
+ },
1737
+ },
1738
+ "app 🛑 Stop ⚠️ | prod ": {
1739
+ "allow_failure": true,
1740
+ "artifacts": {
1741
+ "reports": {
1742
+ "dotenv": "gitlab_environment.env",
1743
+ },
1744
+ },
1745
+ "environment": {
1746
+ "action": "stop",
1747
+ "name": "prod/app",
1748
+ "url": "$CL_GITLAB_ENVIRONMENT_URL",
1749
+ },
1750
+ "image": "path/to/docker/kubernetes:the-version",
1751
+ "interruptible": true,
1752
+ "needs": [],
1753
+ "retry": {
1754
+ "max": 2,
1755
+ "when": [
1756
+ "runner_system_failure",
1757
+ "stuck_or_timeout_failure",
1758
+ ],
1759
+ },
1760
+ "rules": [
1761
+ {
1762
+ "if": "$CI_COMMIT_BRANCH =~ /^[0-9]+\\.([0-9]+|x)\\.x$/",
1763
+ "when": "on_success",
1764
+ },
1765
+ {
1766
+ "when": "manual",
1767
+ },
1768
+ ],
1769
+ "script": [
1770
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
1771
+ "export ENV_SHORT="prod"",
1772
+ "export APP_DIR="."",
1773
+ "export ENV_TYPE="prod"",
1774
+ "export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
1775
+ "export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"",
1776
+ "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")"",
1777
+ "export ROOT_URL="https://my-fancy-website.com"",
1778
+ "export HOST_INTERNAL="app.prod.test-app.pan.panter.cloud"",
1779
+ "export HOST_CANONICAL="app.prod.test-app.pan.panter.cloud"",
1780
+ "export ROOT_URL_INTERNAL="https://app.prod.test-app.pan.panter.cloud"",
1781
+ "export KUBE_NAMESPACE="pan-test-app-prod"",
1782
+ "export KUBE_APP_NAME="app"",
1783
+ "export KUBE_APP_NAME_PREFIX=""",
1784
+ "export SECRET_KEY_BASE="$CL_prod_app_SECRET_KEY_BASE"",
1785
+ "export POSTGRESQL_PASSWORD="$CL_prod_app_POSTGRESQL_PASSWORD"",
1786
+ "export cloudsqlProxyCredentials="$CL_prod_app_cloudsqlProxyCredentials"",
1787
+ "export RAILS_ENV="production"",
1788
+ "export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"ROOT_URL\\",\\"HOST_INTERNAL\\",\\"HOST_CANONICAL\\",\\"ROOT_URL_INTERNAL\\",\\"KUBE_NAMESPACE\\",\\"KUBE_APP_NAME\\",\\"KUBE_APP_NAME_PREFIX\\",\\"SECRET_KEY_BASE\\",\\"POSTGRESQL_PASSWORD\\",\\"cloudsqlProxyCredentials\\",\\"RAILS_ENV\\"]"",
1789
+ "export RELEASE_NAME="pan-test-app-prod-app"",
1790
+ "export HELM_EXPERIMENTAL_OCI="1"",
1791
+ "export KUBE_DOCKER_IMAGE_PULL_SECRET="gitlab-registry-app"",
1792
+ "export HELM_GITLAB_CHART_NAME="/helm-charts/the-panter-chart"",
1793
+ "export HELM_ARGS=""",
1794
+ "export COMPONENT_NAME="app"",
1795
+ "export BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
1796
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
1797
+ "kubectl config set-cluster "kube-pan-test-app-prod-app" --server="$CL_prod_app_KUBE_URL" --certificate-authority <(echo $CL_prod_app_KUBE_CA_PEM | base64 -d) --embed-certs=true",
1798
+ "kubectl config set-credentials "kube-pan-test-app-prod-app" --token="$CL_prod_app_KUBE_TOKEN"",
1799
+ "kubectl config set-context "kube-pan-test-app-prod-app" --cluster="kube-pan-test-app-prod-app" --user="kube-pan-test-app-prod-app" --namespace="pan-test-app-prod"",
1800
+ "kubectl config use-context "kube-pan-test-app-prod-app"",
1801
+ "kubernetesDelete",
1802
+ "echo 'Disabling component in Dependency Track'",
1803
+ "/dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" disable "pan-test-app/app" "https://my-fancy-website.com" || true",
1804
+ "echo "CL_GITLAB_ENVIRONMENT_URL=https://my-fancy-website.com" >> gitlab_environment.env",
1805
+ ],
1806
+ "stage": "stop prod",
1807
+ "variables": {
1808
+ "GIT_STRATEGY": "none",
1809
+ "KUBERNETES_CPU_REQUEST": "0.22",
1810
+ "KUBERNETES_MEMORY_LIMIT": "400Mi",
1811
+ "KUBERNETES_MEMORY_REQUEST": "200Mi",
1812
+ },
1813
+ },
1814
+ "app 🛑 Stop ⚠️ | stage ": {
1815
+ "allow_failure": true,
1816
+ "artifacts": {
1817
+ "reports": {
1818
+ "dotenv": "gitlab_environment.env",
1819
+ },
1820
+ },
1821
+ "environment": {
1822
+ "action": "stop",
1823
+ "name": "stage/app",
1824
+ "url": "$CL_GITLAB_ENVIRONMENT_URL",
1825
+ },
1826
+ "image": "path/to/docker/kubernetes:the-version",
1827
+ "interruptible": true,
1828
+ "needs": [],
1829
+ "retry": {
1830
+ "max": 2,
1831
+ "when": [
1832
+ "runner_system_failure",
1833
+ "stuck_or_timeout_failure",
1834
+ ],
1835
+ },
1836
+ "rules": [
1837
+ {
1838
+ "if": "$CI_COMMIT_BRANCH =~ /^[0-9]+\\.([0-9]+|x)\\.x$/",
1839
+ "when": "on_success",
1840
+ },
1841
+ {
1842
+ "when": "manual",
1843
+ },
1844
+ ],
1845
+ "script": [
1846
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
1847
+ "export ENV_SHORT="stage"",
1848
+ "export APP_DIR="."",
1849
+ "export ENV_TYPE="stage"",
1850
+ "export BUILD_INFO_BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
1851
+ "export BUILD_INFO_BUILD_TIME="$CI_JOB_STARTED_AT"",
1852
+ "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")"",
1853
+ "export ROOT_URL="https://app.stage.test-app.pan.panter.cloud"",
1854
+ "export HOST_INTERNAL="app.stage.test-app.pan.panter.cloud"",
1855
+ "export HOST_CANONICAL="app.stage.test-app.pan.panter.cloud"",
1856
+ "export ROOT_URL_INTERNAL="https://app.stage.test-app.pan.panter.cloud"",
1857
+ "export KUBE_NAMESPACE="pan-test-app-stage"",
1858
+ "export KUBE_APP_NAME="app"",
1859
+ "export KUBE_APP_NAME_PREFIX=""",
1860
+ "export SECRET_KEY_BASE="$CL_stage_app_SECRET_KEY_BASE"",
1861
+ "export POSTGRESQL_PASSWORD="$CL_stage_app_POSTGRESQL_PASSWORD"",
1862
+ "export cloudsqlProxyCredentials="$CL_stage_app_cloudsqlProxyCredentials"",
1863
+ "export RAILS_ENV="production"",
1864
+ "export _ALL_ENV_VAR_KEYS="[\\"ENV_SHORT\\",\\"APP_DIR\\",\\"ENV_TYPE\\",\\"BUILD_INFO_BUILD_ID\\",\\"BUILD_INFO_BUILD_TIME\\",\\"BUILD_INFO_CURRENT_VERSION\\",\\"ROOT_URL\\",\\"HOST_INTERNAL\\",\\"HOST_CANONICAL\\",\\"ROOT_URL_INTERNAL\\",\\"KUBE_NAMESPACE\\",\\"KUBE_APP_NAME\\",\\"KUBE_APP_NAME_PREFIX\\",\\"SECRET_KEY_BASE\\",\\"POSTGRESQL_PASSWORD\\",\\"cloudsqlProxyCredentials\\",\\"RAILS_ENV\\"]"",
1865
+ "export RELEASE_NAME="pan-test-app-stage-app"",
1866
+ "export HELM_EXPERIMENTAL_OCI="1"",
1867
+ "export KUBE_DOCKER_IMAGE_PULL_SECRET="gitlab-registry-app"",
1868
+ "export HELM_GITLAB_CHART_NAME="/helm-charts/the-panter-chart"",
1869
+ "export HELM_ARGS=""",
1870
+ "export COMPONENT_NAME="app"",
1871
+ "export BUILD_ID="$(git describe --tags 2>/dev/null || git rev-parse HEAD)"",
1872
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
1873
+ "kubectl config set-cluster "kube-pan-test-app-stage-app" --server="$CL_stage_app_KUBE_URL" --certificate-authority <(echo $CL_stage_app_KUBE_CA_PEM | base64 -d) --embed-certs=true",
1874
+ "kubectl config set-credentials "kube-pan-test-app-stage-app" --token="$CL_stage_app_KUBE_TOKEN"",
1875
+ "kubectl config set-context "kube-pan-test-app-stage-app" --cluster="kube-pan-test-app-stage-app" --user="kube-pan-test-app-stage-app" --namespace="pan-test-app-stage"",
1876
+ "kubectl config use-context "kube-pan-test-app-stage-app"",
1877
+ "kubernetesDelete",
1878
+ "echo 'Disabling component in Dependency Track'",
1879
+ "/dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" disable "pan-test-app/app" "https://app.stage.test-app.pan.panter.cloud" || true",
1880
+ "echo "CL_GITLAB_ENVIRONMENT_URL=https://app.stage.test-app.pan.panter.cloud" >> gitlab_environment.env",
1881
+ ],
1882
+ "stage": "stop stage",
1883
+ "variables": {
1884
+ "GIT_STRATEGY": "none",
1885
+ "KUBERNETES_CPU_REQUEST": "0.22",
1886
+ "KUBERNETES_MEMORY_LIMIT": "400Mi",
1887
+ "KUBERNETES_MEMORY_REQUEST": "200Mi",
1888
+ },
1889
+ },
1890
+ "app 🧾 sbom | prod ": {
1891
+ "allow_failure": true,
1892
+ "artifacts": {
1893
+ "paths": [
1894
+ "__sbom.json",
1895
+ ],
1896
+ },
1897
+ "image": "aquasec/trivy:0.38.3",
1898
+ "interruptible": true,
1899
+ "needs": [],
1900
+ "retry": {
1901
+ "max": 2,
1902
+ "when": [
1903
+ "runner_system_failure",
1904
+ "stuck_or_timeout_failure",
1905
+ ],
1906
+ },
1907
+ "script": [
1908
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
1909
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
1910
+ "trivy fs --quiet --format cyclonedx --output "__sbom.json" .",
1911
+ ],
1912
+ "stage": "build",
1913
+ "variables": {},
1914
+ },
1915
+ "app 🧾 sbom | stage ": {
1916
+ "allow_failure": true,
1917
+ "artifacts": {
1918
+ "paths": [
1919
+ "__sbom.json",
1920
+ ],
1921
+ },
1922
+ "image": "aquasec/trivy:0.38.3",
1923
+ "interruptible": true,
1924
+ "needs": [],
1925
+ "retry": {
1926
+ "max": 2,
1927
+ "when": [
1928
+ "runner_system_failure",
1929
+ "stuck_or_timeout_failure",
1930
+ ],
1931
+ },
1932
+ "script": [
1933
+ "echo -e "\\e[0Ksection_start:$(date +%s):injectvars[collapsed=true]\\r\\e[0KInjecting variables"",
1934
+ "echo -e "\\e[0Ksection_end:$(date +%s):injectvars\\r\\e[0K"",
1935
+ "trivy fs --quiet --format cyclonedx --output "__sbom.json" .",
1936
+ ],
1937
+ "stage": "build",
1938
+ "variables": {},
1939
+ },
1940
+ },
1941
+ "stages": [
1942
+ "setup",
1943
+ "setup dev",
1944
+ "setup review",
1945
+ "setup stage",
1946
+ "setup prod",
1947
+ "test",
1948
+ "test dev",
1949
+ "test review",
1950
+ "test stage",
1951
+ "test prod",
1952
+ "build",
1953
+ "build dev",
1954
+ "build review",
1955
+ "build stage",
1956
+ "build prod",
1957
+ "deploy",
1958
+ "deploy dev",
1959
+ "deploy review",
1960
+ "deploy stage",
1961
+ "deploy prod",
1962
+ "verify",
1963
+ "verify dev",
1964
+ "verify review",
1965
+ "verify stage",
1966
+ "verify prod",
1967
+ "rollback",
1968
+ "rollback dev",
1969
+ "rollback review",
1970
+ "rollback stage",
1971
+ "rollback prod",
1972
+ "stop",
1973
+ "stop dev",
1974
+ "stop review",
1975
+ "stop stage",
1976
+ "stop prod",
1977
+ ],
1978
+ "variables": {
1979
+ "ARTIFACT_COMPRESSION_LEVEL": "fast",
1980
+ "CACHE_COMPRESSION_LEVEL": "fast",
1981
+ "FF_USE_FASTZIP": "true",
1982
+ "GIT_DEPTH": "1",
1983
+ "TRANSFER_METER_FREQUENCY": "5s",
1984
+ },
1985
+ "workflow": {
1986
+ "rules": [
1987
+ {
1988
+ "if": "$CI_COMMIT_TAG",
1989
+ },
1990
+ {
1991
+ "if": "$CI_COMMIT_MESSAGE =~ /^chore\\(release\\).*/",
1992
+ "when": "never",
1993
+ },
1994
+ {
1995
+ "if": "$CI_PIPELINE_SOURCE == "schedule"",
1996
+ "when": "never",
1997
+ },
1998
+ {
1999
+ "if": "$CI_COMMIT_BRANCH =~ /^[0-9]+.([0-9]+|x).x$/",
2000
+ },
2001
+ {
2002
+ "if": "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH",
2003
+ },
2004
+ {
2005
+ "if": "$CI_MERGE_REQUEST_ID",
2006
+ },
2007
+ ],
2008
+ },
2009
+ },
2010
+ }
2011
+ `;