accounts/.gitlab-ci.yml
2024-12-02 13:14:22 +01:00

282 lines
7.6 KiB
YAML

image: thecodingmachine/php:8.3-v4-cli
stages:
- prepare
- testing
- build
- deploy
variables:
APP_IMAGE_NAME: "$CI_REGISTRY_IMAGE/app"
WEB_IMAGE_NAME: "$CI_REGISTRY_IMAGE/web"
DB_IMAGE_NAME: "$CI_REGISTRY_IMAGE/db"
PHP_EXTENSION_INTL: 1
PHP_EXTENSION_IMAGICK: 1
#######################
# Shared script steps #
#######################
# GitLab do not supports bash syntax in the "variables" definitions,
# so we use custom step to define all necessary environment variables
.defineVars: &defineVars |-
export VERSION="${CI_COMMIT_TAG:-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHORT_SHA}}"
export APP_VERSIONED_IMAGE_NAME="$APP_IMAGE_NAME:$VERSION"
export APP_LATEST_IMAGE_NAME="$APP_IMAGE_NAME:latest"
export WEB_VERSIONED_IMAGE_NAME="$WEB_IMAGE_NAME:$VERSION"
export WEB_LATEST_IMAGE_NAME="$WEB_IMAGE_NAME:latest"
export DB_VERSIONED_IMAGE_NAME="$DB_IMAGE_NAME:$VERSION"
export DB_LATEST_IMAGE_NAME="$DB_IMAGE_NAME:latest"
.dockerLogin: &dockerLogin |-
docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
.installSentry: &installSentry |-
curl -sL https://sentry.io/get-cli/ | bash
.setupSSH: &setupSSH |-
mkdir ~/.ssh
echo -e "Host *\n StrictHostKeyChecking no\n" > ~/.ssh/config
eval $(ssh-agent -s)
echo "$SSH_DEPLOY_KEY" | tr -d '\r' | ssh-add -
###################
# Steps to extend #
###################
.vendorCache: &vendorCache
key: composer
paths:
- vendor
policy: pull
#################
# Prepare stage #
#################
Composer:
stage: prepare
cache:
<<: *vendorCache
policy: pull-push
before_script:
- composer config github-oauth.github.com "$GITHUB_TOKEN"
script:
- composer install --ignore-platform-reqs
#################
# Testing stage #
#################
PHP-CS-Fixer:
stage: testing
cache:
- *vendorCache
- key: php-cs-fixer-$CI_COMMIT_REF_SLUG
fallback_keys:
- php-cs-fixer-$CI_DEFAULT_BRANCH
paths:
- .php-cs-fixer.cache
when: always
script:
- vendor/bin/php-cs-fixer fix -v --dry-run
Codeception:
stage: testing
cache: *vendorCache
services:
- name: redis:4.0.10-alpine
alias: redis
- name: bitnami/mariadb:10.3.20-debian-9-r4
alias: db
variables:
# App config
DB_HOST: "db"
DB_DATABASE: "ely_accounts_test"
DB_USER: "ely_accounts_tester"
DB_PASSWORD: "ely_accounts_tester_password"
REDIS_HOST: "redis"
REDIS_PORT: "6379"
# MariaDB config
ALLOW_EMPTY_PASSWORD: "yes"
MARIADB_DATABASE: "ely_accounts_test"
MARIADB_USER: "ely_accounts_tester"
MARIADB_PASSWORD: "ely_accounts_tester_password"
before_script:
# Install wait-for-it script
- sudo curl "https://raw.githubusercontent.com/vishnubob/wait-for-it/81b1373f17855/wait-for-it.sh" -o /usr/local/bin/wait-for-it
- sudo chmod a+x /usr/local/bin/wait-for-it
# Add SVG support (remove after https://github.com/thecodingmachine/docker-images-php/issues/393 will be resolved)
- sudo apt update
- sudo apt install -y libmagickcore-6.q16-6-extra
script:
- php yii rbac/generate
- wait-for-it "${DB_HOST}:3306" -s -t 0 -- php yii migrate/up --interactive=0
- vendor/bin/codecept run
PHPStan:
stage: testing
cache:
- *vendorCache
- key: phpstan-$CI_COMMIT_REF_SLUG
fallback_keys:
- phpstan-$CI_DEFAULT_BRANCH
paths:
- .phpstan
when: on_success
before_script:
- |
echo -e "includes: [phpstan.dist.neon]\nparameters:\n tmpDir: .phpstan\n reportUnmatchedIgnoredErrors: false" > phpstan.neon
script:
- vendor/bin/codecept build
- vendor/bin/phpstan analyse --no-progress --memory-limit 2G
###############
# Build stage #
###############
Docker:
stage: build
image: docker:20.10.21
services:
- docker:20.10.21-dind
variables:
# Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
DOCKER_HOST: tcp://docker:2376
DOCKER_TLS_CERTDIR: "/certs"
before_script:
- *defineVars
- *dockerLogin
- sed -i -e "s/{{PLACE_VERSION_HERE}}/$VERSION/g" common/config/config.php
script:
# Download previous images to use them as a cache
- docker pull "$APP_LATEST_IMAGE_NAME" || true
- docker pull "$WEB_LATEST_IMAGE_NAME" || true
- docker pull "$DB_LATEST_IMAGE_NAME" || true
# Build images
- >
docker build .
--pull
--target app
--build-arg "build_env=prod"
--cache-from "$APP_LATEST_IMAGE_NAME"
-t "$APP_VERSIONED_IMAGE_NAME"
-t "$APP_LATEST_IMAGE_NAME"
- >
docker build .
--pull
--target web
--build-arg "build_env=prod"
--cache-from "$APP_VERSIONED_IMAGE_NAME"
--cache-from "$WEB_LATEST_IMAGE_NAME"
-t "$WEB_VERSIONED_IMAGE_NAME"
-t "$WEB_LATEST_IMAGE_NAME"
- >
docker build .
--pull
--target db
--build-arg "build_env=prod"
--cache-from "$APP_VERSIONED_IMAGE_NAME"
--cache-from "$WEB_VERSIONED_IMAGE_NAME"
--cache-from "$DB_LATEST_IMAGE_NAME"
-t "$DB_VERSIONED_IMAGE_NAME"
-t "$DB_LATEST_IMAGE_NAME"
# Push images to the registry
- docker push $APP_VERSIONED_IMAGE_NAME
- docker push $APP_LATEST_IMAGE_NAME
- docker push $WEB_VERSIONED_IMAGE_NAME
- docker push $WEB_LATEST_IMAGE_NAME
- docker push $DB_VERSIONED_IMAGE_NAME
- docker push $DB_LATEST_IMAGE_NAME
rules:
- if: '$CI_COMMIT_TAG'
when: on_success
- if: '$CI_COMMIT_BRANCH == "master"'
when: on_success
- if: '$CI_COMMIT_MESSAGE =~ /\[deploy.*\]/'
when: on_success
# Default:
- when: never
##########
# Deploy #
##########
.beforeSentryDeploy: &beforeSentryDeploy |-
sentry-cli releases new $VERSION
sentry-cli releases set-commits --commit "elyby/accounts@${CI_COMMIT_SHA}" $VERSION
.afterSentryDeploy: &afterSentryDeploy |-
sentry-cli releases deploys $VERSION new -e $CI_ENVIRONMENT_NAME
sentry-cli releases finalize $VERSION
.deployJob:
stage: deploy
image: docksal/ssh-agent:1.3
needs:
- Docker
variables:
GIT_STRATEGY: none
before_script:
- *defineVars
- *installSentry
- *setupSSH
script:
- *beforeSentryDeploy
# Escape $ with backslash to prevent value evaluation from CI container.
# We're not using $APP_LATEST_IMAGE_NAME because on remote server might be
# a different semantic of preferred image version tag
- |
ssh -J deploy@ely.by:4534 -p 722 "root@$VM_HOST_NAME" /bin/bash << EOF
set -e
cd "$VM_DEPLOY_PATH"
docker pull "$APP_VERSIONED_IMAGE_NAME"
docker pull "$WEB_VERSIONED_IMAGE_NAME"
docker tag "$APP_VERSIONED_IMAGE_NAME" "$APP_IMAGE_NAME:latest"
docker tag "$WEB_VERSIONED_IMAGE_NAME" "$WEB_IMAGE_NAME:latest"
docker-compose stop app worker cron
docker-compose rm -fv app worker cron
docker-compose up -d --scale worker=3 app worker cron
docker-compose stop web
docker-compose rm -fv web
docker-compose up -d web
EOF
- *afterSentryDeploy
Dev:
extends:
- .deployJob
environment:
name: Development
variables:
VM_HOST_NAME: playground.ely.local
VM_DEPLOY_PATH: /srv/dev.account.ely.by
rules:
- if: '$CI_COMMIT_TAG'
when: on_success
- if: '$CI_COMMIT_BRANCH == "master"'
when: on_success
- if: '$CI_COMMIT_MESSAGE =~ /\[deploy dev\]/'
when: on_success
# Default:
- when: never
Prod:
extends:
- .deployJob
environment:
name: Production
variables:
VM_HOST_NAME: accounts.ely.local
VM_DEPLOY_PATH: /srv
rules:
- if: '$CI_COMMIT_BRANCH != "master"'
when: never
- if: '$CI_COMMIT_MESSAGE =~ /\[deploy\]/'
when: on_success
# Default:
- when: manual