image: php

variables:
  DOCKER_DRIVER: overlay2
  TEST_IMAGE: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}
  RELEASE_IMAGE: ${CI_REGISTRY_IMAGE}:latest
  MYSQL_DATABASE: engelsystem
  MYSQL_USER: engel
  MYSQL_PASSWORD: engelsystem
  MYSQL_HOST: mariadb
  MYSQL_RANDOM_ROOT_PASSWORD: "yes"
  MYSQL_INITDB_SKIP_TZINFO: "yes"
  DOCROOT: /var/www/

stages:
  - validate
  - build
  - test
  - release
  - deploy

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"

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

.docker_template: &docker_definition
  image: docker:18
  services:
    - docker:18-dind
  tags:
    - dind
  before_script:
    - docker login -u gitlab-ci-token -p "${CI_JOB_TOKEN}" "${CI_REGISTRY}"

build-image.nginx:
  <<: *docker_definition
  stage: build
  artifacts:
    name: "${CI_JOB_NAME}_${CI_JOB_ID}_assets"
    expire_in: 1 day
    paths:
      - ./public/assets
  script:
    - docker build --pull -t "${TEST_IMAGE}-nginx" -f docker/nginx/Dockerfile .
    - docker push "${TEST_IMAGE}-nginx"
    - instance=$(docker create "${TEST_IMAGE}-nginx")
    - docker cp "${instance}:/var/www/public/assets" public/
    - docker rm "${instance}"

build-image:
  <<: *docker_definition
  stage: build
  script:
    - apk add -q git
    - VERSION="$(git describe --abbrev=0 --tags)-${CI_COMMIT_REF_NAME}+${CI_PIPELINE_ID}.${CI_COMMIT_SHORT_SHA}"
    - docker build --pull --build-arg VERSION="${VERSION}" -t "${TEST_IMAGE}" -f docker/Dockerfile .
    - docker push "${TEST_IMAGE}"

audit-composer:
  image: ${TEST_IMAGE}
  stage: test
  before_script:
    - curl -sSo /usr/local/bin/security-checker https://get.sensiolabs.org/security-checker.phar
    - chmod +x /usr/local/bin/security-checker
    - cd "${DOCROOT}"
  script:
    - security-checker --no-ansi security:check

audit-yarn:
  image: node:10-alpine
  stage: test
  script:
    - yarn audit

test:
  image: ${TEST_IMAGE}
  stage: test
  services:
    - mariadb:10.2
  artifacts:
    name: "${CI_JOB_NAME}_${CI_JOB_ID}"
    expire_in: 1 week
    when: always
    paths:
      - ./coverage/
      - ./unittests.xml
    reports:
      junit: ./unittests.xml
  coverage: '/^\s*Lines:\s*(\d+(?:\.\d+)?%)/'
  before_script:
    - apk add -q ${PHPIZE_DEPS} && pecl install pcov > /dev/null && docker-php-ext-enable pcov
    - curl -sS https://getcomposer.org/installer | php -- --no-ansi --install-dir /usr/local/bin/ --filename composer
    - cp -R tests/ phpunit.xml "${DOCROOT}"
    - HOMEDIR=$PWD
    - cd "${DOCROOT}"
    - composer --no-ansi install
    - ./bin/migrate
  script:
    - php -d pcov.enabled=1 vendor/bin/phpunit -vvv --colors=never --coverage-text --coverage-html "${HOMEDIR}/coverage/" --log-junit "${HOMEDIR}/unittests.xml"
    - ./bin/migrate down

release-image:
  <<: *docker_definition
  stage: release
  script:
    - docker pull "${TEST_IMAGE}"
    - docker tag "${TEST_IMAGE}" "${RELEASE_IMAGE}"
    - docker push "${RELEASE_IMAGE}"
  only:
    - master

release-image.nginx:
  <<: *docker_definition
  stage: release
  script:
    - docker pull "${TEST_IMAGE}-nginx"
    - docker tag "${TEST_IMAGE}-nginx" "${RELEASE_IMAGE}-nginx"
    - docker push "${RELEASE_IMAGE}-nginx"
  only:
    - master

.deploy_template: &deploy_definition
  stage: deploy
  image: ${TEST_IMAGE}
  before_script:
    - apk add -q bash rsync openssh-client

.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}"

build-release-file:
  <<: *deploy_definition
  stage: deploy
  artifacts:
    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" release/
    - rsync -vAax public/assets release/public/

deploy-staging:
  <<: *deploy_definition
  environment:
    name: staging
  only:
    - master
  script:
    # Check if deployment variables where set
    - |-
      if [ -z "${SSH_PRIVATE_KEY}" ] || [ -z "${STAGING_REMOTE}" ] || [ -z "${STAGING_REMOTE_PATH}" ]; then
        echo "Skipping deployment";
        exit
      fi
    - *deploy_template_script
    # Deploy to server
    - ./bin/deploy.sh -r "${STAGING_REMOTE}" -p "${STAGING_REMOTE_PATH}" -i "${CI_JOB_ID}-${CI_COMMIT_SHA}"

deploy-production:
  <<: *deploy_definition
  environment:
    name: production
  when: manual
  only:
    - master
  script:
    # Check if deployment variables where set
    - |-
      if [ -z "${SSH_PRIVATE_KEY}" ] || [ -z "${PRODUCTION_REMOTE}" ] || [ -z "${PRODUCTION_REMOTE_PATH}" ]; then
        echo "Skipping deployment";
        exit
      fi
    - *deploy_template_script
    # Deploy to server
    - ./bin/deploy.sh -r "${PRODUCTION_REMOTE}" -p "${PRODUCTION_REMOTE_PATH}" -i "${CI_JOB_ID}-${CI_COMMIT_SHA}"