diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 54d6032..d94be74 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -15,7 +15,6 @@ default: stages: - build - - publish variables: # Drupal variables. @@ -24,6 +23,8 @@ variables: DRUPAL_CURRENT: '9.3' DRUPAL_CURRENT_PHP: '8.0' DRUPAL_NEXT: '10.0-rc' + # Specific Drupal 10 rc, remove when released. + DRUPAL_NEXT_IMAGE_TAG: '10.0' DRUPAL_NEXT_PHP: '8.1' # Docker variables. DOCKER_HOST: tcp://docker:2375 @@ -35,16 +36,13 @@ variables: value: "1" description: Publish the image to docker, set 0 to not publish. -.scripts: - tests: - - if [[ -d ./$BUILD_DIR/tests ]]; then ./.gitlab-ci/run-tests.sh $CI_REGISTRY_IMAGE/$IMAGE; fi; - .build_test: stage: build script: - echo -e "\e[0Ksection_start:`date +%s`:build[collapsed=true]\r\e[0K\e[1;34m Build $CI_REGISTRY_IMAGE/$IMAGE from $BUILD_DIR" - docker build --tag $CI_REGISTRY_IMAGE/$IMAGE + --tag $RELEASE_IMAGE/$IMAGE --compress --cache-from $CI_REGISTRY_IMAGE/$IMAGE --build-arg BUILDKIT_INLINE_CACHE=1 @@ -52,75 +50,35 @@ variables: - echo -e "\e[0Ksection_end:`date +%s`:build\r\e[0K" - docker images - docker push --quiet $CI_REGISTRY_IMAGE/$IMAGE - - !reference [.scripts, tests] - -# .publish: -# stage: publish -# rules: -# - if: '$DO_RELEASE == "1"' -# when: on_success -# - when: never -# script: -# # Tag and push to target registry. -# - docker tag $CI_REGISTRY_IMAGE/$IMAGE $RELEASE_IMAGE/$IMAGE -# - docker images -# # Login to Docker hub, tag and push. -# - | -# echo -e "\e[0Ksection_start:`date +%s`:release[collapsed=true]\r\e[0K\e[1;34m Push $RELEASE_IMAGE/$IMAGE to $RELEASE_REGISTRY with user $RELEASE_USER" -# echo "$RELEASE_PASSWORD" | docker login $RELEASE_REGISTRY --username $RELEASE_USER --password-stdin -# docker push $RELEASE_IMAGE/$IMAGE -# echo -e "\e[0Ksection_end:`date +%s`:release\r\e[0K" - -# previous: -# extends: .build_test -# variables: -# IMAGE_BASE: drupal:${DRUPAL_PREVIOUS}-php${DRUPAL_PREVIOUS_PHP} -# IMAGE: drupal-ci:${CI_COMMIT_BRANCH}-${DRUPAL_PREVIOUS} -# BUILD_DIR: '${DRUPAL_PREVIOUS}' + - if [[ -d ./$BUILD_DIR/tests ]]; then ./.gitlab-ci/run-tests.sh $CI_REGISTRY_IMAGE/$IMAGE; fi; + # Login to Docker hub and push. + - echo "$RELEASE_PASSWORD" | docker login $RELEASE_REGISTRY --username $RELEASE_USER --password-stdin + - docker push --quiet $RELEASE_IMAGE/$IMAGE -# previous_publish: -# extends: .publish -# variables: -# IMAGE_BASE: drupal:${DRUPAL_PREVIOUS}-php${DRUPAL_PREVIOUS_PHP} -# IMAGE: drupal-ci:${CI_COMMIT_BRANCH}-${DRUPAL_PREVIOUS} +prev-9-2: + extends: .build_test + variables: + IMAGE_BASE: drupal:${DRUPAL_PREVIOUS}-php${DRUPAL_PREVIOUS_PHP} + IMAGE: drupal-ci:${CI_COMMIT_BRANCH}-${DRUPAL_PREVIOUS} + BUILD_DIR: '${DRUPAL_PREVIOUS}' -current: +cur-9-3: extends: .build_test variables: IMAGE_BASE: drupal:${DRUPAL_CURRENT}-php${DRUPAL_CURRENT_PHP} IMAGE: drupal-ci:${CI_COMMIT_BRANCH}-${DRUPAL_CURRENT} BUILD_DIR: '${DRUPAL_CURRENT}' -# current_publish: -# extends: .publish -# variables: -# IMAGE_BASE: drupal:${DRUPAL_CURRENT}-php${DRUPAL_CURRENT_PHP} -# IMAGE: drupal-ci:${CI_COMMIT_BRANCH}-${DRUPAL_CURRENT} - -# next: -# extends: .build_test -# variables: -# IMAGE_BASE: drupal:${DRUPAL_NEXT}-php${DRUPAL_NEXT_PHP} -# IMAGE: drupal-ci:${CI_COMMIT_BRANCH}-10.0 -# BUILD_DIR: '${DRUPAL_NEXT}' - -# next_publish: -# extends: .publish -# variables: -# IMAGE_BASE: drupal:${DRUPAL_NEXT}-php${DRUPAL_NEXT_PHP} -# IMAGE: drupal-ci:${CI_COMMIT_BRANCH}-10.0 - -# chrome-headless: -# extends: .build_test -# variables: -# IMAGE_BASE: debian:bullseye-slim -# IMAGE: chrome-headless:${CI_COMMIT_BRANCH} -# BUILD_DIR: chrome-headless -# NO_TESTS: 1 +next-10: + extends: .build_test + variables: + IMAGE_BASE: drupal:${DRUPAL_NEXT}-php${DRUPAL_NEXT_PHP} + IMAGE: drupal-ci:${CI_COMMIT_BRANCH}-${DRUPAL_NEXT_IMAGE_TAG} + BUILD_DIR: '${DRUPAL_NEXT}' -# chrome-headless_publish: -# extends: .publish -# variables: -# IMAGE_BASE: debian:bullseye-slim -# IMAGE: chrome-headless:${CI_COMMIT_BRANCH} -# NO_TESTS: 1 +chrome-headless: + extends: .build_test + variables: + IMAGE_BASE: debian:bullseye-slim + IMAGE: chrome-headless:${CI_COMMIT_BRANCH} + BUILD_DIR: chrome-headless diff --git a/10.0-rc/Dockerfile b/10.0-rc/Dockerfile new file mode 100755 index 0000000..f711ff3 --- /dev/null +++ b/10.0-rc/Dockerfile @@ -0,0 +1,113 @@ +# https://github.com/docker-library/drupal/blob/master/10.0-rc/php8.1/apache-buster/Dockerfile +FROM drupal:10.0-rc-php8.1 + +LABEL maintainer="dev-drupal.com" +LABEL org.label-schema.schema-version="1.0" +LABEL org.label-schema.name="gitlab-ci-drupal/drupal-ci-images" +LABEL org.label-schema.description="Drupal CI images for project https://gitlab.com/mog33/gitlab-ci-drupal" +LABEL org.label-schema.url="https://mog33.gitlab.io/gitlab-ci-drupal" +LABEL org.label-schema.vcs-url="https://gitlab.com/gitlab-ci-drupal/drupal-ci-images" +LABEL org.label-schema.vendor="dev-drupal.com" + +# Install needed programs. +RUN apt-get update && apt-get install --no-install-recommends -y \ + apt-transport-https \ + bc \ + ca-certificates \ + curl \ + gettext-base \ + git \ + gnupg2 \ + jq \ + software-properties-common \ + ssh \ + sudo \ + unzip \ + vim \ + xsltproc \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +#================== +# Install Nodejs, Yarn. +RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - \ + && curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \ + && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ + && apt-get update && apt-get install --no-install-recommends -y \ + nodejs \ + yarn \ + # Required for Drush sql commands. + mariadb-client \ + postgresql-client \ + # Install PHP extensions. + libicu-dev \ + imagemagick \ + libmagickwand-dev \ + libnss3-dev \ + libssl-dev \ + libxslt-dev \ + # https://github.com/mlocati/docker-php-extension-installer + && docker-php-ext-install intl xsl mysqli bcmath calendar sockets pcntl opcache exif ftp \ + && pecl channel-update pecl.php.net && pecl install imagick xdebug \ + && docker-php-ext-enable imagick xdebug \ + # Cleanup. + && docker-php-source delete \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +#================== +# Install composer third party. +RUN /usr/local/bin/composer selfupdate +COPY --chown=www-data:www-data composer.json /var/www/.composer/composer.json + +USER www-data + +# Manage Composer. +WORKDIR /var/www/.composer + +# Install our tools, see composer.json +RUN COMPOSER_MEMORY_LIMIT=-1 composer install -n \ + && composer clear-cache + +WORKDIR /opt/drupal + +USER root + +#================== +# Install Drupal core:dev, Drush for a module. +# @todo remove phpspec/prophecy-phpunit when Drupal 9 is deprecated. +RUN COMPOSER_MEMORY_LIMIT=-1 \ + composer require -n --dev --working-dir="/opt/drupal" \ + "drupal/core-dev:10.0.x-dev" "drush/drush:^11" "phpspec/prophecy-phpunit:^2" \ + && composer clear-cache + +#================== +# Include testing code. +COPY --chown=www-data:www-data ./tests/ /tests/ + +#================== +# Manage final tasks. +RUN chmod 777 /var/www \ + && chown -R www-data:www-data /var/www \ + # Symlink composer downloaded binaries. + && ln -sf /var/www/.composer/vendor/bin/* /usr/local/bin \ + # Phpunit 9+ cache. + && chown www-data:www-data /opt/drupal/web/core \ + # Tests scripts. + && chmod +x /tests/*.sh \ + # Fix Php performances. + && mv /usr/local/etc/php/php.ini-development /usr/local/etc/php/php.ini \ + && sed -i "s#memory_limit = 128M#memory_limit = 4G#g" /usr/local/etc/php/php.ini \ + && sed -i "s#max_execution_time = 30#max_execution_time = 90#g" /usr/local/etc/php/php.ini \ + && sed -i "s#;max_input_nesting_level = 64#max_input_nesting_level = 512#g" /usr/local/etc/php/php.ini \ + # Convenient alias for root and www-data. + && echo "alias ls='ls --color=auto -lAh'" >> /root/.bashrc \ + && echo "alias l='ls --color=auto -lAh'" >> /root/.bashrc \ + && echo "alias dr='drush --root=/opt/drupal/web'" >> /root/.bashrc \ + && cp /root/.bashrc /var/www/.bashrc \ + && chown www-data:www-data /var/www/.bashrc + +#================== +# Stay as root becasue it's a ci image. +# For obvious security reason, this image is NOT meant to be used by any production system. +# USER www-data diff --git a/10.0-rc/composer.json b/10.0-rc/composer.json new file mode 100755 index 0000000..d4fc125 --- /dev/null +++ b/10.0-rc/composer.json @@ -0,0 +1,24 @@ +{ + "name": "mog33/drupal8ci", + "description": "Packages for CI with Drupal 10.0-rc for https://gitlab.com/mog33/drupal8ci.", + "type": "project", + "minimum-stability": "dev", + "prefer-stable": true, + "require": { + "edgedesign/phpqa": "^1.25", + "consolidation/robo": "^3", + "drupal/coder": "^8.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7", + "phpstan/phpstan": "^1.4", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan-deprecation-rules": "^1.0", + "mglaman/phpstan-drupal": "^1.1", + "php-parallel-lint/php-parallel-lint": "^1.3" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true, + "phpstan/extension-installer": true + } + } +} diff --git a/10.0-rc/tests/prepare-tests.sh b/10.0-rc/tests/prepare-tests.sh new file mode 100644 index 0000000..e7451d1 --- /dev/null +++ b/10.0-rc/tests/prepare-tests.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +set -eu + +_install_packages() { + + if ! [ -x "$(command -v python3)" ]; then + if [ -f "/etc/alpine-release" ]; then + apk add --no-cache --no-progress --quiet python3 + else + apt update && apt install -y python3 + fi + fi + + if ! [ -x "$(command -v pip3)" ]; then + # https://pip.pypa.io/en/stable/installing/ + curl -s https://bootstrap.pypa.io/get-pip.py -o get-pip.py + python3 get-pip.py --quiet + fi + + if [ -f "/etc/alpine-release" ]; then + # nettoolsis needed for infratest 'socket' using netstat. + # default one on Alpine (busybox) is a limited versions. + apk add --no-cache --no-progress --quiet net-tools + fi +} + +_install_testinfra() { + if ! [ -x "$(command -v pytest)" ]; then + # https://github.com/pytest-dev/pytest-testinfra + pip3 install pytest-testinfra --quiet + fi +} + +_main() { + echo -e "[notice] Install packages for tests..." + _install_packages + _install_testinfra + echo -e "[notice] Done!" +} + +# Call `_main` after everything has been defined. +_main diff --git a/10.0-rc/tests/pytest.ini b/10.0-rc/tests/pytest.ini new file mode 100644 index 0000000..38e7fab --- /dev/null +++ b/10.0-rc/tests/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +console_output_style = classic diff --git a/10.0-rc/tests/requirements.txt b/10.0-rc/tests/requirements.txt new file mode 100644 index 0000000..f9bb305 --- /dev/null +++ b/10.0-rc/tests/requirements.txt @@ -0,0 +1 @@ +testinfra \ No newline at end of file diff --git a/10.0-rc/tests/test_composer.py b/10.0-rc/tests/test_composer.py new file mode 100644 index 0000000..803dd89 --- /dev/null +++ b/10.0-rc/tests/test_composer.py @@ -0,0 +1,27 @@ +import pytest + +def test_composer(host): + assert host.check_output('composer -V').startswith('Composer version 2') + assert host.file("/var/www/.composer/composer.json").exists + +@pytest.mark.parametrize("bin", [ + ("parallel-lint"), + ("pdepend"), + ("phpcs"), + ("phploc"), + ("phpmd"), + ("phpmetrics"), + ("phpqa"), + ("phpstan"), + ("robo"), +]) +def test_composer_bin(host, bin): + ''' Test bin exist ''' + assert host.file("/var/www/.composer/vendor/bin/" + bin).exists + assert host.file("/usr/local/bin/" + bin).is_symlink + assert host.file("/usr/local/bin/" + bin).mode == 0o777 + +def test_phpcs_standard(host): + '''' Test phpcs standards ''' + assert host.check_output('phpcs -i').__contains__('Drupal') + assert host.check_output('phpcs -i').__contains__('DrupalPractice') diff --git a/10.0-rc/tests/test_drush.py b/10.0-rc/tests/test_drush.py new file mode 100644 index 0000000..035883c --- /dev/null +++ b/10.0-rc/tests/test_drush.py @@ -0,0 +1,8 @@ +import pytest + +def test_drush(host): + ''' Test drush exist ''' + assert host.file("/opt/drupal/vendor/bin/drush").exists + assert host.file("/opt/drupal/vendor/bin/drush").mode == 0o755 + assert host.check_output("drush --version").startswith("Drush Commandline Tool") + assert host.check_output("drush --root=/opt/drupal/web status --field=drupal-version").startswith("10.0-rc") diff --git a/10.0-rc/tests/test_packages.py b/10.0-rc/tests/test_packages.py new file mode 100644 index 0000000..9471717 --- /dev/null +++ b/10.0-rc/tests/test_packages.py @@ -0,0 +1,20 @@ +import pytest + +@pytest.mark.parametrize("name", [ + ("bash"), + ("bc"), + ("curl"), + ("git"), + ("jq"), + ("gettext-base"), + ("ssh"), + ("xsltproc"), + ("mariadb-client"), + ("postgresql-client"), + ("nodejs"), + ("yarn"), +]) +def test_packages_installed(host, name): + ''' Test a minimum of required packages ''' + pkg = host.package(name) + assert pkg.is_installed diff --git a/10.0-rc/tests/test_permissions.py b/10.0-rc/tests/test_permissions.py new file mode 100644 index 0000000..067d340 --- /dev/null +++ b/10.0-rc/tests/test_permissions.py @@ -0,0 +1,13 @@ +import pytest + +@pytest.mark.parametrize("folder", [ + ("/opt/drupal/web/core"), + ("/opt/drupal/web/modules"), + ("/opt/drupal/web/themes"), + ("/opt/drupal/web/sites"), + ("/var/www"), +]) +def test_permissions(host, folder): + ''' Test folder permissions ''' + assert host.file(folder).user == "www-data" + assert host.file(folder).group == "www-data" \ No newline at end of file diff --git a/10.0-rc/tests/test_php.py b/10.0-rc/tests/test_php.py new file mode 100644 index 0000000..fd6ff9c --- /dev/null +++ b/10.0-rc/tests/test_php.py @@ -0,0 +1,21 @@ +import pytest + +def test_php_version(host): + ''' Check PHP version so it's highlighted when changed ''' + assert host.check_output('php -v').startswith('PHP 8.1') + +@pytest.mark.parametrize("name", [ + ("sockets"), + ("ftp"), + ("intl"), + ("xsl"), + ("mysqli"), + ("pdo_mysql"), + ("pdo_pgsql"), + ("pdo_sqlite"), + ("OPcache"), + ("xdebug"), +]) +def test_php_modules(host, name): + ''' Test the minimum list of needed extensions ''' + assert host.check_output('php -m | grep ' + name) diff --git a/10.0-rc/tests/test_php_ini.py b/10.0-rc/tests/test_php_ini.py new file mode 100644 index 0000000..a61b99d --- /dev/null +++ b/10.0-rc/tests/test_php_ini.py @@ -0,0 +1,14 @@ +import pytest +import configparser + +config = configparser.ConfigParser() + +def test_php_ini(host): + assert host.file("/usr/local/etc/php/php.ini").exists + +def test_php_ini_values(host): + ''' Check important config that should be highlighted when changed ''' + config.read('/usr/local/etc/php/php.ini') + assert config['PHP']['max_execution_time'] == '90' + assert config['PHP']['max_input_nesting_level'] == '512' + assert config['PHP']['memory_limit'] == '4G' diff --git a/9.2/Dockerfile b/9.2/Dockerfile new file mode 100755 index 0000000..e99c661 --- /dev/null +++ b/9.2/Dockerfile @@ -0,0 +1,113 @@ +# https://github.com/docker-library/drupal/blob/master/9.2/php8.0/apache-buster/Dockerfile +FROM drupal:9.2-php8.0 + +LABEL maintainer="dev-drupal.com" +LABEL org.label-schema.schema-version="1.0" +LABEL org.label-schema.name="gitlab-ci-drupal/drupal-ci-images" +LABEL org.label-schema.description="Drupal CI images for project https://gitlab.com/mog33/gitlab-ci-drupal" +LABEL org.label-schema.url="https://mog33.gitlab.io/gitlab-ci-drupal" +LABEL org.label-schema.vcs-url="https://gitlab.com/gitlab-ci-drupal/drupal-ci-images" +LABEL org.label-schema.vendor="dev-drupal.com" + +# Install needed programs. +RUN apt-get update && apt-get install --no-install-recommends -y \ + apt-transport-https \ + bc \ + ca-certificates \ + curl \ + gettext-base \ + git \ + gnupg2 \ + jq \ + software-properties-common \ + ssh \ + sudo \ + unzip \ + vim \ + xsltproc \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +#================== +# Install Nodejs, Yarn. +RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - \ + && curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \ + && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ + && apt-get update && apt-get install --no-install-recommends -y \ + nodejs \ + yarn \ + # Required for Drush sql commands. + mariadb-client \ + postgresql-client \ + # Install PHP extensions. + libicu-dev \ + imagemagick \ + libmagickwand-dev \ + libnss3-dev \ + libssl-dev \ + libxslt-dev \ + # https://github.com/mlocati/docker-php-extension-installer + && docker-php-ext-install intl xsl mysqli bcmath calendar sockets pcntl opcache exif ftp \ + && pecl channel-update pecl.php.net && pecl install imagick xdebug \ + && docker-php-ext-enable imagick xdebug \ + # Cleanup. + && docker-php-source delete \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +#================== +# Install composer third party. +RUN /usr/local/bin/composer selfupdate +COPY --chown=www-data:www-data composer.json /var/www/.composer/composer.json + +USER www-data + +# Manage Composer. +WORKDIR /var/www/.composer + +# Install our tools, see composer.json +RUN COMPOSER_MEMORY_LIMIT=-1 composer install -n \ + && composer clear-cache + +WORKDIR /opt/drupal + +USER root + +#================== +# Install Drupal core:dev, Drush for a module. +# @todo remove phpspec/prophecy-phpunit when Drupal 9 is deprecated. +RUN COMPOSER_MEMORY_LIMIT=-1 \ + composer require -n --dev --working-dir="/opt/drupal" \ + "drupal/core-dev:^9.2" "drush/drush:^11" "phpspec/prophecy-phpunit:^2" \ + && composer clear-cache + +#================== +# Include testing code. +COPY --chown=www-data:www-data ./tests/ /tests/ + +#================== +# Manage final tasks. +RUN chmod 777 /var/www \ + && chown -R www-data:www-data /var/www \ + # Symlink composer downloaded binaries. + && ln -sf /var/www/.composer/vendor/bin/* /usr/local/bin \ + # Phpunit 9+ cache. + && chown www-data:www-data /opt/drupal/web/core \ + # Tests scripts. + && chmod +x /tests/*.sh \ + # Fix Php performances. + && mv /usr/local/etc/php/php.ini-development /usr/local/etc/php/php.ini \ + && sed -i "s#memory_limit = 128M#memory_limit = 4G#g" /usr/local/etc/php/php.ini \ + && sed -i "s#max_execution_time = 30#max_execution_time = 90#g" /usr/local/etc/php/php.ini \ + && sed -i "s#;max_input_nesting_level = 64#max_input_nesting_level = 512#g" /usr/local/etc/php/php.ini \ + # Convenient alias for root and www-data. + && echo "alias ls='ls --color=auto -lAh'" >> /root/.bashrc \ + && echo "alias l='ls --color=auto -lAh'" >> /root/.bashrc \ + && echo "alias dr='drush --root=/opt/drupal/web'" >> /root/.bashrc \ + && cp /root/.bashrc /var/www/.bashrc \ + && chown www-data:www-data /var/www/.bashrc + +#================== +# Stay as root becasue it's a ci image. +# For obvious security reason, this image is NOT meant to be used by any production system. +# USER www-data diff --git a/9.2/composer.json b/9.2/composer.json new file mode 100755 index 0000000..87b1417 --- /dev/null +++ b/9.2/composer.json @@ -0,0 +1,24 @@ +{ + "name": "mog33/drupal8ci", + "description": "Packages for CI with Drupal 9.2 for https://gitlab.com/mog33/drupal8ci.", + "type": "project", + "minimum-stability": "dev", + "prefer-stable": true, + "require": { + "edgedesign/phpqa": "^1.25", + "consolidation/robo": "^3", + "drupal/coder": "^8.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7", + "phpstan/phpstan": "^1.4", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan-deprecation-rules": "^1.0", + "mglaman/phpstan-drupal": "^1.1", + "php-parallel-lint/php-parallel-lint": "^1.3" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true, + "phpstan/extension-installer": true + } + } +} diff --git a/9.2/tests/prepare-tests.sh b/9.2/tests/prepare-tests.sh new file mode 100644 index 0000000..e7451d1 --- /dev/null +++ b/9.2/tests/prepare-tests.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +set -eu + +_install_packages() { + + if ! [ -x "$(command -v python3)" ]; then + if [ -f "/etc/alpine-release" ]; then + apk add --no-cache --no-progress --quiet python3 + else + apt update && apt install -y python3 + fi + fi + + if ! [ -x "$(command -v pip3)" ]; then + # https://pip.pypa.io/en/stable/installing/ + curl -s https://bootstrap.pypa.io/get-pip.py -o get-pip.py + python3 get-pip.py --quiet + fi + + if [ -f "/etc/alpine-release" ]; then + # nettoolsis needed for infratest 'socket' using netstat. + # default one on Alpine (busybox) is a limited versions. + apk add --no-cache --no-progress --quiet net-tools + fi +} + +_install_testinfra() { + if ! [ -x "$(command -v pytest)" ]; then + # https://github.com/pytest-dev/pytest-testinfra + pip3 install pytest-testinfra --quiet + fi +} + +_main() { + echo -e "[notice] Install packages for tests..." + _install_packages + _install_testinfra + echo -e "[notice] Done!" +} + +# Call `_main` after everything has been defined. +_main diff --git a/9.2/tests/pytest.ini b/9.2/tests/pytest.ini new file mode 100644 index 0000000..38e7fab --- /dev/null +++ b/9.2/tests/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +console_output_style = classic diff --git a/9.2/tests/requirements.txt b/9.2/tests/requirements.txt new file mode 100644 index 0000000..f9bb305 --- /dev/null +++ b/9.2/tests/requirements.txt @@ -0,0 +1 @@ +testinfra \ No newline at end of file diff --git a/9.2/tests/test_composer.py b/9.2/tests/test_composer.py new file mode 100644 index 0000000..803dd89 --- /dev/null +++ b/9.2/tests/test_composer.py @@ -0,0 +1,27 @@ +import pytest + +def test_composer(host): + assert host.check_output('composer -V').startswith('Composer version 2') + assert host.file("/var/www/.composer/composer.json").exists + +@pytest.mark.parametrize("bin", [ + ("parallel-lint"), + ("pdepend"), + ("phpcs"), + ("phploc"), + ("phpmd"), + ("phpmetrics"), + ("phpqa"), + ("phpstan"), + ("robo"), +]) +def test_composer_bin(host, bin): + ''' Test bin exist ''' + assert host.file("/var/www/.composer/vendor/bin/" + bin).exists + assert host.file("/usr/local/bin/" + bin).is_symlink + assert host.file("/usr/local/bin/" + bin).mode == 0o777 + +def test_phpcs_standard(host): + '''' Test phpcs standards ''' + assert host.check_output('phpcs -i').__contains__('Drupal') + assert host.check_output('phpcs -i').__contains__('DrupalPractice') diff --git a/9.2/tests/test_drush.py b/9.2/tests/test_drush.py new file mode 100644 index 0000000..73a54a1 --- /dev/null +++ b/9.2/tests/test_drush.py @@ -0,0 +1,8 @@ +import pytest + +def test_drush(host): + ''' Test drush exist ''' + assert host.file("/opt/drupal/vendor/bin/drush").exists + assert host.file("/opt/drupal/vendor/bin/drush").mode == 0o755 + assert host.check_output("drush --version").startswith("Drush Commandline Tool") + assert host.check_output("drush --root=/opt/drupal/web status --field=drupal-version").startswith("9.2") diff --git a/9.2/tests/test_packages.py b/9.2/tests/test_packages.py new file mode 100644 index 0000000..9471717 --- /dev/null +++ b/9.2/tests/test_packages.py @@ -0,0 +1,20 @@ +import pytest + +@pytest.mark.parametrize("name", [ + ("bash"), + ("bc"), + ("curl"), + ("git"), + ("jq"), + ("gettext-base"), + ("ssh"), + ("xsltproc"), + ("mariadb-client"), + ("postgresql-client"), + ("nodejs"), + ("yarn"), +]) +def test_packages_installed(host, name): + ''' Test a minimum of required packages ''' + pkg = host.package(name) + assert pkg.is_installed diff --git a/9.2/tests/test_permissions.py b/9.2/tests/test_permissions.py new file mode 100644 index 0000000..067d340 --- /dev/null +++ b/9.2/tests/test_permissions.py @@ -0,0 +1,13 @@ +import pytest + +@pytest.mark.parametrize("folder", [ + ("/opt/drupal/web/core"), + ("/opt/drupal/web/modules"), + ("/opt/drupal/web/themes"), + ("/opt/drupal/web/sites"), + ("/var/www"), +]) +def test_permissions(host, folder): + ''' Test folder permissions ''' + assert host.file(folder).user == "www-data" + assert host.file(folder).group == "www-data" \ No newline at end of file diff --git a/9.2/tests/test_php.py b/9.2/tests/test_php.py new file mode 100644 index 0000000..5b8c062 --- /dev/null +++ b/9.2/tests/test_php.py @@ -0,0 +1,21 @@ +import pytest + +def test_php_version(host): + ''' Check PHP version so it's highlighted when changed ''' + assert host.check_output('php -v').startswith('PHP 8.0') + +@pytest.mark.parametrize("name", [ + ("sockets"), + ("ftp"), + ("intl"), + ("xsl"), + ("mysqli"), + ("pdo_mysql"), + ("pdo_pgsql"), + ("pdo_sqlite"), + ("OPcache"), + ("xdebug"), +]) +def test_php_modules(host, name): + ''' Test the minimum list of needed extensions ''' + assert host.check_output('php -m | grep ' + name) diff --git a/9.2/tests/test_php_ini.py b/9.2/tests/test_php_ini.py new file mode 100644 index 0000000..a61b99d --- /dev/null +++ b/9.2/tests/test_php_ini.py @@ -0,0 +1,14 @@ +import pytest +import configparser + +config = configparser.ConfigParser() + +def test_php_ini(host): + assert host.file("/usr/local/etc/php/php.ini").exists + +def test_php_ini_values(host): + ''' Check important config that should be highlighted when changed ''' + config.read('/usr/local/etc/php/php.ini') + assert config['PHP']['max_execution_time'] == '90' + assert config['PHP']['max_input_nesting_level'] == '512' + assert config['PHP']['memory_limit'] == '4G' diff --git a/9.3/Dockerfile b/9.3/Dockerfile index b1a3f38..0b0a649 100755 --- a/9.3/Dockerfile +++ b/9.3/Dockerfile @@ -2,6 +2,12 @@ FROM drupal:9.3-php8.0 LABEL maintainer="dev-drupal.com" +LABEL org.label-schema.schema-version="1.0" +LABEL org.label-schema.name="gitlab-ci-drupal/drupal-ci-images" +LABEL org.label-schema.description="Drupal CI images for project https://gitlab.com/mog33/gitlab-ci-drupal" +LABEL org.label-schema.url="https://mog33.gitlab.io/gitlab-ci-drupal" +LABEL org.label-schema.vcs-url="https://gitlab.com/gitlab-ci-drupal/drupal-ci-images" +LABEL org.label-schema.vendor="dev-drupal.com" # Install needed programs. RUN apt-get update && apt-get install --no-install-recommends -y \ diff --git a/9.3/tests/test_composer.py b/9.3/tests/test_composer.py index b166a93..803dd89 100644 --- a/9.3/tests/test_composer.py +++ b/9.3/tests/test_composer.py @@ -17,7 +17,7 @@ def test_composer(host): ]) def test_composer_bin(host, bin): ''' Test bin exist ''' - assert host.file("var/www/.composer/vendor/bin/" + bin).exists + assert host.file("/var/www/.composer/vendor/bin/" + bin).exists assert host.file("/usr/local/bin/" + bin).is_symlink assert host.file("/usr/local/bin/" + bin).mode == 0o777 diff --git a/9.3/tests/test_drush.py b/9.3/tests/test_drush.py index ab0dfb4..8a20d3f 100644 --- a/9.3/tests/test_drush.py +++ b/9.3/tests/test_drush.py @@ -4,5 +4,5 @@ def test_drush(host): ''' Test drush exist ''' assert host.file("/opt/drupal/vendor/bin/drush").exists assert host.file("/opt/drupal/vendor/bin/drush").mode == 0o755 - assert host.file("drush --version").startwith("Drush Commandline Tool") - assert host.file("drush --root=/opt/drupal/web status --field=drupal-version").startwith("9.3") + assert host.check_output("drush --version").startswith("Drush Commandline Tool") + assert host.check_output("drush --root=/opt/drupal/web status --field=drupal-version").startswith("9.3") diff --git a/9.3/tests/test_packages.py b/9.3/tests/test_packages.py index c724393..9471717 100644 --- a/9.3/tests/test_packages.py +++ b/9.3/tests/test_packages.py @@ -6,12 +6,12 @@ ("curl"), ("git"), ("jq"), - ("gettext"), - ("openssh"), + ("gettext-base"), + ("ssh"), ("xsltproc"), ("mariadb-client"), ("postgresql-client"), - ("node"), + ("nodejs"), ("yarn"), ]) def test_packages_installed(host, name): diff --git a/9.3/tests/test_php.py b/9.3/tests/test_php.py index e5e6f5b..5b8c062 100644 --- a/9.3/tests/test_php.py +++ b/9.3/tests/test_php.py @@ -6,12 +6,14 @@ def test_php_version(host): @pytest.mark.parametrize("name", [ ("sockets"), - ("opcache"), ("ftp"), ("intl"), ("xsl"), ("mysqli"), - ("Zend OPcache"), + ("pdo_mysql"), + ("pdo_pgsql"), + ("pdo_sqlite"), + ("OPcache"), ("xdebug"), ]) def test_php_modules(host, name): diff --git a/Makefile b/Makefile index 493ef79..95311ce 100755 --- a/Makefile +++ b/Makefile @@ -24,8 +24,8 @@ define prepare endef prepare: -# $(call prepare,${DRUPAL_PREVIOUS},${DRUPAL_PREVIOUS_PHP},${DRUPAL_PREVIOUS_DEV}) + $(call prepare,${DRUPAL_PREVIOUS},${DRUPAL_PREVIOUS_PHP},${DRUPAL_PREVIOUS_DEV}) $(call prepare,${DRUPAL_CURRENT},${DRUPAL_CURRENT_PHP},${DRUPAL_CURRENT_DEV}) -# $(call prepare,${DRUPAL_NEXT},${DRUPAL_NEXT_PHP},${DRUPAL_NEXT_DEV}) + $(call prepare,${DRUPAL_NEXT},${DRUPAL_NEXT_PHP},${DRUPAL_NEXT_DEV}) .PHONY: prepare diff --git a/README.md b/README.md index 56e3ca8..295326f 100755 --- a/README.md +++ b/README.md @@ -10,7 +10,6 @@ Used with project [Gitlab CI Drupal](https://gitlab.com/mog33/gitlab-ci-drupal). * Fork from [juampynr/drupal8ci](https://hub.docker.com/r/juampynr/drupal8ci/~/dockerfile/) * Based on [Drupal official image](https://github.com/docker-library/drupal), added * [Node.js](https://nodejs.org/en/) + [Yarn](https://yarnpkg.com) - * [Google chrome stable](https://dl.google.com/linux/chrome/deb/) + [Chromedriver](http://chromedriver.chromium.org) * [Robo CI](http://robo.li) * [Phpqa](https://github.com/EdgedesignCZ/phpqa) including: * [Phpmetrics](https://www.phpmetrics.org) @@ -18,16 +17,17 @@ Used with project [Gitlab CI Drupal](https://gitlab.com/mog33/gitlab-ci-drupal). * [Phpcs](https://github.com/squizlabs/PHP_CodeSniffer) * [Phpmd](https://phpmd.org) * [Pdepend](https://pdepend.org) - * [Phpcpd](https://github.com/sebastianbergmann/phpcpd) * [Security checker](https://github.com/fabpot/local-php-security-checker) * [phpstan](https://github.com/phpstan/phpstan) * [phpstan-drupal](https://github.com/mglaman/phpstan-drupal) * [Drupal Coder](https://www.drupal.org/project/coder) - * Mariadb (MySQL) client (For Drush sql commands) + * Mariadb (MySQL) and PostgreSQL client * Php with extensions: - * intl xsl mysqli bcmath calendar sockets pcntl opcache exif ftp imagick xdebug + * intl xsl mysqli bcmath calendar sockets pcntl opcache exif ftp imagick xdebug * [jq](https://stedolan.github.io/jq/) * [bc](https://www.gnu.org/software/bc/) + * [xsltproc](http://xmlsoft.org/xslt/xsltproc.html) + * [gettext](http://xmlsoft.org/xslt/xsltproc.html) ## Basic usage (local) @@ -49,11 +49,11 @@ make prepare ## Tests -Basic version check tests with [Obvious Shell Testing (osht)](https://github.com/coryb/osht). +Tests with [infratest](https://testinfra.readthedocs.io/en/latest/). ```bash -docker run -it --rm mogtofu33/drupal8ci:3.x-dev-9.3 /scripts/run-tests.sh +docker run -it --rm mogtofu33/drupal8ci:4.x-dev-9.3 /tests/prepare-tests.sh && pytest ``` ---- -Want some help implementing this on your project? I provide Drupal expertise as a freelance, just [contact me](https://developpeur-drupal.com/en). +Want some help implementing this on your project? I provide Drupal expertise as a **freelance**, just [contact me](https://developpeur-drupal.com/en). diff --git a/chrome-headless/Dockerfile b/chrome-headless/Dockerfile new file mode 100644 index 0000000..24a1361 --- /dev/null +++ b/chrome-headless/Dockerfile @@ -0,0 +1,36 @@ +FROM debian:bullseye-slim + +LABEL name="chrome-headless" \ + maintainer="dev-drupal.com" \ + version="1.0" \ + description="Google Chrome Headless for CI usage" + +ENV CHROME_OPTS="--headless --no-sandbox --window-size=1920,1080 --remote-debugging-address=0.0.0.0 --remote-debugging-port=9222" + +RUN apt-get update && apt-get install -y \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg \ + procps \ + --no-install-recommends \ + && curl -sS -o - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ + && echo "deb [arch=amd64] https://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list \ + && apt-get update && apt-get install --no-install-recommends -y \ + google-chrome-stable \ + && apt-get purge --auto-remove -y curl gnupg \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +COPY start-chrome.sh /scripts/start-chrome.sh + +RUN chmod +x /scripts/start-chrome.sh + +RUN groupadd -r chrome && useradd -r -g chrome -G audio,video chrome \ + && mkdir -p /home/chrome && chown -R chrome:chrome /home/chrome + +USER chrome + +EXPOSE 9222 + +ENTRYPOINT [ "/scripts/start-chrome.sh" ] \ No newline at end of file diff --git a/chrome-headless/start-chrome.sh b/chrome-headless/start-chrome.sh new file mode 100755 index 0000000..58ca5fb --- /dev/null +++ b/chrome-headless/start-chrome.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +if pgrep -x "chrome" > /dev/null +then + echo "Chrome already running!" +else + echo "Running with: ${CHROME_OPTS}" + /usr/bin/google-chrome ${CHROME_OPTS} +fi \ No newline at end of file diff --git a/drupal-tpl/Dockerfile b/drupal-tpl/Dockerfile index 0d63bc6..5712308 100755 --- a/drupal-tpl/Dockerfile +++ b/drupal-tpl/Dockerfile @@ -2,6 +2,12 @@ FROM drupal:${IMAGE_TAG}-php${PHP_VERSION} LABEL maintainer="dev-drupal.com" +LABEL org.label-schema.schema-version="1.0" +LABEL org.label-schema.name="gitlab-ci-drupal/drupal-ci-images" +LABEL org.label-schema.description="Drupal CI images for project https://gitlab.com/mog33/gitlab-ci-drupal" +LABEL org.label-schema.url="https://mog33.gitlab.io/gitlab-ci-drupal" +LABEL org.label-schema.vcs-url="https://gitlab.com/gitlab-ci-drupal/drupal-ci-images" +LABEL org.label-schema.vendor="dev-drupal.com" # Install needed programs. RUN apt-get update && apt-get install --no-install-recommends -y \ diff --git a/drupal-tpl/tests/test_composer.py b/drupal-tpl/tests/test_composer.py index b166a93..803dd89 100644 --- a/drupal-tpl/tests/test_composer.py +++ b/drupal-tpl/tests/test_composer.py @@ -17,7 +17,7 @@ def test_composer(host): ]) def test_composer_bin(host, bin): ''' Test bin exist ''' - assert host.file("var/www/.composer/vendor/bin/" + bin).exists + assert host.file("/var/www/.composer/vendor/bin/" + bin).exists assert host.file("/usr/local/bin/" + bin).is_symlink assert host.file("/usr/local/bin/" + bin).mode == 0o777 diff --git a/drupal-tpl/tests/test_drush.py b/drupal-tpl/tests/test_drush.py index ed87466..c13259c 100644 --- a/drupal-tpl/tests/test_drush.py +++ b/drupal-tpl/tests/test_drush.py @@ -4,5 +4,5 @@ def test_drush(host): ''' Test drush exist ''' assert host.file("/opt/drupal/vendor/bin/drush").exists assert host.file("/opt/drupal/vendor/bin/drush").mode == 0o755 - assert host.file("drush --version").startwith("Drush Commandline Tool") - assert host.file("drush --root=/opt/drupal/web status --field=drupal-version").startwith("$DRUPAL_VERSION") + assert host.check_output("drush --version").startswith("Drush Commandline Tool") + assert host.check_output("drush --root=/opt/drupal/web status --field=drupal-version").startswith("$DRUPAL_VERSION") diff --git a/drupal-tpl/tests/test_packages.py b/drupal-tpl/tests/test_packages.py index c724393..9471717 100644 --- a/drupal-tpl/tests/test_packages.py +++ b/drupal-tpl/tests/test_packages.py @@ -6,12 +6,12 @@ ("curl"), ("git"), ("jq"), - ("gettext"), - ("openssh"), + ("gettext-base"), + ("ssh"), ("xsltproc"), ("mariadb-client"), ("postgresql-client"), - ("node"), + ("nodejs"), ("yarn"), ]) def test_packages_installed(host, name): diff --git a/drupal-tpl/tests/test_php.py b/drupal-tpl/tests/test_php.py index d7fe3ef..1fb69c9 100644 --- a/drupal-tpl/tests/test_php.py +++ b/drupal-tpl/tests/test_php.py @@ -6,12 +6,14 @@ def test_php_version(host): @pytest.mark.parametrize("name", [ ("sockets"), - ("opcache"), ("ftp"), ("intl"), ("xsl"), ("mysqli"), - ("Zend OPcache"), + ("pdo_mysql"), + ("pdo_pgsql"), + ("pdo_sqlite"), + ("OPcache"), ("xdebug"), ]) def test_php_modules(host, name):