diff --git a/bin/tests b/bin/tests index c0c48d5..71fdb2a 100755 --- a/bin/tests +++ b/bin/tests @@ -1,9 +1,37 @@ -#!/usr/bin/env sh -set -ex +#!/usr/bin/env bash -#docker build -t localhost/tests-util build/tests-util -docker run --init \ - --rm \ - -i \ - -v "${PWD}:/var/www/html" \ - localhost/tests-util wp-patch-tests +build_tests_util() { + docker build -t "${TESTS_UTIL_IMAGE:?}" build/tests-util +} + +main() { + # Use docker BuildKit + DOCKER_BUILDKIT=1 + export DOCKER_BUILDKIT + + TESTS_UTIL_IMAGE="localhost/tests-util:latest" + export TESTS_UTIL_IMAGE + + if [ "${1:-}" = "build" ]; then + echo "Rebuilding image..." + build_tests_util + elif ! docker inspect --type=image "${TESTS_UTIL_IMAGE}" > /dev/null 2>&1; then + echo "Image does not exist locally. Building..." + build_tests_util + fi + + local runCommand="wp-patch-tests" + if [ "${1:-}" = "shell" ]; then + runCommand="/bin/bash" + fi + + docker run --init \ + --rm \ + --interactive \ + --volume "./build/tests-util/wp-patch-tests.sh:/usr/local/bin/wp-patch-tests" \ + --volume "./build/docker-bake.hcl:/data/docker-bake.hcl:ro" \ + --volume "./patches:/data/patches:ro" \ + "${TESTS_UTIL_IMAGE}" "${runCommand}" +} + +main "${@}" diff --git a/build/tests-util/Dockerfile b/build/tests-util/Dockerfile index 637aaa1..3e16ada 100644 --- a/build/tests-util/Dockerfile +++ b/build/tests-util/Dockerfile @@ -30,7 +30,6 @@ COPY --from=wp-cli ["/usr/local/bin/wp", "/usr/local/bin/wp"] # WP patch tests COPY --chmod=0777 ["./wp-patch-tests.sh", "/usr/local/bin/wp-patch-tests"] - # Build final image ARG PHP_VERSION ARG WP_VERSION @@ -38,8 +37,11 @@ FROM --platform=${TARGETPLATFORM} wordpress:${WP_VERSION}-php${PHP_VERSION}-fpm- RUN set -eux \ - && apk add --update --no-cache git patch less \ + && apk add --update --no-cache gawk git grep patch less \ && git config --global --add safe.directory /var/www/html \ + && echo "memory_limit = 512M" > /usr/local/etc/php/conf.d/memory-limit.ini \ && ln -sf /var/www/composer/vendor/bin/parallel-lint /usr/local/bin/php-parallel-lint COPY --from=rootfs ["/", "/"] + +WORKDIR /data diff --git a/build/tests-util/wp-patch-tests.sh b/build/tests-util/wp-patch-tests.sh index c56270a..cbd6e5c 100755 --- a/build/tests-util/wp-patch-tests.sh +++ b/build/tests-util/wp-patch-tests.sh @@ -21,14 +21,16 @@ function getFileCount() { } function taskPrepareWpPatch() { - local patchDir="${1:?}" - local downloadRoot="${2:?}" + set -eou pipefail + local wpLongVersion="${1:?}" + local patchDir="${2:?}" + local downloadRoot="${3:?}" - local wpLongVersion + # Define variables local wpShortVersion local downloadPath - wpLongVersion="$(basename "${patchDir}")" + wpShortVersion="$(echo "${wpLongVersion}" | sed --expression='s/.0$//g')" downloadPath="${downloadRoot}/${wpLongVersion}" @@ -39,11 +41,23 @@ function taskPrepareWpPatch() { echo "> Applying patch" patch "${downloadPath}/wp-admin/update-core.php" <"${patchDir}/wp-admin-update-core.patch" - mv -v "${downloadPath}/wp-admin/update-core.php" "${PHP_TESTS_DIR}/update-core-${wpLongVersion}.php" + cp -v "${downloadPath}/wp-admin/update-core.php" "${PHP_TESTS_DIR}/update-core-${wpLongVersion}.php" rm "${downloadPath}" -rf } +function extractVersionsFromHCL() { + local hclFile="${1:?HCL file path required}" + + gawk ' + /args *= *get-args/ { + if (match($0, /get-args\("([0-9]+\.[0-9]+\.[0-9]+)", *"([0-9]+\.[0-9]+\.[0-9]+)"\)/, arr)) { + print arr[1], arr[2]; + } + } + ' "${hclFile}" +} + main() { PHP_TESTS_DIR="/data/test_files" export PHP_TESTS_DIR @@ -52,20 +66,35 @@ main() { local patchDir - # For each patch, download appropriate WP version, apply patch and check if file syntax is correct afterwards - for patchDir in patches/*/; do - echo "> Deploying task ${patchDir}" + local wpLongVersion + local wpPatchVersion + local expectedPatchCount=0 + + declare -a versions + mapfile -t versions < <(extractVersionsFromHCL /data/docker-bake.hcl) + + for version in "${versions[@]}"; do + wpLongVersion=$(echo "$version" | awk '{print $1}') + wpPatchVersion=$(echo "$version" | awk '{print $2}') + patchDir="/data/patches/${wpPatchVersion}" + printf "Deploying task [Version: %s, Patch: %s, Path: %s]\n" "${wpLongVersion}" "${wpPatchVersion}" "${patchDir}" # Introduce ~50ms overhead before deploying another task # Even shorter overhead helps. but better to be on safe side. # This should prevent concurrency issues sleep 0.05 - # Run task concurrently - taskPrepareWpPatch "${patchDir}" "/data/wp_src" & + if [ ! -d "${patchDir}" ]; then + printf "Error: Patch directory not found: %s\n" "${patchDir}" + return 1 + fi + + # Start the task in the background and capture the PID + taskPrepareWpPatch "${wpLongVersion}" "${patchDir}" "/data/wp_src" & + ((expectedPatchCount++)) done - echo "Waiting for all tasks to finish..." + echo "Waiting for all tasks to complete..." wait # Make sure that directory is not empty @@ -74,21 +103,23 @@ main() { return 1 fi - local numberOfPatches local numberOfTestFiles - numberOfPatches="$(getFileCount patches)" numberOfTestFiles="$(getFileCount "${PHP_TESTS_DIR}")" - if [ "${numberOfPatches}" != "${numberOfTestFiles}" ]; then + if [ "${expectedPatchCount}" != "${numberOfTestFiles}" ]; then echo "> Error - Unexpected number of files" - echo " Expected: ${numberOfPatches}" + echo " Expected: ${expectedPatchCount}" echo " Actual: ${numberOfTestFiles}" return 1 fi # Run php-lint on resulting patch files - php-parallel-lint "${PHP_TESTS_DIR}" -s --blame --exclude vendor -p php - return $? + if php-parallel-lint "${PHP_TESTS_DIR}" -s --blame --exclude vendor -p php; then + printf "> Success. All of the %d generated patch files were valid.\n" "${expectedPatchCount}" + return 0 + fi + + return 1 } main "${@}"