αααααΈααΆααΆααα·ααααααΆααα»ααααααααααααΆααΉααααΆαα αααΆααααΆααΆαααΆααααααααααα·ααΈααααα’αααααΆαααΆααααααΆαα αα·αα αΆαααΆα α α αΎαααα»αααααΆα αααΎαααΆαααααΎααΆαααααααααααααααα·α’ααααααααααΆααΌαααα αΎα ααα»αααααα αααα»αααΆαααααΌααΆααα Habr αα·αααΆαααΌααααααααα½ααααααΆαααααααΎαααΆααα½ααααα αΌαααααΆααααα·αααααααα·αααααααααα αααα»α ααΈααααΆααα·ααααααααΆ (ααααααααααααΎα) GitLab αα·α JUnit α ααααααααα αααααααα!
ααΆαααααΆα
ααΆααααΌααααα»αααΌααααααααα·αααα½αα ααα½αα
- αααααΆααααααα·ααΈααΆααα’ααααααααΎαααααΎαααΆαααΎ Kubernetes ααΎαααΉααα·α αΆαααΆααΆαααΆαααααααααΎαααΆαααΎα αααααΆαα ααΆααααααααααααααα
- αααααΆααααΆααααα»α αα·αααΆαααααααΆα ααΎαααααΎ
werf (ααΎβαα·ααΆαβααΈβαααααβα αααααΆαα ααΆαααααααα ααΆβααβααΆαβαααβαααααβαααααααα·βαααβααΆ Helm ααααΌαβααΆαβα αΌαβαα½α)α - αααα»αααΉααα·αα αΌααα αααα»αααααααΆααααα’α·αααααΆααααααΎαααΆαααααΎαααααααΆαααααααααα αααα»αααααΈααααααΎα α’αα·αα·αααααααααΆαααααΎαααααααααααα½αα―α α αΎαααΎαααααΆααααααΆααΆααΆαααΎαααααΎαααΆααααααα½αααααα»ααααα (αα·αααααααΆααααααΆαααΆααααααααααΌαααααΆαα αααα»αααααΎαααα αΌαααααΆ)α
ααΎααααΆααααΌαα
αααααααααΆαααΉαααΎααα
ααΌα
α’αααΈ?
- ααΆααααΆααααααα·ααΈ - ααΎαααΉααα»αα ααααΆααα·αααααΆααααααΆααααΆααααα
- ααΆαααααααΆααααααα·ααΈαα αααααααααααααΆα ααααα‘ααααα ααααα Kubernetes α αΎαα αΆααααααΎαααΆαααααα
- ααΆααααααααααααα»αα»ααΆα αα·αααΆαααααααΆαααΆααα JUnit ααΆαα½α GitLab α
- ααΆααα»αααααααααααΆααααααΎαααΈαα»αα
α₯α‘αΌαααα - ααΎααααΈα’αα»αααα!
ααΆααααααααΌα
GitLab αααΈα’αΆα
α
αΌαα
αΆααααααΎαααΆαα½αααΉαααααααα½αα .gitlab-ci.yaml
ααααα·αααααΆα’αααΈααΆαααΆαααααααΆααααααα·ααΈ αα·αααΆαααΆαααααααααααα»αααααΎαααΆαα ααΆαβα
α»αβαααααΈβααΆαβααααβααααΆαβαα
βααΆβααΆαβαααααΊβααααΆααβααΆαα ααΌα
ααααβααΆβααααΌαβααΆαβαααααβααααααβαααβααα·βαααααα
variables:
# ΠΎΠ±ΡΡΠ²Π»ΡΠ΅ΠΌ Π²Π΅ΡΡΠΈΡ werf, ΠΊΠΎΡΠΎΡΡΡ ΡΠΎΠ±ΠΈΡΠ°Π΅ΠΌΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ
WERF_VERSION: "1.0 beta"
.base_deploy: &base_deploy
script:
# ΡΠΎΠ·Π΄Π°Π΅ΠΌ namespace Π² K8s, Π΅ΡΠ»ΠΈ Π΅Π³ΠΎ Π½Π΅Ρ
- kubectl --context="${WERF_KUBE_CONTEXT}" get ns ${CI_ENVIRONMENT_SLUG} || kubectl create ns ${CI_ENVIRONMENT_SLUG}
# Π·Π°Π³ΡΡΠΆΠ°Π΅ΠΌ werf ΠΈ Π΄Π΅ΠΏΠ»ΠΎΠΈΠΌ β ΠΏΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅ ΠΎΠ± ΡΡΠΎΠΌ ΡΠΌ. Π² Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ
# (https://werf.io/how_to/gitlab_ci_cd_integration.html#deploy-stage)
- type multiwerf && source <(multiwerf use ${WERF_VERSION})
- werf version
- type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
- werf deploy --stages-storage :local
--namespace ${CI_ENVIRONMENT_SLUG}
--set "global.commit_ref_slug=${CI_COMMIT_REF_SLUG:-''}"
# ΠΏΠ΅ΡΠ΅Π΄Π°Π΅ΠΌ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ `run_tests`
# ΠΎΠ½Π° Π±ΡΠ΄Π΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡΡΡ Π² ΡΠ΅Π½Π΄Π΅ΡΠ΅ Helm-ΡΠ΅Π»ΠΈΠ·Π°
--set "global.run_tests=${RUN_TESTS:-no}"
--set "global.env=${CI_ENVIRONMENT_SLUG}"
# ΠΈΠ·ΠΌΠ΅Π½ΡΠ΅ΠΌ timeout (Π±ΡΠ²Π°ΡΡ Π΄ΠΎΠ»Π³ΠΈΠ΅ ΡΠ΅ΡΡΡ) ΠΈ ΠΏΠ΅ΡΠ΅Π΄Π°Π΅ΠΌ Π΅Π³ΠΎ Π² ΡΠ΅Π»ΠΈΠ·
--set "global.ci_timeout=${CI_TIMEOUT:-900}"
--timeout ${CI_TIMEOUT:-900}
dependencies:
- Build
.test-base: &test-base
extends: .base_deploy
before_script:
# ΡΠΎΠ·Π΄Π°Π΅ΠΌ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡ Π΄Π»Ρ Π±ΡΠ΄ΡΡΠ΅Π³ΠΎ ΠΎΡΡΠ΅ΡΠ°, ΠΈΡΡ
ΠΎΠ΄Ρ ΠΈΠ· $CI_COMMIT_REF_SLUG
- mkdir /mnt/tests/${CI_COMMIT_REF_SLUG} || true
# Π²ΡΠ½ΡΠΆΠ΄Π΅Π½Π½ΡΠΉ ΠΊΠΎΡΡΡΠ»Ρ, Ρ.ΠΊ. GitLab Ρ
ΠΎΡΠ΅Ρ ΠΏΠΎΠ»ΡΡΠΈΡΡ Π°ΡΡΠ΅ΡΠ°ΠΊΡΡ Π² ΡΠ²ΠΎΠ΅ΠΌ build-dirβΠ΅
- mkdir ./tests || true
- ln -s /mnt/tests/${CI_COMMIT_REF_SLUG} ./tests/${CI_COMMIT_REF_SLUG}
after_script:
# ΠΏΠΎΡΠ»Π΅ ΠΎΠΊΠΎΠ½ΡΠ°Π½ΠΈΡ ΡΠ΅ΡΡΠΎΠ² ΡΠ΄Π°Π»ΡΠ΅ΠΌ ΡΠ΅Π»ΠΈΠ· Π²ΠΌΠ΅ΡΡΠ΅ Ρ JobβΠΎΠΌ
# (ΠΈ, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Π΅Π³ΠΎ ΠΈΠ½ΡΡΠ°ΡΡΡΡΠΊΡΡΡΠΎΠΉ)
- type multiwerf && source <(multiwerf use ${WERF_VERSION})
- werf version
- type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
- werf dismiss --namespace ${CI_ENVIRONMENT_SLUG} --with-namespace
# ΠΌΡ ΡΠ°Π·ΡΠ΅ΡΠ°Π΅ΠΌ ΠΏΠ°Π΄Π΅Π½ΠΈΡ, Π½ΠΎ Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΡΠ΄Π΅Π»Π°ΡΡ ΠΈΠ½Π°ΡΠ΅
allow_failure: true
variables:
RUN_TESTS: 'yes'
# Π·Π°Π΄Π°Π΅ΠΌ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ Π² werf
# (https://werf.io/how_to/gitlab_ci_cd_integration.html#infrastructure)
WERF_KUBE_CONTEXT: 'admin@stage-cluster'
tags:
# ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ ΡΠ°Π½Π½Π΅Ρ Ρ ΡΠ΅Π³ΠΎΠΌ `werf-runner`
- werf-runner
artifacts:
# ΡΡΠ΅Π±ΡΠ΅ΡΡΡ ΡΠΎΠ±ΡΠ°ΡΡ Π°ΡΡΠ΅ΡΠ°ΠΊΡ Π΄Π»Ρ ΡΠΎΠ³ΠΎ, ΡΡΠΎΠ±Ρ Π΅Π³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π±ΡΠ»ΠΎ ΡΠ²ΠΈΠ΄Π΅ΡΡ
# Π² ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½Π΅ ΠΈ ΡΠΊΠ°ΡΠ°ΡΡ β Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, Π΄Π»Ρ Π±ΠΎΠ»Π΅Π΅ Π²Π΄ΡΠΌΡΠΈΠ²ΠΎΠ³ΠΎ ΠΈΠ·ΡΡΠ΅Π½ΠΈΡ
paths:
- ./tests/${CI_COMMIT_REF_SLUG}/*
# Π°ΡΡΠ΅ΡΠ°ΠΊΡΡ ΡΡΠ°ΡΡΠ΅ Π½Π΅Π΄Π΅Π»ΠΈ Π±ΡΠ΄ΡΡ ΡΠ΄Π°Π»Π΅Π½Ρ
expire_in: 7 day
# Π²Π°ΠΆΠ½ΠΎ: ΡΡΠΈ ΡΡΡΠΎΠΊΠΈ ΠΎΡΠ²Π΅ΡΠ°ΡΡ Π·Π° ΠΏΠ°ΡΡΠΈΠ½Π³ ΠΎΡΡΠ΅ΡΠ° GitLabβΠΎΠΌ
reports:
junit: ./tests/${CI_COMMIT_REF_SLUG}/report.xml
# Π΄Π»Ρ ΡΠΏΡΠΎΡΠ΅Π½ΠΈΡ Π·Π΄Π΅ΡΡ ΠΏΠΎΠΊΠ°Π·Π°Π½Ρ Π²ΡΠ΅Π³ΠΎ Π΄Π²Π΅ ΡΡΠ°Π΄ΠΈΠΈ
# Π² ΡΠ΅Π°Π»ΡΠ½ΠΎΡΡΠΈ ΠΆΠ΅ Ρ Π²Π°Ρ ΠΈΡ
Π±ΡΠ΄Π΅Ρ Π±ΠΎΠ»ΡΡΠ΅ β ΠΊΠ°ΠΊ ΠΌΠΈΠ½ΠΈΠΌΡΠΌ ΠΈΠ·-Π·Π° Π΄Π΅ΠΏΠ»ΠΎΡ
stages:
- build
- tests
build:
stage: build
script:
# ΡΠ±ΠΎΡΠΊΠ° β ΡΠ½ΠΎΠ²Π° ΠΏΠΎ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ ΠΏΠΎ werf
# (https://werf.io/how_to/gitlab_ci_cd_integration.html#build-stage)
- type multiwerf && source <(multiwerf use ${WERF_VERSION})
- werf version
- type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
- werf build-and-publish --stages-storage :local
tags:
- werf-runner
except:
- schedules
run tests:
<<: *test-base
environment:
# "ΡΠ°ΠΌΠ° ΡΠΎΠ»Ρ" ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½ΠΈΡ namespaceβΠ°
# (https://docs.gitlab.com/ce/ci/variables/predefined_variables.html)
name: tests-${CI_COMMIT_REF_SLUG}
stage: tests
except:
- schedules
Kubernetes
α₯α‘αΌαααααα
αααα»ααα .helm/templates
ααααααααΎα YAML ααΆαα½α Job - tests-job.yaml
β ααΎααααΈααααΎαααΆαααΆαααααΎααααα αα·αααααΆα Kubernetes αααααΆααααΌαααΆαα ααΌαααΎαααΆααααααααααααΆααααΈααΆαααΆααααααΈα
{{- if eq .Values.global.run_tests "yes" }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: tests-script
data:
tests.sh: |
echo "======================"
echo "${APP_NAME} TESTS"
echo "======================"
cd /app
npm run test:ci
cp report.xml /app/test_results/${CI_COMMIT_REF_SLUG}/
echo ""
echo ""
echo ""
chown -R 999:999 /app/test_results/${CI_COMMIT_REF_SLUG}
---
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Chart.Name }}-test
annotations:
"helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-weight": "2"
"werf/watch-logs": "true"
spec:
activeDeadlineSeconds: {{ .Values.global.ci_timeout }}
backoffLimit: 1
template:
metadata:
name: {{ .Chart.Name }}-test
spec:
containers:
- name: test
command: ['bash', '-c', '/app/tests.sh']
{{ tuple "application" . | include "werf_container_image" | indent 8 }}
env:
- name: env
value: {{ .Values.global.env }}
- name: CI_COMMIT_REF_SLUG
value: {{ .Values.global.commit_ref_slug }}
- name: APP_NAME
value: {{ .Chart.Name }}
{{ tuple "application" . | include "werf_container_env" | indent 8 }}
volumeMounts:
- mountPath: /app/test_results/
name: data
- mountPath: /app/tests.sh
name: tests-script
subPath: tests.sh
tolerations:
- key: dedicated
operator: Exists
- key: node-role.kubernetes.io/master
operator: Exists
restartPolicy: OnFailure
volumes:
- name: data
persistentVolumeClaim:
claimName: {{ .Chart.Name }}-pvc
- name: tests-script
configMap:
name: tests-script
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ .Chart.Name }}-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Mi
storageClassName: {{ .Chart.Name }}-{{ .Values.global.commit_ref_slug }}
volumeName: {{ .Values.global.commit_ref_slug }}
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: {{ .Values.global.commit_ref_slug }}
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 10Mi
local:
path: /mnt/tests/
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- kube-master
persistentVolumeReclaimPolicy: Delete
storageClassName: {{ .Chart.Name }}-{{ .Values.global.commit_ref_slug }}
{{- end }}
ααααΆαααααααααΆ ααΆααα·αααααΆαα
αααα»αααΆααααααααα? αα
αααααΆαααααααΆα ααΎααααααΎαααα ααααααααα½αααααααααΆαααααααα (ααΆααααΌαααΆαα
ααα’α»ααααα αΆααα
αααα»α .gitlab-ci.yaml
- tests-${CI_COMMIT_REF_SLUG}
) α αΎαααααααΆα
ααα
- ConfigMap ααΆαα½αααααααΈαααΆααααα;
- ααΆαααΆα ααΆαα½αααΉαααΆααα·αααααΆα’αααΈ pod αα·αααΆαααααΆααααααΆααααααΆαα
command
αααααΎαααααααΎαααΆαααΆαααααΎααααα; - PV αα·α PVCαααα’αα»ααααΆαα±ααα’ααααααααΆαα»ααα·ααααααααΆαααααα
ααα
α·ααααα»αααΆααααΎααααααααααααΆαααΆαα½α if
αα
ααΎαααααΌαααααΆααααα αΆα - ααααα
ααΆαα―αααΆα YAML ααααααααααααααΌαααΆα Helm ααΆαα½ααααααα·ααΈααααΌαααααααΌαααΆααα»ααα
αααα»α αααα
αααΆα ααΆααα
ααΆααΎααααΈαα»αα±αααα½αααΆααααΌαααΆαααΆαααααααΆαααα‘α»ααααααααΎαααααα αααααΊα
{{- if ne .Values.global.run_tests "yes" }}
---
Ρ Π΄ΡΡΠ³ΠΎΠΉ ΡΠΌΠ»ΠΈΠΊ
{{- end }}
ααααααΆαααΆαααααααααα·αααΎααΆαααααΎααααα ααΆαααΆαα αααααΆαα ααΆαααααααααα½αα ααα½α (α§ααΆα ααα Redis, RabbitMQ, Mongo, PostgreSQL ... ) - YAMLs αααααα½αααα’αΆα ααΆ αα·αααΆα αα·αα ααΆαααααααΆααα½αααΆαα αααα»αααα·ααΆααΆαααΆαααααααααα... ααΆααααααααΌααα½αααΆααΆααααα’αααααΎαααΆααα
ααΆααααα α»αααααα
αααααΆααα ααΆααααα»ααα·αααΆαααΆαααααααΆααααααααΎ werf ααααΎαααΆααααααΆαααααααα αα αα
ααΎ build server (ααΆαα½α gitlab-runner) α αΎα pod with tests ααααΌαααΆαααΆααα±ααααααΎαααΆααα
ααΎ master α’αααααΉαααααΌααααααΎα directory /mnt/tests
αα
ααΎααα αΎαα±ααααΆαα
α’αααααα, α§ααΆα αααααΆαααα NFS. α§ααΆα ααααααα’α·αααΆαα½αααΉαααΆαααααααα’αΆα
ααααΆααα
αααα»α
ααααααααΉαααΆα
user@kube-master:~$ cat /etc/exports | grep tests
/mnt/tests IP_gitlab-builder/32(rw,nohide,insecure,no_subtree_check,sync,all_squash,anonuid=999,anongid=998)
user@gitlab-runner:~$ cat /etc/fstab | grep tests
IP_kube-master:/mnt/tests /mnt/tests nfs4 _netdev,auto 0 0
ααααΆαααααΆααααΆααα αΆαααΆααααΆαα ααααααα NFS αααααααΆαααα ααΎ gitlab-runner α αΎααααααΆααααααα‘αΎαααΆαα αααα»α pods α
ααΆαααααααααΆαα
α’ααααααα ααααΆαααα»ααα½αααΆα ααα»α’αααΈααΆαααΆααααΎα±ααα’αααΈαααΆαααΆααααα»αααααΆαααααααααΎα Job ααααα·αααΎα’αααααααΆααααα’αΆα ααααΎαααΆαααααααΈαααΆαα½αααΉαααΆαααααΎααααααααααααΆαααα ααΎαααααα·ααΈαααααα? α ααααΎαβααΊβααΆβααΏαβααΌα ααΆα ...
ααΆαααααΎααααααα½αα ααα½ααααααΌαα±ααααΆαααΆαα αΌααα ααΆααα αααααΆαα ααΆαααααααα (MongoDB, RabbitMQ, PostgreSQL ααα) ααΎααααΈαααααααααΆααααΆαα½αααΆααααΎαααΆαααΆαααααΉαααααΌαα ααΎαααααΎα±ααααΆαααααΎαααααααααα½αααααα½α - ααΆαα½ααα·ααΈααΆαααααααα ααΆααΆααααα½αααΆαααααα αΌαα’αααααΆαααααααααααααα ααααααααΈααΎαααααΎαααα½αααΆα αααααααΆα αα·ααΈααΆαααααααΆαααααααΆα (αααααΈααΆααααΎ NFS ααΆαααααΆαααααααααααα) α
αααααα
ααΎβααΎαβααΉαβααΎαβα’αααΈβαααβααΎαβα’αα»ααααβααΆαβαααααβαα ααΆααααααααβαααβααΆαβαααα α?
ααααΎαααα αΌαααααΆααΉααααα αΆααααα·αα·αααααααααααΆααααΆαααααΎαααααααααΎαααΆααα αααα»ααααααα α»αααααααααα»αααααααΆα
ααα α»αααΈαα½ααα’αΆα
α
α»α
αα
ααΈααααααααΆααααααααΆααααα’α·αα
NBα α’αααα’αΆααααααα
α·ααααα»αααΆααααΉααααααΆααααΎαααΆααΎααααα»αααΆααααααααααα·ααΈ NodeJS α αΎααα
αααα»αααΌαααα’αααααα - .NET... αα»αααααΆααααα’αΎαα ααααΆααααααΆααααααα½αααααΆααααα
αα’ααααα αα·αααΆαααα α»αααααΌαααΆαααααΎααααα»αααΆαααΆααααααααααα·ααΈααααΌαα‘αΎα ααα»αααααα½αααααααΌαααΆαααααααΎααα
αααα»ααα½αααααααααα
ααα ααααΈααααα·ααααΆα
ααΌα αααα’αααα’αΆα ααΎαααααΆαα’αααΈαααα»αααααΆααα!
ααΆαααααΆααα ααααα·αααΎα’αααααΆαα§ααααααααααΌαααααα½α
α αΎα α αΎαααΆααααΎαααΆα ααα»ααααα’ααααα·αααααΌαααΆα Kubernetes αα ααΆαααααΆααααΆαααΆαααααααΆαα½αααΆααΉαααΆαα·α
αα
ααΆαααΆααααααΆαααΆααα·αααααΆαα
ααΈαααα α αΎααα
αααα»α
PS
ααΌαα’αΆαααααααα ααΎαααααααααααΎαα
- Β«
ααΆαα’αα»αααα CI/CD ααα’αααα»αααΆαα½α Kubernetes αα·α GitLab (ααΆααα·αα·αααα‘αΎααα·α αα·ααααΆαααΆαααααΈααα’αΌ) Β» - Β«
αααααΉααααααΆαααααααΎαααα αΌαααΆαααΆαααααΆαααααα½ααα αααα»α GitLab CI Β» - Β«
GitLab CI αααααΆααααΆααα½ααααα αΌαααΆαααααααααΆαα αα·αααΆαα ααα αΆααα αααα»αααα·ααααα "α
ααααα: www.habr.com