From ebf1b2c728e38fde1118783b0c1490bc067e05a7 Mon Sep 17 00:00:00 2001
From: owenbush <ojb@ukhhf.co.uk>
Date: Sat, 26 Dec 2020 15:18:52 -0700
Subject: [PATCH] Add circle CI config

---
 .circleci/build.sh             | 124 ++++++++++++++++++++++++++++++++
 .circleci/config.yml           | 127 +++++++++++++++++++++++++++++++++
 .circleci/deploy.sh            |  79 ++++++++++++++++++++
 .circleci/lint.sh              |  25 +++++++
 .circleci/process-artifacts.sh |  13 ++++
 .circleci/test.sh              |  53 ++++++++++++++
 6 files changed, 421 insertions(+)
 create mode 100755 .circleci/build.sh
 create mode 100644 .circleci/config.yml
 create mode 100755 .circleci/deploy.sh
 create mode 100755 .circleci/lint.sh
 create mode 100755 .circleci/process-artifacts.sh
 create mode 100755 .circleci/test.sh

diff --git a/.circleci/build.sh b/.circleci/build.sh
new file mode 100755
index 00000000..884d15b0
--- /dev/null
+++ b/.circleci/build.sh
@@ -0,0 +1,124 @@
+#!/usr/bin/env bash
+##
+# Build Drupal site using SQLite database, install current module and serve
+# using in-built PHP server.
+#
+# Allows to use the latest Drupal core as well as specified versions (for
+# testing backward compatibility).
+#
+# - builds Drupal site codebase with current module and it's dependencies.
+# - installs Drupal using SQLite database.
+# - starts in-built PHP-server
+# - enables module
+# - serves site
+# - generates one-time login link
+#
+# This script will re-build everything from scratch every time it runs.
+
+# shellcheck disable=SC2015,SC2094
+
+set -e
+
+#-------------------------------------------------------------------------------
+# Variables (passed from environment; provided for reference only).
+#-------------------------------------------------------------------------------
+
+# Directory where Drupal site will be built.
+BUILD_DIR="${BUILD_DIR:-build}"
+
+# Webserver hostname.
+WEBSERVER_HOST="${WEBSERVER_HOST:-localhost}"
+
+# Webserver port.
+WEBSERVER_PORT="${WEBSERVER_PORT:-8000}"
+
+# Drupal core version to use. If not provided - latest version will be used.
+# Must be coupled with DRUPAL_PROJECT_SHA below.
+DRUPAL_VERSION="${DRUPAL_VERSION:-}"
+
+# Commit SHA of the drupal-project to install custom core version. If not
+# provided - the latest version will be used.
+# Must be coupled with DRUPAL_VERSION above.
+DRUPAL_PROJECT_SHA="${DRUPAL_PROJECT_SHA:-}"
+
+# Drupal profile to use when installing site.
+DRUPAL_PROFILE="${DRUPAL_PROFILE:-standard}"
+
+# Module name, taken from .info file.
+MODULE="$(basename -s .info.yml -- ./*.info.yml)"
+
+# Database file path.
+DB_FILE="${DB_FILE:-/tmp/site_${MODULE}.sqlite}"
+
+#-------------------------------------------------------------------------------
+
+echo "==> Validate requirements."
+! command -v git > /dev/null && echo "ERROR: Git is required for this script to run." && exit 1
+! command -v php > /dev/null && echo "ERROR: PHP is required for this script to run." && exit 1
+! command -v composer > /dev/null && echo "ERROR: Composer (https://getcomposer.org/) is required for this script to run." && exit 1
+! command -v jq > /dev/null && echo "ERROR: jq (https://stedolan.github.io/jq/) is required for this script to run." && exit 1
+
+echo "==> Validate Composer config."
+composer validate --ansi --strict
+
+[ -d "${BUILD_DIR}" ] && echo "==> Remove existing ${BUILD_DIR} directory." && chmod -Rf 777 "${BUILD_DIR}" && rm -rf "${BUILD_DIR}"
+
+# Allow installing custom version of Drupal core, but only coupled with
+# drupal-project SHA (required to get correct dependencies).
+if [ -n "${DRUPAL_VERSION}" ] && [ -n "${DRUPAL_PROJECT_SHA}" ]; then
+  echo "==> Initialise Drupal site from the scaffold commit ${DRUPAL_PROJECT_SHA}."
+
+  git clone -n https://github.com/drupal-composer/drupal-project.git "${BUILD_DIR}"
+  git --git-dir="${BUILD_DIR}/.git" --work-tree="${BUILD_DIR}" checkout "${DRUPAL_PROJECT_SHA}"
+  rm -rf "${BUILD_DIR}/.git" > /dev/null
+
+  echo "==> Pin Drupal to a specific version ${DRUPAL_VERSION}."
+  sed_opts=(-i) && [ "$(uname)" == "Darwin" ] && sed_opts=(-i '')
+  sed "${sed_opts[@]}" 's|\(.*"drupal\/core"\): "\(.*\)",.*|\1: '"\"$DRUPAL_VERSION\",|" "${BUILD_DIR}/composer.json"
+  cat "${BUILD_DIR}/composer.json"
+
+  echo "==> Install dependencies."
+  php -d memory_limit=-1 "$(command -v composer)" --working-dir="${BUILD_DIR}" install
+else
+  echo "==> Initialise Drupal site from the latest scaffold."
+  php -d memory_limit=-1 "$(command -v composer)" create-project drupal-composer/drupal-project:8.x-dev "${BUILD_DIR}" --no-interaction
+fi
+
+echo "==> Install additional dev dependencies from module's composer.json."
+cat <<< "$(jq --indent 4 -M -s '.[0] * .[1]' composer.json "${BUILD_DIR}/composer.json")" > "${BUILD_DIR}/composer.json"
+php -d memory_limit=-1 "$(command -v composer)" --working-dir="${BUILD_DIR}" update --lock
+
+echo "==> Install other dev dependencies."
+cat <<< "$(jq --indent 4 '.extra["phpcodesniffer-search-depth"] = 10' "${BUILD_DIR}/composer.json")" > "${BUILD_DIR}/composer.json"
+php -d memory_limit=-1 "$(command -v composer)" --working-dir="${BUILD_DIR}" require --dev dealerdirect/phpcodesniffer-composer-installer
+
+echo "==> Start inbuilt PHP server at http://${WEBSERVER_HOST}:${WEBSERVER_PORT} in $(pwd)/${BUILD_DIR}/web."
+killall -9 php > /dev/null 2>&1 || true
+nohup php -S "${WEBSERVER_HOST}:${WEBSERVER_PORT}" -t "$(pwd)/${BUILD_DIR}/web" "$(pwd)/${BUILD_DIR}/web/.ht.router.php" > /tmp/php.log 2>&1 &
+sleep 4 # Waiting for the server to be ready.
+netstat_opts='-tulpn'; [ "$(uname)" == "Darwin" ] && netstat_opts='-anv' || true;
+netstat "${netstat_opts[@]}" | grep -q "${WEBSERVER_PORT}" || (echo "ERROR: Unable to start inbuilt PHP server" && cat /tmp/php.log && exit 1)
+curl -s -o /dev/null -w "%{http_code}" -L -I "http://${WEBSERVER_HOST}:${WEBSERVER_PORT}" | grep -q 200 || (echo "ERROR: Server is started, but site cannot be served" && exit 1)
+
+echo "==> Install Drupal into SQLite database ${DB_FILE}."
+"${BUILD_DIR}/vendor/bin/drush" -r "${BUILD_DIR}/web" si "${DRUPAL_PROFILE}" -y --db-url "sqlite://${DB_FILE}" --account-name=admin install_configure_form.enable_update_status_module=NULL install_configure_form.enable_update_status_emails=NULL
+"${BUILD_DIR}/vendor/bin/drush" -r "$(pwd)/${BUILD_DIR}/web" status
+
+echo "==> Symlink module code."
+rm -rf "${BUILD_DIR}/web/modules/${MODULE}"/* > /dev/null
+mkdir -p "${BUILD_DIR}/web/modules/${MODULE}"
+ln -s "$(pwd)"/* "${BUILD_DIR}/web/modules/${MODULE}" && rm "${BUILD_DIR}/web/modules/${MODULE}/${BUILD_DIR}"
+
+echo "==> Enable module ${MODULE}."
+"${BUILD_DIR}/vendor/bin/drush" -r "${BUILD_DIR}/web" pm:enable "${MODULE}" -y
+"${BUILD_DIR}/vendor/bin/drush" -r "${BUILD_DIR}/web" cr
+
+# Visit site to pre-warm caches.
+curl -s "http://${WEBSERVER_HOST}:${WEBSERVER_PORT}" > /dev/null
+
+echo -n "==> One-time login link: "
+"${BUILD_DIR}/vendor/bin/drush" -r "${BUILD_DIR}/web" -l "http://${WEBSERVER_HOST}:${WEBSERVER_PORT}" uli --no-browser
+
+echo
+echo "==> Build finished. The site is available at http://${WEBSERVER_HOST}:${WEBSERVER_PORT}."
+echo
diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 00000000..eccb0601
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,127 @@
+# @see https://github.com/integratedexperts/drupal_circleci
+version: 2
+aliases:
+  # SSH deployment key fingerprint from CircleCI App -> Project -> Settings -> SSH Permissions.
+  # Replace the value for your project.
+  - &deploy_ssh_fingerprint "2d:71:4d:aa:4d:34:38:b5:8f:af:ca:3b:d4:82:6a:21"
+  - &container_config
+    working_directory: ~/project
+    docker:
+      - image: circleci/php:7.4-cli-browsers
+
+job-build: &job-build
+  steps:
+    - checkout
+    - run: |
+        sudo -E apt-get update && sudo -E apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev jq \
+        && sudo -E docker-php-ext-install -j$(nproc) iconv \
+        && if [ "$(php -r "echo PHP_MAJOR_VERSION;")" -gt 5 ] && [ "$(php -r "echo PHP_MINOR_VERSION;")" -gt 3 ] ; then sudo -E docker-php-ext-configure gd --with-freetype --with-jpeg; else sudo -E docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/; fi \
+        && sudo -E docker-php-ext-install -j$(nproc) gd
+    - run: .circleci/build.sh
+    - run: .circleci/lint.sh
+    - run: .circleci/test.sh
+    - run:
+        command: .circleci/process-artifacts.sh
+        when: always
+    - store_test_results:
+        path: /tmp/test_results
+        when: always
+    - store_artifacts:
+        path: /tmp/artifacts
+        when: always
+
+jobs:
+  build-php-7.4:
+    <<: *container_config
+    <<: *job-build
+
+  build-php-7.3:
+    <<: *container_config
+    docker:
+      - image: circleci/php:7.3-cli-browsers
+    <<: *job-build
+
+  build-php-7.2:
+    <<: *container_config
+    docker:
+      - image: circleci/php:7.2-cli-browsers
+    <<: *job-build
+
+  build-php-7.4-legacy:
+    <<: *container_config
+    environment:
+      DRUPAL_VERSION: 8.8.10
+      DRUPAL_PROJECT_SHA: 8.x
+    <<: *job-build
+
+  build-php-7.3-legacy:
+    <<: *container_config
+    docker:
+      - image: circleci/php:7.3-cli-browsers
+    environment:
+      DRUPAL_VERSION: 8.8.10
+      DRUPAL_PROJECT_SHA: 8.x
+    <<: *job-build
+
+  build-php-7.2-legacy:
+    <<: *container_config
+    docker:
+      - image: circleci/php:7.2-cli-browsers
+    environment:
+      DRUPAL_VERSION: 8.8.10
+      DRUPAL_PROJECT_SHA: 8.x
+    <<: *job-build
+
+  deploy:
+    <<: *container_config
+    environment:
+      DEPLOY_SSH_FINGERPRINT: *deploy_ssh_fingerprint
+    steps:
+      - checkout
+      - add_ssh_keys:
+          fingerprints:
+            - *deploy_ssh_fingerprint
+      - run: DEPLOY_BRANCH=${CIRCLE_BRANCH} .circleci/deploy.sh
+
+workflows:
+  version: 2
+  main:
+    jobs:
+      - build-php-7.4:
+          filters:
+            tags:
+              only: /.*/
+      - build-php-7.3:
+          filters:
+            tags:
+              only: /.*/
+      - build-php-7.2:
+          filters:
+            tags:
+              only: /.*/
+      - build-php-7.4-legacy:
+          filters:
+            tags:
+              only: /.*/
+      - build-php-7.3-legacy:
+          filters:
+            tags:
+              only: /.*/
+      - build-php-7.2-legacy:
+          filters:
+            tags:
+              only: /.*/
+      - deploy:
+          requires:
+            - build-php-7.4
+            - build-php-7.3
+            - build-php-7.2
+            - build-php-7.4-legacy
+            - build-php-7.3-legacy
+            - build-php-7.2-legacy
+          filters:
+            tags:
+              only: /.*/
+            branches:
+              # 7.x, 8.x, 7.x-1.x, 8.x-1.x, 7.x-2.x, 8.x-2.x, ci
+              only: /^(?:7|8)\.x(?:\-[0-9]+\.x)?|ci$/
diff --git a/.circleci/deploy.sh b/.circleci/deploy.sh
new file mode 100755
index 00000000..fbbeae49
--- /dev/null
+++ b/.circleci/deploy.sh
@@ -0,0 +1,79 @@
+#!/usr/bin/env bash
+##
+# Deploy code to a remote repository.
+#
+# - configures local git
+# - adds deployment SSH key to SSH agent
+# - force-pushes code to a remote code repository branch
+#
+# It is a good practice to create a separate Deployer user with own SSH key for
+# every project.
+#
+# Add the following variables through CircleCI UI.
+# - DEPLOY_USER_NAME - name of the user who will be committing to a remote repository.
+# - DEPLOY_USER_EMAIL - email address of the user who will be committing to a remote repository.
+# - DEPLOY_REMOTE - remote repository to push code to.
+# - DEPLOY_PROCEED - set to 1 if the deployment should proceed. Useful for testing CI configuration before an actual code push.
+
+set -e
+
+#-------------------------------------------------------------------------------
+# Variables (passed from environment; provided for reference only).
+#-------------------------------------------------------------------------------
+
+# Name of the user who will be committing to a remote repository.
+DEPLOY_USER_NAME="${DEPLOY_USER_NAME}"
+
+# Email address of the user who will be committing to a remote repository.
+DEPLOY_USER_EMAIL="${DEPLOY_USER_EMAIL}"
+
+# Remote repository to push code to.
+DEPLOY_REMOTE="${DEPLOY_REMOTE:-}"
+
+# Git branch to deploy. If not provided - current branch will be used.
+DEPLOY_BRANCH="${DEPLOY_BRANCH:-}"
+
+# The fingerprint of the SSH key of the user on behalf of which the deployment
+# is performed.
+DEPLOY_SSH_FINGERPRINT="${DEPLOY_SSH_FINGERPRINT:-}"
+
+# Set to 1 if the deployment should proceed. Useful for testing CI configuration
+# before an actual code push.
+DEPLOY_PROCEED="${DEPLOY_PROCEED:-0}"
+
+#-------------------------------------------------------------------------------
+
+[ -z "${DEPLOY_USER_NAME}" ] && echo "ERROR: Missing required value for DEPLOY_USER_NAME" && exit 1
+[ -z "${DEPLOY_USER_EMAIL}" ] && echo "ERROR: Missing required value for DEPLOY_USER_EMAIL" && exit 1
+[ -z "${DEPLOY_REMOTE}" ] && echo "ERROR: Missing required value for DEPLOY_REMOTE" && exit 1
+[ -z "${DEPLOY_SSH_FINGERPRINT}" ] && echo "ERROR: Missing required value for DEPLOY_SSH_FINGERPRINT" && exit 1
+
+[ "${DEPLOY_PROCEED}" != "1" ] && echo "==> Skipping deployment because \$DEPLOY_PROCEED is not set to 1" && exit 0
+
+# Configure git and SSH to connect to remote servers for deployment.
+mkdir -p "${HOME}/.ssh/"
+echo -e "Host *\n\tStrictHostKeyChecking no\n" > "${HOME}/.ssh/config"
+DEPLOY_SSH_FILE="${DEPLOY_SSH_FINGERPRINT//:}"
+DEPLOY_SSH_FILE="${HOME}/.ssh/id_rsa_${DEPLOY_SSH_FILE//\"}"
+[ ! -f "${DEPLOY_SSH_FILE}" ] && echo "ERROR: Unable to find Deploy SSH key file ${DEPLOY_SSH_FILE}." && exit 1
+if [ -z "${SSH_AGENT_PID}" ]; then eval "$(ssh-agent)"; fi
+ssh-add -D > /dev/null
+ssh-add "${DEPLOY_SSH_FILE}"
+
+# Configure git user name and email, but only if not already set.
+[ "$(git config --global user.name)" == "" ] && echo "==> Configuring global git user name ${DEPLOY_USER_NAME}." && git config --global user.name "${DEPLOY_USER_NAME}"
+[ "$(git config --global user.email)" == "" ] && echo "==> Configuring global git user email ${DEPLOY_USER_EMAIL}." && git config --global user.email "${DEPLOY_USER_EMAIL}"
+
+# Set git to push to a matching remote branch.
+git config --global push.default matching
+
+echo "==> Adding remote ${DEPLOY_REMOTE}."
+git remote add deployremote "${DEPLOY_REMOTE}"
+
+echo "==> Deploying to remote ${DEPLOY_REMOTE}."
+# shellcheck disable=SC2086
+git push --force --tags deployremote ${DEPLOY_BRANCH}
+
+echo
+echo "==> Deployment finished."
+echo
diff --git a/.circleci/lint.sh b/.circleci/lint.sh
new file mode 100755
index 00000000..edc89d07
--- /dev/null
+++ b/.circleci/lint.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+##
+# Run lint checks.
+#
+
+set -e
+
+#-------------------------------------------------------------------------------
+# Variables (passed from environment; provided for reference only).
+#-------------------------------------------------------------------------------
+
+# Directory where Drupal site will be built.
+BUILD_DIR="${BUILD_DIR:-build}"
+
+# Module name, taken from .info file.
+MODULE="$(basename -s .info.yml -- ./*.info.yml)"
+
+#-------------------------------------------------------------------------------
+
+echo "==> Lint code."
+build/vendor/bin/phpcs \
+  -s \
+  --standard=Drupal,DrupalPractice \
+  --extensions=module,php,install,inc,test,info.yml,js \
+  "build/web/modules/${MODULE}"
diff --git a/.circleci/process-artifacts.sh b/.circleci/process-artifacts.sh
new file mode 100755
index 00000000..ba84e002
--- /dev/null
+++ b/.circleci/process-artifacts.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+##
+# Process test artifacts.
+#
+# This runs only in CircleCI.
+#
+set -e
+
+if [ -d "$(pwd)/build/web/sites/simpletest/browser_output" ]; then
+  echo "==> Copying Simpletest test artifacts"
+  mkdir -p /tmp/artifacts/simpletest
+  cp -Rf "$(pwd)/build/web/sites/simpletest/browser_output/." /tmp/artifacts/simpletest
+fi
diff --git a/.circleci/test.sh b/.circleci/test.sh
new file mode 100755
index 00000000..c17c8c3c
--- /dev/null
+++ b/.circleci/test.sh
@@ -0,0 +1,53 @@
+#!/usr/bin/env bash
+##
+# Run tests.
+#
+
+set -e
+
+#-------------------------------------------------------------------------------
+# Variables (passed from environment; provided for reference only).
+#-------------------------------------------------------------------------------
+
+# Directory where Drupal site will be built.
+BUILD_DIR="${BUILD_DIR:-build}"
+
+# Webserver hostname.
+WEBSERVER_HOST="${WEBSERVER_HOST:-localhost}"
+
+# Webserver port.
+WEBSERVER_PORT="${WEBSERVER_PORT:-8000}"
+
+# Module name, taken from .info file.
+MODULE="$(basename -s .info.yml -- ./*.info.yml)"
+
+# Test database file path.
+TEST_DB_FILE="${TEST_DB_FILE:-/tmp/test.sqlite}"
+
+# Directory to store test results.
+TEST_RESULTS_DIR="${TEST_RESULTS_DIR:-/tmp/test_results/simpletest}"
+
+#-------------------------------------------------------------------------------
+
+echo "==> Run tests."
+
+# Do not fail if there are no tests.
+[ ! -d "tests" ] && echo "==> No tests were found. Skipping." && exit 0
+
+# Re-create test results directory.
+rm -rf "${TEST_RESULTS_DIR}" > /dev/null
+mkdir -p "${TEST_RESULTS_DIR}"
+
+# Remove existing test DB file.
+rm -f "${TEST_DB_FILE}" > /dev/null
+
+php "./${BUILD_DIR}/web/core/scripts/run-tests.sh" \
+  --sqlite "${TEST_DB_FILE}" \
+  --dburl "sqlite://localhost/${TEST_DB_FILE}" \
+  --url "http://${WEBSERVER_HOST}:${WEBSERVER_PORT}" \
+  --non-html \
+  --xml "${TEST_RESULTS_DIR}" \
+  --color \
+  --verbose \
+  --suppress-deprecations \
+  --module "${MODULE}"
-- 
GitLab