#!/bin/sh # Let's set a sane environment set -o errexit set -o nounset echo 'Checking environment' if test -n "${GITHUB_WORKSPACE:-}" && test -n "${GITHUB_SHA:-}"; then if test -z "${1:-}"; then echo 'Missing commit range of the push event' >&2 exit 1 fi CI_BUILD_DIR="$GITHUB_WORKSPACE" CI_COMMIT_RANGE="$1" else echo 'Not in a CI environment' >&2 exit 1 fi if test -z "${DOCKER_DISTRO:-}"; then echo 'DOCKER_DISTRO environment variable not set' >&2 exit 1 fi . "$CI_BUILD_DIR/scripts/common" ALREADY_TESTED_EXTENSIONS='' # Get the docker image ID for a PHP extension and a PHP version # # Arguments: # $1: space-separated list with the names of the PHP extensions # $2: the PHP version # # Outputs: # the full docker image ID getDockerImageName() { case "$2" in *) getDockerImageName_version="$2" ;; esac getDockerImageName_suffix='cli' getDockerImageName_reqs="$CI_BUILD_DIR/data/special-requirements" if test -f "$getDockerImageName_reqs"; then IFS=' ' for getDockerImageName_testExtension in $1; do if test -n "$(cat "$getDockerImageName_reqs" | grep -E "^$getDockerImageName_testExtension[ \t]+zts[ \t]*$")"; then getDockerImageName_suffix='zts' fi done fi getDockerImageName_imageName="$(printf 'php:%s-%s-%s' "$getDockerImageName_version" "$getDockerImageName_suffix" "$DOCKER_DISTRO")" case "$getDockerImageName_imageName" in php:5.5-cli-jessie) getDockerImageName_imageName='php:5.5-cli' ;; php:5.5-zts-jessie) getDockerImageName_imageName='php:5.5-zts' ;; esac if test -z "$(docker images -q "$getDockerImageName_imageName" 2>/dev/null)"; then getDockerImageName_log="$(docker pull "$getDockerImageName_imageName" 2>&1 || true)" if test -z "$(docker images -q "$getDockerImageName_imageName" 2>/dev/null)"; then if test "${getDockerImageName_log#*manifest unknown}" != "$getDockerImageName_log" || test "${getDockerImageName_log#*manifest for * not found}" != "$getDockerImageName_log"; then true return fi printf '%s\n' "$getDockerImageName_log" >&2 exit 1 fi fi printf '%s' "$getDockerImageName_imageName" } # Test an extension # # Arguments: # $1: space-separated list with the names of the PHP extensions to be tested # $2: the PHP version # # Return: # 0 (true): if test passes # 1 (false): if test fails testExtension() { printf 'PHP version: %s\n' "$2" if test -n "$(printf '%s' "$2" | sed -E 's/^[0-9]+\.[0-9]+$//')"; then printf ' INVALID PHP VERSION: %s\n' "$2" >&2 return 1 fi testExtension_Image="$(getDockerImageName "$1" "$2")" if test $? -ne 0; then exit 1 fi if test -z "$testExtension_Image"; then printf ' - Docker image not available\n' return 0 fi printf ' - Docker image: %s\n' "$testExtension_Image" testExtension_out="$(mktemp)" if $(docker run --rm --volume "$CI_BUILD_DIR:/app" --workdir /app "$testExtension_Image" sh -c "./install-php-extensions $1 && php ./scripts/check-installed-extension.php $1" >"$testExtension_out" 2>&1); then rm -rf "$testExtension_out" printf ' - Passed\n' return 0 fi printf ' - FAILED!\n' >&2 tail -n500 "$testExtension_out" >&2 rm -rf "$testExtension_out" return 1 } # Test a new extension line # # Arguments: # $1: the extension name # $@: the list of PHP versions # # Return: # 0 (true): if test passes # 1 (false): if test fails testNewExtensionLine() { testNewExtensionLine_rc=0 if test $# -lt 2; then printf 'Missing PHP version list for the new extension %s\n' "${1:-}" testNewExtensionLine_rc=1 elif ! stringInList "$1" "$ALREADY_TESTED_EXTENSIONS"; then printf '### TESTING NEW EXTENSION %s ###\n' "$1" if test -n "$(printf '%s' "$1" | sed -E 's/^[a-z][a-z0-9\-\_\.]+$//')"; then printf ' INVALID PHP EXTENSION NAME: %s\n' "$1" >&2 testNewExtensionLine_rc=1 else ALREADY_TESTED_EXTENSIONS="$ALREADY_TESTED_EXTENSIONS $1" testNewExtensionLine_extension="$1" while test $# -ge 2; do shift testNewExtensionLine_phpVersion="$1" if ! testExtension "$testNewExtensionLine_extension" "$1"; then testNewExtensionLine_rc=1 fi done fi fi return $testNewExtensionLine_rc } # Get the list of all supported PHP versions # # Arguments: # $1: space-separated list with the names of the PHP extensions to be tested # # Outputs: # the space-separated list of supported PHP versions getAllPHPVersionsForExtensions() { getAllPHPVersionsForExtensions_result='' IFS=' ' for getAllPHPVersionsForExtensions_extension in $1; do getAllPHPVersionsForExtensions_this="$(getAllPHPVersionsForExtension "$getAllPHPVersionsForExtensions_extension")" if test -z "$getAllPHPVersionsForExtensions_this"; then return fi if test -z "$getAllPHPVersionsForExtensions_result"; then getAllPHPVersionsForExtensions_result="$getAllPHPVersionsForExtensions_this" else getAllPHPVersionsForExtensions_tmp='' for getAllPHPVersionsForExtensions_php1 in $getAllPHPVersionsForExtensions_this; do if stringInList "$getAllPHPVersionsForExtensions_php1" "$getAllPHPVersionsForExtensions_result"; then getAllPHPVersionsForExtensions_tmp="$getAllPHPVersionsForExtensions_tmp $getAllPHPVersionsForExtensions_php1" fi done getAllPHPVersionsForExtensions_result="${getAllPHPVersionsForExtensions_tmp# }" fi done printf '%s' "$getAllPHPVersionsForExtensions_result" } # Get the list of all supported PHP versions # # Arguments: # $1: the names of a PHP extension to be tested # # Outputs: # the space-separated list of supported PHP versions getAllPHPVersionsForExtension() { getAllPHPVersionsForExtension_result='' while IFS= read -r getAllPHPVersionsForExtension_line; do getAllPHPVersionsForExtension_ok= IFS=' ' for getAllPHPVersionsForExtension_chunk in $getAllPHPVersionsForExtension_line; do if test -z "$getAllPHPVersionsForExtension_ok"; then if test "$getAllPHPVersionsForExtension_chunk" = "$1"; then getAllPHPVersionsForExtension_ok=y else getAllPHPVersionsForExtension_ok=n fi else if test $getAllPHPVersionsForExtension_ok = 'y'; then if test -z "$getAllPHPVersionsForExtension_result"; then getAllPHPVersionsForExtension_result="$getAllPHPVersionsForExtension_chunk" else if ! stringInList "$getAllPHPVersionsForExtension_chunk" "$getAllPHPVersionsForExtension_result"; then getAllPHPVersionsForExtension_result="$getAllPHPVersionsForExtension_result $getAllPHPVersionsForExtension_chunk" fi fi fi fi done done <"$CI_BUILD_DIR/data/supported-extensions" printf '%s' "$getAllPHPVersionsForExtension_result" } # Test extensions by reading a commit message # # Arguments: # $1: the commit hash # # Set: # STOP_NEXT_COMMITS to 1 if we should skip next commits # # Return: # 0 (true): if test passes # 1 (false): if test fails testExtensionsFromMessage() { testExtensionsFromMessage_result=0 TEST_EXTENSIONS= FIRST_LINE=1 testExtensionsFromMessage_message="$(git -C "$CI_BUILD_DIR" log --pretty='format:%B' -n 1 "$1")" IFS=' ' for COMMIT_LINE in $testExtensionsFromMessage_message; do if test $FIRST_LINE -eq 1; then FIRST_LINE=0 else TESTLIST= case "$COMMIT_LINE" in Test:*) TESTLIST=${COMMIT_LINE#Test:} ;; TEST:*) TESTLIST=${COMMIT_LINE#TEST:} ;; test:*) TESTLIST=${COMMIT_LINE#test:} ;; esac if test -n "$TESTLIST"; then IFS=' ,;' for COMMIT_LINE_EXT in $TESTLIST; do if test $COMMIT_LINE_EXT = '-STOP-'; then STOP_NEXT_COMMITS=1 elif test -z "$TEST_EXTENSIONS"; then TEST_EXTENSIONS=$COMMIT_LINE_EXT else if ! stringInList "$COMMIT_LINE_EXT" "$TEST_EXTENSIONS"; then TEST_EXTENSIONS="$TEST_EXTENSIONS $COMMIT_LINE_EXT" fi fi done fi fi IFS=' ' for TEST_EXTENSION in $TEST_EXTENSIONS; do if ! stringInList "$TEST_EXTENSION" "$ALREADY_TESTED_EXTENSIONS"; then ALREADY_TESTED_EXTENSIONS="$ALREADY_TESTED_EXTENSIONS $TEST_EXTENSION" TEST_EXTENSION="$(printf '%s' "$TEST_EXTENSION" | sed 's/\+/ /g')" printf '### TESTING EXTENSION(S) %s ###\n' "$TEST_EXTENSION" for TEST_PHPVERSION in $(getAllPHPVersionsForExtensions "$TEST_EXTENSION"); do if ! testExtension "$TEST_EXTENSION" "$TEST_PHPVERSION"; then testExtensionsFromMessage_result=1 fi done fi done done resetIFS return $testExtensionsFromMessage_result } STOP_NEXT_COMMITS=0 TESTS_RESULTS=0 ADDED_EXTENSION_LINE= FOUND_ATAT= IFS=' ' for DIFF_LINE in $(git -C "$CI_BUILD_DIR" diff --no-indent-heuristic --minimal --no-color --word-diff=none -no-renames --unified=0 "$CI_COMMIT_RANGE" -- data/supported-extensions); do if test -n "$DIFF_LINE"; then if test -z "$FOUND_ATAT"; then if test -z "${DIFF_LINE##@@*}"; then FOUND_ATAT=y fi elif test -z "${DIFF_LINE##+*}"; then resetIFS ADDED_EXTENSION_LINE="${DIFF_LINE##+}" if ! testNewExtensionLine $ADDED_EXTENSION_LINE; then TESTS_RESULTS=1 fi fi fi done IFS=' ' for COMMIT_HASH in $(git -C "$CI_BUILD_DIR" log --pretty='format:%H' "$CI_COMMIT_RANGE"); do if ! testExtensionsFromMessage "$COMMIT_HASH"; then TESTS_RESULTS=1 fi if test $STOP_NEXT_COMMITS -eq 1; then break fi done if test $TESTS_RESULTS -ne 0; then exit $TESTS_RESULTS fi if test -z "$ADDED_EXTENSION_LINE"; then echo 'No new extensions detected.' fi