-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path.gitlab-ci.yml
353 lines (321 loc) · 11.2 KB
/
.gitlab-ci.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
---
# cSpell:ignore urllib unprotect interruptible hostvars keyscan
stages:
- validate
- provision
- install
- destroy
- release
default:
image: alpine:latest
before_script: &default_before_script
- apk -U upgrade
variables:
GIT_SUBMODULE_STRATEGY: recursive
TF_IN_AUTOMATION: "true"
TF_INPUT: "false"
GL_TF_BE: https://gitlab.com/api/v4/projects/31099306/terraform/state
TF_HTTP_PASSWORD: $CI_JOB_TOKEN
.lint:
stage: validate
image: alpine:3.18
variables:
PIP_CACHE_DIR: $CI_PROJECT_DIR/.cache/pip
PRE_COMMIT_HOME: $CI_PROJECT_DIR/.cache/pre-commit
GITLAB_PRIVATE_TOKEN: $GL_TOKEN
# Skip protect-first-parent pre-commit hook until `[ERROR] caught error 1 on line 69 of ...: FIRST_PARENT="$(git show-ref -s "${BASE}")"` is fixed
SKIP: check-hooks-apply,protect-first-parent
before_script:
- *default_before_script
- apk --no-cache add ansible bash curl git go grep libffi-dev npm py-pip python3-dev shellcheck shfmt terraform unzip
- python3 -m venv .venv
- source .venv/bin/activate
- pip install -r requirements.txt
- npm install -g markdownlint-cli
- curl -s https://raw.githubusercontent.com/terraform-linters/tflint/master/install_linux.sh | bash
- ansible-galaxy collection install -r requirements.yml
script:
- pre-commit run -a --hook-stage manual
cache:
- key: default
paths:
- $PIP_CACHE_DIR
unprotect: true
- key:
files:
- requirements.txt
paths:
- .venv
when: always
- key:
files:
- .pre-commit-config.yaml
paths:
- $PRE_COMMIT_HOME
unprotect: true
when: always
interruptible: true
lint:
extends: [.lint]
variables:
SKIP: check-hooks-apply,protect-first-parent,anti-todo
rules:
- if: $CI_PIPELINE_SOURCE != 'merge_request_event'
lint-merge-request:
extends: [.lint]
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
.test:
stage: validate
.test-alpine:
extends: [.test]
before_script:
- *default_before_script
- apk --no-cache add bats git
.test-ubuntu:
extends: [.test]
image: ubuntu:latest
before_script:
- apt-get update && apt-get upgrade -y
- apt-get install -y bats git
.test-full:
script:
- scripts/test tests/full.set
interruptible: true
rules:
- if: $CI_PIPELINE_SOURCE != "schedule"
.test-nightly:
script:
- scripts/test tests/nightly.set
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
test-alpine-full:
extends: [.test-alpine, .test-full]
test-alpine-nightly:
extends: [.test-alpine, .test-nightly]
test-ubuntu-full:
extends: [.test-ubuntu, .test-full]
test-ubuntu-nightly:
extends: [.test-ubuntu, .test-nightly]
.provision-env:
stage: provision
image:
name: hashicorp/terraform:light
entrypoint:
- /usr/bin/env
- PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
script:
- echo "Provision **$CI_ENVIRONMENT_NAME** environment \`$CI_ENVIRONMENT_SLUG\` (tier $CI_ENVIRONMENT_TIER) at <$CI_ENVIRONMENT_URL>"
- cd terraform
- terraform init -reconfigure -backend-config="address=$GL_TF_BE/$CI_ENVIRONMENT_SLUG" -backend-config="lock_address=$GL_TF_BE/$CI_ENVIRONMENT_SLUG/lock" -backend-config="unlock_address=$GL_TF_BE/$CI_ENVIRONMENT_SLUG/lock"
- terraform apply -auto-approve -var="ENV_SLUG=$CI_ENVIRONMENT_SLUG" -var="ENV_TIER=$CI_ENVIRONMENT_TIER"
cache:
key: $CI_COMMIT_REF_SLUG
paths:
- terraform/.terraform
.install-env:
stage: install
image: gableroux/ansible:latest
before_script:
- *default_before_script
- apk --no-cache add git jq
- pip install hcloud
- ansible-galaxy collection install -r requirements.yml
- ansible-galaxy role install -r requirements.yml
script:
- echo "Install **$CI_ENVIRONMENT_NAME** environment \`$CI_ENVIRONMENT_SLUG\` (tier $CI_ENVIRONMENT_TIER) at <$CI_ENVIRONMENT_URL>"
- sed -i "s/env-slug/$CI_ENVIRONMENT_SLUG/" ansible/hcloud.yml
- SSH_HOST_LIST=$(ansible-inventory -i ansible/hcloud.yml --list | jq -r '._meta.hostvars | with_entries(.value |= .ipv4) | join(",")')
- |
if [ -n "$SSH_HOST_LIST" ]; then
echo "Install IPs: $SSH_HOST_LIST"
eval $(ssh-agent -s)
echo "$GL_CI_SSH_KEY" | tr -d '\r' | ssh-add -
mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keyscan "$SSH_HOST_LIST" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
ansible -u gitlab-ci -i ansible/hcloud.yml env -m ansible.builtin.ping
ansible-playbook -u gitlab-ci -i ansible/hcloud.yml ansible/playbook.yml
fi
.destroy-env:
stage: destroy
image:
name: hashicorp/terraform:light
entrypoint:
- /usr/bin/env
- PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
variables:
GIT_STRATEGY: none
before_script:
- *default_before_script
- apk --no-cache add git
script:
- echo "Destroy **$CI_ENVIRONMENT_NAME** environment \`$CI_ENVIRONMENT_SLUG\` (tier $CI_ENVIRONMENT_TIER) at <$CI_ENVIRONMENT_URL>"
- |
if [ ! -d .git ]; then
git init -b main
git remote add origin $CI_REPOSITORY_URL
git fetch origin $CI_COMMIT_SHA --depth=1
git reset --hard FETCH_HEAD
fi
- cd terraform
- terraform init -reconfigure -backend-config="address=$GL_TF_BE/$CI_ENVIRONMENT_SLUG" -backend-config="lock_address=$GL_TF_BE/$CI_ENVIRONMENT_SLUG/lock" -backend-config="unlock_address=$GL_TF_BE/$CI_ENVIRONMENT_SLUG/lock"
- terraform destroy -auto-approve -var="ENV_SLUG=$CI_ENVIRONMENT_SLUG" -var="ENV_TIER=$CI_ENVIRONMENT_TIER"
cache:
key: $CI_COMMIT_REF_SLUG
paths:
- terraform/.terraform
.env-prod:
environment:
name: Production
url: https://example.com
rules:
- if: $CI_COMMIT_TAG =~ /^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
resource_group: production
.env-stg:
environment:
name: Staging
url: https://$CI_ENVIRONMENT_SLUG.example.com
rules:
- if: $CI_COMMIT_BRANCH == "main" && $CI_PIPELINE_SOURCE != "schedule"
resource_group: staging
.env-test:
environment:
name: Testing/$CI_COMMIT_REF_SLUG
url: https://$CI_ENVIRONMENT_SLUG.example.com
rules:
- if: $CI_COMMIT_TAG =~ /^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
resource_group: testing/$CI_COMMIT_REF_SLUG
.env-dev:
before_script:
- *default_before_script
- apk --no-cache add bash curl
environment:
name: Development/$CI_COMMIT_REF_SLUG
url: https://$CI_ENVIRONMENT_SLUG.example.com
rules:
- if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "main"
resource_group: development/$CI_COMMIT_REF_SLUG
provision-prod:
extends: [.provision-env, .env-prod]
install-prod:
extends: [.install-env, .env-prod]
needs:
- provision-prod
provision-stg:
extends: [.provision-env, .env-stg]
install-stg:
extends: [.install-env, .env-stg]
needs:
- provision-stg
provision-test:
extends: [.provision-env, .env-test]
environment:
name: Testing/$CI_COMMIT_REF_SLUG
on_stop: destroy-test
auto_stop_in: 1 week
install-test:
extends: [.install-env, .env-test]
environment:
name: Testing/$CI_COMMIT_REF_SLUG
needs:
- provision-test
destroy-test:
extends: [.destroy-env, .env-test]
environment:
name: Testing/$CI_COMMIT_REF_SLUG
action: stop
needs:
- provision-test
- install-test
rules:
- if: $CI_COMMIT_TAG =~ /^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
when: manual
provision-dev:
extends: [.provision-env, .env-dev]
script:
- |
if scripts/deploy-env; then
echo "Provision **$CI_ENVIRONMENT_NAME** environment \`$CI_ENVIRONMENT_SLUG\` (tier $CI_ENVIRONMENT_TIER) at <$CI_ENVIRONMENT_URL>"
cd terraform
terraform init -reconfigure -backend-config="address=$GL_TF_BE/$CI_ENVIRONMENT_SLUG" -backend-config="lock_address=$GL_TF_BE/$CI_ENVIRONMENT_SLUG/lock" -backend-config="unlock_address=$GL_TF_BE/$CI_ENVIRONMENT_SLUG/lock"
terraform apply -auto-approve -var="ENV_SLUG=$CI_ENVIRONMENT_SLUG" -var="ENV_TIER=$CI_ENVIRONMENT_TIER"
fi
environment:
name: Development/$CI_COMMIT_REF_SLUG
on_stop: destroy-dev
auto_stop_in: 1 day
install-dev:
extends: [.install-env, .env-dev]
before_script:
- *default_before_script
- apk --no-cache add bash curl git jq
- pip install hcloud
- ansible-galaxy collection install -r requirements.yml
- ansible-galaxy role install -r requirements.yml
script:
- |
if scripts/deploy-env; then
echo "Install **$CI_ENVIRONMENT_NAME** environment \`$CI_ENVIRONMENT_SLUG\` (tier $CI_ENVIRONMENT_TIER) at <$CI_ENVIRONMENT_URL>"
sed -i "s/env-slug/$CI_ENVIRONMENT_SLUG/" ansible/hcloud.yml
SSH_HOST_LIST=$(ansible-inventory -i ansible/hcloud.yml --list | jq -r '._meta.hostvars | with_entries(.value |= .ipv4) | join(",")')
if [ -n "$SSH_HOST_LIST" ]; then
echo "Install IPs: $SSH_HOST_LIST"
eval $(ssh-agent -s)
echo "$GL_CI_SSH_KEY" | tr -d '\r' | ssh-add -
mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keyscan "$SSH_HOST_LIST" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
ansible -u gitlab-ci -i ansible/hcloud.yml env -m ansible.builtin.ping
ansible-playbook -u gitlab-ci -i ansible/hcloud.yml ansible/playbook.yml
fi
fi
needs:
- provision-dev
destroy-dev:
extends: [.destroy-env, .env-dev]
before_script:
- *default_before_script
- apk --no-cache add bash curl git
script:
- |
if [ ! -d .git ]; then
git init -b main
git remote add origin $CI_REPOSITORY_URL
git fetch origin $CI_COMMIT_SHA --depth=1
git reset --hard FETCH_HEAD
git submodule init
git submodule update
fi
if scripts/deploy-env; then
echo "Destroy **$CI_ENVIRONMENT_NAME** environment \`$CI_ENVIRONMENT_SLUG\` (tier $CI_ENVIRONMENT_TIER) at <$CI_ENVIRONMENT_URL>"
cd terraform
terraform init -reconfigure -backend-config="address=$GL_TF_BE/$CI_ENVIRONMENT_SLUG" -backend-config="lock_address=$GL_TF_BE/$CI_ENVIRONMENT_SLUG/lock" -backend-config="unlock_address=$GL_TF_BE/$CI_ENVIRONMENT_SLUG/lock"
terraform destroy -auto-approve -var="ENV_SLUG=$CI_ENVIRONMENT_SLUG" -var="ENV_TIER=$CI_ENVIRONMENT_TIER"
fi
environment:
name: Development/$CI_COMMIT_REF_SLUG
action: stop
needs:
- install-dev
- provision-dev
rules:
- if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "main"
when: manual
allow_failure: true
release:
stage: release
image:
name: node:alpine
entrypoint: [""]
before_script:
- *default_before_script
- apk --no-cache add git
- npm install -g semantic-release @semantic-release/gitlab @semantic-release/git @semantic-release/changelog
script:
- npx semantic-release
rules:
- if: $CI_COMMIT_BRANCH =~ /^(((0|[1-9]\d*)\.)(((0|[1-9]\d*|x)\.)?x)|main|next(-major)?|beta|alpha)$/ && $CI_PIPELINE_SOURCE != "schedule"
resource_group: release