engelsystem/.gitlab-ci.yml

421 lines
10 KiB
YAML
Raw Normal View History

image: php
variables:
2018-08-20 23:21:02 +02:00
DOCKER_DRIVER: overlay2
2020-05-09 00:58:17 +02:00
TEST_IMAGE: ${CI_REGISTRY_IMAGE}/engelsystem:${CI_COMMIT_REF_SLUG}
TEST_IMAGE_NGINX: ${CI_REGISTRY_IMAGE}/nginx:${CI_COMMIT_REF_SLUG}
RELEASE_IMAGE: ${CI_REGISTRY_IMAGE}/engelsystem:latest
RELEASE_IMAGE_NGINX: ${CI_REGISTRY_IMAGE}/nginx:latest
MYSQL_DATABASE: engelsystem
MYSQL_USER: engel
MYSQL_PASSWORD: engelsystem
2017-11-25 10:53:50 +01:00
MYSQL_HOST: mariadb
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
2019-09-17 20:24:16 +02:00
MYSQL_INITDB_SKIP_TZINFO: "yes"
2018-08-20 23:21:02 +02:00
DOCROOT: /var/www/
2018-08-20 23:21:02 +02:00
stages:
- validate
2018-08-20 23:21:02 +02:00
- build
- test
- release
- deploy
2020-05-09 13:08:53 +02:00
- deploy-production
2020-09-01 14:40:09 +02:00
- stop
2020-05-09 13:08:53 +02:00
#
# Validation
#
2018-08-20 23:21:02 +02:00
check-style:
image: composer:latest
stage: validate
before_script:
- composer --no-ansi global require squizlabs/php_codesniffer
- export PATH=$PATH:$COMPOSER_HOME/vendor/bin
script:
- phpcs -p --no-colors --basepath="$PWD"
2020-05-13 18:40:03 +02:00
check-editorconfig:
image: mstruebing/editorconfig-checker
stage: validate
script:
- ec -v
validate-composer:
image: composer:latest
stage: validate
script:
- composer --no-ansi validate --strict
validate-yarn:
image: node:alpine
stage: validate
before_script:
- yarn global add package-json-validator
- export PATH=$PATH:~/.yarn/bin
script:
- pjv
2020-05-09 13:08:53 +02:00
#
# Build
#
2018-08-20 23:21:02 +02:00
.docker_template: &docker_definition
image: docker:18
2018-08-20 23:21:02 +02:00
services:
- docker:18-dind
2018-08-20 23:21:02 +02:00
tags:
- dind
before_script:
2018-09-23 14:17:48 +02:00
- docker login -u gitlab-ci-token -p "${CI_JOB_TOKEN}" "${CI_REGISTRY}"
2020-05-09 00:58:17 +02:00
build-image-nginx:
2018-08-20 23:21:02 +02:00
<<: *docker_definition
stage: build
2020-09-01 14:40:09 +02:00
needs:
- check-editorconfig
- validate-yarn
2019-07-21 04:13:31 +02:00
artifacts:
name: "${CI_JOB_NAME}_${CI_JOB_ID}_assets"
expire_in: 1 day
paths:
- ./public/assets
2018-08-20 23:21:02 +02:00
script:
2020-05-09 00:58:17 +02:00
- docker build --pull -t "${TEST_IMAGE_NGINX}" -f docker/nginx/Dockerfile .
- docker push "${TEST_IMAGE_NGINX}"
- instance=$(docker create "${TEST_IMAGE_NGINX}")
2019-07-21 04:13:31 +02:00
- docker cp "${instance}:/var/www/public/assets" public/
- docker rm "${instance}"
build-image:
2018-08-20 23:21:02 +02:00
<<: *docker_definition
stage: build
2020-09-01 14:40:09 +02:00
needs:
- check-editorconfig
- validate-composer
- check-style
2018-08-20 23:21:02 +02:00
script:
- apk add -q git
- VERSION="$(git describe --abbrev=0 --tags)-${CI_COMMIT_REF_NAME}+${CI_PIPELINE_ID}.${CI_COMMIT_SHORT_SHA}"
2019-10-14 23:36:26 +02:00
- docker build --pull --build-arg VERSION="${VERSION}" -t "${TEST_IMAGE}" -f docker/Dockerfile .
- docker push "${TEST_IMAGE}"
2020-05-09 13:08:53 +02:00
#
# Test
#
audit-composer:
image: php:latest
stage: test
needs: [ ]
before_script:
- curl -Ls https://github.com/symfony/cli/releases/latest/download/symfony_linux_amd64.gz | gzip -d > /bin/symfony
- chmod +x /bin/symfony
script:
- symfony check:security --no-ansi
audit-yarn:
2020-09-01 14:40:09 +02:00
image: node:alpine
stage: test
2020-09-01 14:40:09 +02:00
needs: [ ]
script:
- yarn audit
2018-08-20 23:21:02 +02:00
test:
2018-09-23 14:17:48 +02:00
image: ${TEST_IMAGE}
stage: test
2020-09-01 14:40:09 +02:00
needs: [ build-image ]
2018-08-20 23:21:02 +02:00
services:
- mariadb:10.2
artifacts:
name: "${CI_JOB_NAME}_${CI_JOB_ID}"
expire_in: 1 week
2018-08-30 13:33:16 +02:00
when: always
paths:
- ./coverage/
- ./unittests.xml
reports:
junit: ./unittests.xml
coverage: '/^\s*Lines:\s*(\d+(?:\.\d+)?%)/'
2018-08-20 23:21:02 +02:00
before_script:
- apk add -q ${PHPIZE_DEPS} && pecl install pcov > /dev/null && docker-php-ext-enable pcov
2018-08-20 23:21:02 +02:00
- curl -sS https://getcomposer.org/installer | php -- --no-ansi --install-dir /usr/local/bin/ --filename composer
- cp -R tests/ phpunit.xml "${DOCROOT}"
2019-11-10 23:26:23 +01:00
- HOMEDIR=$PWD
2018-08-20 23:21:02 +02:00
- cd "${DOCROOT}"
2019-05-31 17:09:50 +02:00
- composer --no-ansi install
2018-09-02 17:56:19 +02:00
- ./bin/migrate
script:
2020-05-09 00:58:17 +02:00
- >-
php -d pcov.enabled=1 vendor/bin/phpunit -vvv --colors=never
--coverage-text --coverage-html "${HOMEDIR}/coverage/"
--log-junit "${HOMEDIR}/unittests.xml"
after_script:
- '"${DOCROOT}/bin/migrate" down'
2019-11-10 23:26:23 +01:00
dump-database:
image: ${TEST_IMAGE}
stage: test
needs: [ build-image ]
services:
- mariadb:10.2
artifacts:
expire_in: 1 week
paths:
- initial-install.sql
before_script:
- apk add -q mariadb-client
- HOMEDIR=$PWD
- cd "${DOCROOT}"
- ./bin/migrate
script:
- >-
mysqldump -h "${MYSQL_HOST}" -u "${MYSQL_USER}" -p"${MYSQL_PASSWORD}" "${MYSQL_DATABASE}"
> "${HOMEDIR}/initial-install.sql"
2020-05-09 13:08:53 +02:00
#
# Release
#
2018-08-20 23:21:02 +02:00
release-image:
<<: *docker_definition
stage: release
2020-09-01 14:40:09 +02:00
needs: [ test ]
dependencies: [ ]
2018-08-20 23:21:02 +02:00
script:
2018-09-23 14:17:48 +02:00
- docker pull "${TEST_IMAGE}"
- docker tag "${TEST_IMAGE}" "${RELEASE_IMAGE}"
- docker push "${RELEASE_IMAGE}"
2018-08-20 23:21:02 +02:00
only:
2021-03-14 12:07:34 +01:00
- main
2020-05-09 00:58:17 +02:00
release-image-nginx:
2018-08-20 23:21:02 +02:00
<<: *docker_definition
stage: release
2020-09-01 14:40:09 +02:00
needs:
- test
- build-image-nginx
dependencies: [ ]
2018-08-20 23:21:02 +02:00
script:
2020-05-09 00:58:17 +02:00
- docker pull "${TEST_IMAGE_NGINX}"
- docker tag "${TEST_IMAGE_NGINX}" "${RELEASE_IMAGE_NGINX}"
- docker push "${RELEASE_IMAGE_NGINX}"
2018-08-20 23:21:02 +02:00
only:
2021-03-14 12:07:34 +01:00
- main
2017-10-22 17:04:07 +02:00
.deploy_template: &deploy_definition
2020-05-09 13:08:53 +02:00
stage: release
2018-09-23 14:17:48 +02:00
image: ${TEST_IMAGE}
before_script:
- apk add -q bash rsync openssh-client
2018-08-20 23:21:02 +02:00
build-release-file:
<<: *deploy_definition
2020-05-09 13:08:53 +02:00
stage: release
2020-09-01 14:40:09 +02:00
needs:
- build-image
- build-image-nginx
- audit-yarn
- audit-composer
- test
- dump-database
2020-09-01 14:40:09 +02:00
dependencies:
- build-image
- build-image-nginx
- dump-database
artifacts:
2020-05-09 13:08:53 +02:00
name: release_${CI_COMMIT_REF_SLUG}_${CI_JOB_ID}_${CI_COMMIT_SHA}
expire_in: 1 week
paths:
- ./release/
script:
- rsync -vAax "${DOCROOT}" "${DOCROOT}/.babelrc" "${DOCROOT}/.browserslistrc" "initial-install.sql" release/
2019-07-21 04:13:31 +02:00
- rsync -vAax public/assets release/public/
pages:
image: node:alpine
stage: release
2020-09-01 14:40:09 +02:00
needs: [ test ]
dependencies: [ test ]
script:
- rm -rf public
- mv coverage public
- cp unittests.xml public/
artifacts:
expire_in: 1 week
paths:
- public
only:
2021-03-14 12:07:34 +01:00
- main
variables:
GIT_STRATEGY: none
2020-05-09 13:08:53 +02:00
#
# Deploy staging
#
.deploy_template_script:
# Configure SSH
- &deploy_template_script |-
eval $(ssh-agent -s) && echo "${SSH_PRIVATE_KEY}" | ssh-add -
rsync -vAax public/assets ${DOCROOT}/public/
cd "${DOCROOT}"
deploy:
<<: *deploy_definition
2020-05-09 13:08:53 +02:00
stage: deploy
2020-09-01 14:40:09 +02:00
needs: &deploy_needs
- release-image
- build-image-nginx
dependencies: *deploy_needs
environment:
name: staging
2018-08-20 23:21:02 +02:00
only:
2021-03-14 12:07:34 +01:00
- main
2017-10-22 17:04:07 +02:00
script:
# Check if deployment variables where set
2017-10-22 17:04:07 +02:00
- |-
if [ -z "${SSH_PRIVATE_KEY}" ] || [ -z "${STAGING_REMOTE}" ] || [ -z "${STAGING_REMOTE_PATH}" ]; then
2020-05-09 00:58:17 +02:00
echo "Skipping deployment"
2017-10-22 17:04:07 +02:00
exit
fi
2018-09-02 17:56:19 +02:00
- *deploy_template_script
# Deploy to server
2018-08-07 16:47:47 +02:00
- ./bin/deploy.sh -r "${STAGING_REMOTE}" -p "${STAGING_REMOTE_PATH}" -i "${CI_JOB_ID}-${CI_COMMIT_SHA}"
2017-10-22 17:04:07 +02:00
2020-05-09 13:08:53 +02:00
.kubectl_deployment: &kubectl_deployment
stage: deploy
image:
name: bitnami/kubectl:latest
2020-09-01 14:40:09 +02:00
entrypoint: [ '' ]
needs:
- test
- build-image
- build-image-nginx
2020-05-09 13:08:53 +02:00
before_script:
- &kubectl_deployment_script if [[ -z "${KUBE_INGRESS_BASE_DOMAIN}" ]]; then echo "Skipping deployment"; exit; fi
.deploy_k8s: &deploy_k8s
<<: *kubectl_deployment
2020-09-01 14:40:09 +02:00
dependencies: [ ]
2020-05-09 13:08:53 +02:00
artifacts:
name: deployment.yaml
expire_in: 1 day
when: always
paths:
- deployment.yaml
script:
# CI_ENVIRONMENT_URL is the URL configured in the GitLab environment
- export CI_ENVIRONMENT_URL="${CI_ENVIRONMENT_URL:-https://${CI_PROJECT_PATH_SLUG}.${KUBE_INGRESS_BASE_DOMAIN}/}"
- export CI_IMAGE=$RELEASE_IMAGE
- export CI_IMAGE_NGINX=$RELEASE_IMAGE_NGINX
- export CI_INGRESS_DOMAIN=$(echo "$CI_ENVIRONMENT_URL" | grep -oP '(?:https?://)?\K([^/]+)' | head -n1)
- export CI_INGRESS_PATH=$(echo "$CI_ENVIRONMENT_URL" | grep -oP '(?:https?://)?(?:[^/])+\K(.*)')
- export CI_KUBE_NAMESPACE=$KUBE_NAMESPACE
# Any available storage class like longhorn
- export CI_PVC_SC=${CI_PVC_SC:-"${CI_PVC_SC_LOCAL:-local-path}"}
- export CI_REPLICAS=${CI_REPLICAS_REVIEW:-${CI_REPLICAS:-2}}
- export CI_APP_NAME=${CI_APP_NAME:-Engelsystem}
- export CI_CLUSTER_ISSUER=${CI_CLUSTER_ISSUER:-letsencrypt}
2020-05-09 13:08:53 +02:00
- cp deployment.tpl.yaml deployment.yaml
- for env in ${!CI_*}; do sed -i "s#<${env}>#$(echo "${!env}"|head -n1)#g" deployment.yaml; done
- echo "Deploying to ${CI_ENVIRONMENT_URL}"
- kubectl apply -f deployment.yaml
- >-
kubectl -n $CI_KUBE_NAMESPACE wait --for=condition=Ready pods --timeout=${CI_WAIT_TIMEOUT:-5}m
-l app=$CI_PROJECT_PATH_SLUG -l tier=database
- >-
kubectl -n $CI_KUBE_NAMESPACE wait --for=condition=Ready pods --timeout=${CI_WAIT_TIMEOUT:-5}m
-l app=$CI_PROJECT_PATH_SLUG -l tier=application -l commit=$CI_COMMIT_SHORT_SHA
.deploy_k8s_stop: &deploy_k8s_stop
<<: *kubectl_deployment
2020-09-01 14:40:09 +02:00
stage: stop
dependencies: [ ]
2020-05-09 13:08:53 +02:00
variables:
GIT_STRATEGY: none
when: manual
script:
- kubectl delete all,ingress,pvc -l app=$CI_PROJECT_PATH_SLUG -l environment=$CI_ENVIRONMENT_SLUG
deploy-k8s-review:
<<: *deploy_k8s
environment:
name: review/${CI_COMMIT_REF_NAME}
on_stop: stop-k8s-review
auto_stop_in: 1 week
url: https://${CI_PROJECT_PATH_SLUG}-review.${KUBE_INGRESS_BASE_DOMAIN}/${CI_COMMIT_REF_SLUG}
variables:
CI_REPLICAS_REVIEW: 1
CI_APP_NAME: review/${CI_COMMIT_REF_NAME}
before_script:
- *kubectl_deployment_script
- RELEASE_IMAGE=$TEST_IMAGE
- RELEASE_IMAGE_NGINX=$TEST_IMAGE_NGINX
stop-k8s-review:
<<: *deploy_k8s_stop
2020-09-01 14:40:09 +02:00
needs: [ deploy-k8s-review ]
2020-05-09 13:08:53 +02:00
environment:
name: review/${CI_COMMIT_REF_NAME}
action: stop
#
# Deploy production
#
2018-08-20 23:21:02 +02:00
deploy-production:
<<: *deploy_definition
2020-05-09 13:08:53 +02:00
stage: deploy-production
2020-09-01 14:40:09 +02:00
needs:
- test
- audit-yarn
- audit-composer
- build-image
- build-image-nginx
dependencies:
- build-image
- build-image-nginx
environment:
name: production
when: manual
2018-08-20 23:21:02 +02:00
only:
2021-03-14 12:07:34 +01:00
- main
script:
# Check if deployment variables where set
- |-
if [ -z "${SSH_PRIVATE_KEY}" ] || [ -z "${PRODUCTION_REMOTE}" ] || [ -z "${PRODUCTION_REMOTE_PATH}" ]; then
2020-05-09 00:58:17 +02:00
echo "Skipping deployment"
exit
fi
2018-09-02 17:56:19 +02:00
- *deploy_template_script
# Deploy to server
2018-08-07 16:47:47 +02:00
- ./bin/deploy.sh -r "${PRODUCTION_REMOTE}" -p "${PRODUCTION_REMOTE_PATH}" -i "${CI_JOB_ID}-${CI_COMMIT_SHA}"
2020-05-09 13:08:53 +02:00
deploy-k8s-production:
<<: *deploy_k8s
stage: deploy-production
2020-09-01 14:40:09 +02:00
needs:
- release-image
- release-image-nginx
- audit-yarn
- audit-composer
2020-05-09 13:08:53 +02:00
environment:
name: production
on_stop: stop-k8s-production
when: manual
only:
2021-03-14 12:07:34 +01:00
- main
2020-05-09 13:08:53 +02:00
stop-k8s-production:
<<: *deploy_k8s_stop
2020-09-01 14:40:09 +02:00
needs: [ deploy-k8s-production ]
2020-05-09 13:08:53 +02:00
only:
2021-03-14 12:07:34 +01:00
- main
2020-05-09 13:08:53 +02:00
environment:
name: production
action: stop