From 54886cc9208a079f33ee29d13e24a2e9cb1716bb Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Thu, 2 Jul 2026 16:30:14 +0200 Subject: [PATCH 1/5] Extracted composer audit configuration for reusability --- .../configure_composer_audit_ignores.sh | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100755 bin/_common/configure_composer_audit_ignores.sh diff --git a/bin/_common/configure_composer_audit_ignores.sh b/bin/_common/configure_composer_audit_ignores.sh new file mode 100755 index 0000000..3e1e0f1 --- /dev/null +++ b/bin/_common/configure_composer_audit_ignores.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +set -o errexit +set -o nounset +set -o pipefail + +add_audit_ignores() { + local reason=$1 + shift + + local advisory + for advisory in "$@"; do + composer config audit.ignore --json --merge "{\"${advisory}\":\"${reason}\"}" + done +} + +PHP74_ADVISORIES=( + PKSA-xwpn-zs9j-6wy5 + PKSA-sf9j-1gs7-xzvx + PKSA-7h5p-prw9-w5nr +) + +PHP7X_PHP80_ADVISORIES=( + PKSA-5k7f-wvjj-jrgw + PKSA-sjvz-tbbr-vwth + PKSA-h8hf-ytnd-5t9q + PKSA-wwb1-81rc-pd65 + PKSA-hgmw-wn4d-hpcy + PKSA-kvv6-36cr-fkzb + PKSA-n14z-jjjg-g8vd + PKSA-3mcc-k66d-pydb + PKSA-gw7n-z4yx-7xjt + PKSA-dpx1-78wg-1kqs + PKSA-21g2-dzjv-sky5 + PKSA-v3kg-5xkr-pykw + PKSA-yhcn-xrg3-68b1 + PKSA-2wrf-1xmk-1pky + PKSA-6319-ffpf-gx66 + PKSA-n7sg-8f52-pqtf + PKSA-8kk8-h2xr-h5nx + PKSA-2rbx-bjdx-4d4d + PKSA-fs5b-x5k4-1h39 + PKSA-fbvq-z33h-r2np + PKSA-g9zw-qxh8-pq8w + PKSA-yd6k-t2gh-1m43 + PKSA-1tmc-rt7x-12w6 + PKSA-xx6c-6d96-db2w + PKSA-8zx5-v2nz-58pb +) + +PHP_VERSION_INPUT=${1:-$(php -r 'echo PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION;')} +IFS=. read -r PHP_MAJOR_VERSION PHP_MINOR_VERSION _ <<< "$PHP_VERSION_INPUT" +PHP_VERSION=${PHP_MAJOR_VERSION}.${PHP_MINOR_VERSION} + +if [ "$PHP_VERSION" = "7.4" ]; then + add_audit_ignores \ + "The affected version of 3rd party component is installed on PHP 7.4. There is no alternative supporting PHP 7.4. Consider upgrading to PHP 8.1+" \ + "${PHP74_ADVISORIES[@]}" +fi + +if [ "$PHP_VERSION" = "7.3" ] || [ "$PHP_VERSION" = "7.4" ] || [ "$PHP_VERSION" = "8.0" ]; then + add_audit_ignores \ + "The affected version of 3rd party component is installed on PHP ${PHP_VERSION}. There is no alternative supporting PHP ${PHP_VERSION}. Consider upgrading to PHP 8.1+" \ + "${PHP7X_PHP80_ADVISORIES[@]}" +fi From cd5fb61458c22a8eb1c473e55bbf618b817d17ac Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Fri, 3 Jul 2026 16:31:22 +0200 Subject: [PATCH 2/5] Refactored composer audit ignore to rely on shared source of truth --- bin/_common/composer_audit_ignore.sh | 63 ++----------------- .../configure_composer_audit_ignores.sh | 6 +- 2 files changed, 10 insertions(+), 59 deletions(-) diff --git a/bin/_common/composer_audit_ignore.sh b/bin/_common/composer_audit_ignore.sh index d386670..c966772 100644 --- a/bin/_common/composer_audit_ignore.sh +++ b/bin/_common/composer_audit_ignore.sh @@ -2,65 +2,14 @@ add_composer_audit_ignore_config() { docker exec install_dependencies bash -c ' + set -o errexit cd /var/www - add_audit_ignores() { - local reason=$1 - shift - - for advisory in "$@"; do - composer config audit.ignore --json --merge "{\"$advisory\":\"$reason\"}" - done - - return $? - } - - PHP74_ADVISORIES=( - PKSA-xwpn-zs9j-6wy5 - PKSA-sf9j-1gs7-xzvx - PKSA-7h5p-prw9-w5nr - ) - - PHP7X_PHP80_ADVISORIES=( - PKSA-5k7f-wvjj-jrgw - PKSA-sjvz-tbbr-vwth - PKSA-h8hf-ytnd-5t9q - PKSA-wwb1-81rc-pd65 - PKSA-hgmw-wn4d-hpcy - PKSA-kvv6-36cr-fkzb - PKSA-n14z-jjjg-g8vd - PKSA-3mcc-k66d-pydb - PKSA-gw7n-z4yx-7xjt - PKSA-dpx1-78wg-1kqs - PKSA-21g2-dzjv-sky5 - PKSA-v3kg-5xkr-pykw - PKSA-yhcn-xrg3-68b1 - PKSA-2wrf-1xmk-1pky - PKSA-6319-ffpf-gx66 - PKSA-n7sg-8f52-pqtf - PKSA-8kk8-h2xr-h5nx - PKSA-2rbx-bjdx-4d4d - PKSA-fs5b-x5k4-1h39 - PKSA-fbvq-z33h-r2np - PKSA-g9zw-qxh8-pq8w - PKSA-yd6k-t2gh-1m43 - PKSA-1tmc-rt7x-12w6 - PKSA-xx6c-6d96-db2w - ) - - PHP_VERSION="$(php -r "echo PHP_MAJOR_VERSION . \".\" . PHP_MINOR_VERSION;")" - - if [ "$PHP_VERSION" = "7.4" ]; then - add_audit_ignores \ - "The affected version of 3rd party component is installed on PHP 7.4. There is no alternative supporting PHP 7.4. Consider upgrading to PHP 8.1+" \ - "${PHP74_ADVISORIES[@]}" - fi - - if [ "$PHP_VERSION" = "7.3" ] || [ "$PHP_VERSION" = "7.4" ] || [ "$PHP_VERSION" = "8.0" ]; then - add_audit_ignores \ - "The affected version of 3rd party component is installed on PHP ${PHP_VERSION}. There is no alternative supporting PHP ${PHP_VERSION}. Consider upgrading to PHP 8.1+" \ - "${PHP7X_PHP80_ADVISORIES[@]}" - fi + script=$(mktemp) + curl -fsSL \ + https://raw.githubusercontent.com/ibexa/ci-scripts/main/bin/_common/configure_composer_audit_ignores.sh \ + --output "$script" + bash "$script" ' return $? diff --git a/bin/_common/configure_composer_audit_ignores.sh b/bin/_common/configure_composer_audit_ignores.sh index 3e1e0f1..6e93d92 100755 --- a/bin/_common/configure_composer_audit_ignores.sh +++ b/bin/_common/configure_composer_audit_ignores.sh @@ -12,6 +12,8 @@ add_audit_ignores() { for advisory in "$@"; do composer config audit.ignore --json --merge "{\"${advisory}\":\"${reason}\"}" done + + return 0 } PHP74_ADVISORIES=( @@ -52,13 +54,13 @@ PHP_VERSION_INPUT=${1:-$(php -r 'echo PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSIO IFS=. read -r PHP_MAJOR_VERSION PHP_MINOR_VERSION _ <<< "$PHP_VERSION_INPUT" PHP_VERSION=${PHP_MAJOR_VERSION}.${PHP_MINOR_VERSION} -if [ "$PHP_VERSION" = "7.4" ]; then +if [[ "$PHP_VERSION" = "7.4" ]]; then add_audit_ignores \ "The affected version of 3rd party component is installed on PHP 7.4. There is no alternative supporting PHP 7.4. Consider upgrading to PHP 8.1+" \ "${PHP74_ADVISORIES[@]}" fi -if [ "$PHP_VERSION" = "7.3" ] || [ "$PHP_VERSION" = "7.4" ] || [ "$PHP_VERSION" = "8.0" ]; then +if [[ "$PHP_VERSION" = "7.3" ]] || [[ "$PHP_VERSION" = "7.4" ]] || [[ "$PHP_VERSION" = "8.0" ]]; then add_audit_ignores \ "The affected version of 3rd party component is installed on PHP ${PHP_VERSION}. There is no alternative supporting PHP ${PHP_VERSION}. Consider upgrading to PHP 8.1+" \ "${PHP7X_PHP80_ADVISORIES[@]}" From 3e855455995a4b40070466fbb48ba60afcb90927 Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Fri, 3 Jul 2026 16:31:22 +0200 Subject: [PATCH 3/5] [Tests] Added coverage for ./bin/_common/configure_composer_audit_ignores.sh --- composer.json | 5 +- .../configure_composer_audit_ignores_test.sh | 65 +++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100755 tests/bin/configure_composer_audit_ignores_test.sh diff --git a/composer.json b/composer.json index fc9912b..0cb2fd0 100644 --- a/composer.json +++ b/composer.json @@ -46,7 +46,10 @@ "phpstan-baseline": "phpstan analyse -c phpstan.neon --generate-baseline", "fix-cs": "php-cs-fixer fix --config=.php-cs-fixer.php -v --show-progress=dots", "check-cs": "@fix-cs --dry-run", - "test": "phpunit -c phpunit.xml" + "test": [ + "phpunit -c phpunit.xml", + "tests/bin/configure_composer_audit_ignores_test.sh" + ] }, "config": { "allow-plugins": { diff --git a/tests/bin/configure_composer_audit_ignores_test.sh b/tests/bin/configure_composer_audit_ignores_test.sh new file mode 100755 index 0000000..14b2d0b --- /dev/null +++ b/tests/bin/configure_composer_audit_ignores_test.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +set -o errexit +set -o nounset +set -o pipefail + +ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd) +SCRIPT=${ROOT_DIR}/bin/_common/configure_composer_audit_ignores.sh +TEST_DIR=$(mktemp -d) +OUTPUT=${TEST_DIR}/composer-calls + +cleanup() { + rm -rf "$TEST_DIR" + return 0 +} +trap cleanup EXIT + +cat > "${TEST_DIR}/composer" <<'EOF' +#!/bin/bash +printf '%s\n' "$*" >> "$COMPOSER_CALLS_OUTPUT" +if [ "${COMPOSER_FAILURE:-0}" = "1" ]; then + exit 1 +fi +EOF +chmod +x "${TEST_DIR}/composer" + +run_for_version() { + local version=$1 + : > "$OUTPUT" + COMPOSER_CALLS_OUTPUT=$OUTPUT PATH="${TEST_DIR}:${PATH}" bash "$SCRIPT" "$version" + return 0 +} + +assert_line_count() { + local expected=$1 + local actual + actual=$(wc -l < "$OUTPUT") + + if [[ "$actual" -ne "$expected" ]]; then + echo "Expected ${expected} Composer calls, got ${actual}" >&2 + exit 1 + fi + return 0 +} + +run_for_version 7.3 +assert_line_count 25 +! grep -q PKSA-xwpn-zs9j-6wy5 "$OUTPUT" + +run_for_version 7.4.33 +assert_line_count 28 +grep -q PKSA-xwpn-zs9j-6wy5 "$OUTPUT" +grep -q PKSA-8zx5-v2nz-58pb "$OUTPUT" + +run_for_version 8.0 +assert_line_count 25 +! grep -q PKSA-xwpn-zs9j-6wy5 "$OUTPUT" + +run_for_version 8.1 +assert_line_count 0 + +if COMPOSER_CALLS_OUTPUT=$OUTPUT PATH="${TEST_DIR}:${PATH}" COMPOSER_FAILURE=1 bash "$SCRIPT" 7.3; then + echo 'Expected a Composer failure to be propagated' >&2 + exit 1 +fi From 7ce7f6266ce151e246178fbf0b992c295a6d5aa0 Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Fri, 3 Jul 2026 16:31:22 +0200 Subject: [PATCH 4/5] Parametrized ci-scripts ref for nested script fetches The prepare scripts fetched composer_audit_ignore.sh, which in turn fetched configure_composer_audit_ignores.sh, from a hardcoded raw.githubusercontent.com/ibexa/ci-scripts/main URL. This defeated the ci-scripts-branch testing mechanism: even when CI pointed at a feature branch, the nested fetches still pulled main, so branch changes to these scripts (e.g. the twig advisory in the shared source of truth) never ran on CI and could not be validated before merge. Introduced a CI_SCRIPTS_REF environment variable (defaulting to main) threaded through every nested fetch: the prepare scripts use it in their composer_audit_ignore.sh curl and pass it into the install_dependencies container, and composer_audit_ignore.sh forwards it via docker exec -e so the container's bash resolves the configure_composer_audit_ignores.sh URL against the same ref. Setting the ref once now propagates through the whole chain. Co-Authored-By: Claude Opus 4.8 --- bin/4.6.x-dev/prepare_project_edition.sh | 5 ++++- bin/^3.3.x-dev/prepare_project_edition.sh | 5 ++++- bin/_common/composer_audit_ignore.sh | 6 ++++-- bin/stable/prepare_project_edition.sh | 5 ++++- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/bin/4.6.x-dev/prepare_project_edition.sh b/bin/4.6.x-dev/prepare_project_edition.sh index 9657efb..fcce710 100755 --- a/bin/4.6.x-dev/prepare_project_edition.sh +++ b/bin/4.6.x-dev/prepare_project_edition.sh @@ -7,6 +7,8 @@ PROJECT_BUILD_DIR=${HOME}/build/project export COMPOSE_FILE=$3 export PHP_IMAGE=${4-ghcr.io/ibexa/docker/php:8.3-node18} export COMPOSER_MAX_PARALLEL_HTTP=6 # Reduce Composer parallelism to work around Github Actions network errors +# Git ref of ibexa/ci-scripts used for nested script fetches; defaults to main +export CI_SCRIPTS_REF="${CI_SCRIPTS_REF:-main}" if [[ -n "${DOCKER_PASSWORD}" ]]; then echo "> Set up Docker credentials" @@ -37,6 +39,7 @@ docker run --name install_dependencies -d \ -e COMPOSER_MAX_PARALLEL_HTTP \ -e PHP_INI_ENV_memory_limit -e COMPOSER_MEMORY_LIMIT \ -e COMPOSER_NO_INTERACTION=1 \ +-e CI_SCRIPTS_REF \ ${PHP_IMAGE} echo "> Setting up website skeleton" @@ -44,7 +47,7 @@ composer create-project ibexa/website-skeleton:$PROJECT_VERSION . --no-install - # Configure composer audit for unresolvable advisories echo "> Adding composer audit.ignore script, if applies" -curl -L "https://raw.githubusercontent.com/ibexa/ci-scripts/main/bin/_common/composer_audit_ignore.sh" > composer_audit_ignore.sh +curl -L "https://raw.githubusercontent.com/ibexa/ci-scripts/${CI_SCRIPTS_REF}/bin/_common/composer_audit_ignore.sh" > composer_audit_ignore.sh source ./composer_audit_ignore.sh add_composer_audit_ignore_config diff --git a/bin/^3.3.x-dev/prepare_project_edition.sh b/bin/^3.3.x-dev/prepare_project_edition.sh index efcd30d..7a1d2b4 100644 --- a/bin/^3.3.x-dev/prepare_project_edition.sh +++ b/bin/^3.3.x-dev/prepare_project_edition.sh @@ -7,6 +7,8 @@ PROJECT_BUILD_DIR=${HOME}/build/project export COMPOSE_FILE=$3 export PHP_IMAGE=${4-ghcr.io/ibexa/docker/php:8.3-node18} export COMPOSER_MAX_PARALLEL_HTTP=6 # Reduce Composer parallelism to work around Github Actions network errors +# Git ref of ibexa/ci-scripts used for nested script fetches; defaults to main +export CI_SCRIPTS_REF="${CI_SCRIPTS_REF:-main}" if [[ -n "${DOCKER_PASSWORD}" ]]; then echo "> Set up Docker credentials" @@ -37,6 +39,7 @@ docker run --name install_dependencies -d \ -e COMPOSER_MAX_PARALLEL_HTTP \ -e PHP_INI_ENV_memory_limit -e COMPOSER_MEMORY_LIMIT \ -e COMPOSER_NO_INTERACTION=1 \ +-e CI_SCRIPTS_REF \ ${PHP_IMAGE} echo "> Setting up website skeleton" @@ -112,7 +115,7 @@ fi # Configure composer audit for unresolvable advisories echo "> Adding composer audit.ignore script, if applies" -curl -L "https://raw.githubusercontent.com/ibexa/ci-scripts/main/bin/_common/composer_audit_ignore.sh" > composer_audit_ignore.sh +curl -L "https://raw.githubusercontent.com/ibexa/ci-scripts/${CI_SCRIPTS_REF}/bin/_common/composer_audit_ignore.sh" > composer_audit_ignore.sh source ./composer_audit_ignore.sh add_composer_audit_ignore_config diff --git a/bin/_common/composer_audit_ignore.sh b/bin/_common/composer_audit_ignore.sh index c966772..46bc1e9 100644 --- a/bin/_common/composer_audit_ignore.sh +++ b/bin/_common/composer_audit_ignore.sh @@ -1,13 +1,15 @@ #!/bin/bash add_composer_audit_ignore_config() { - docker exec install_dependencies bash -c ' + # CI_SCRIPTS_REF is passed into the container via -e so the single-quoted + # heredoc below is expanded by the container's bash, not the parent shell. + docker exec -e CI_SCRIPTS_REF install_dependencies bash -c ' set -o errexit cd /var/www script=$(mktemp) curl -fsSL \ - https://raw.githubusercontent.com/ibexa/ci-scripts/main/bin/_common/configure_composer_audit_ignores.sh \ + "https://raw.githubusercontent.com/ibexa/ci-scripts/${CI_SCRIPTS_REF:-main}/bin/_common/configure_composer_audit_ignores.sh" \ --output "$script" bash "$script" ' diff --git a/bin/stable/prepare_project_edition.sh b/bin/stable/prepare_project_edition.sh index 9e33a42..1e2cff6 100755 --- a/bin/stable/prepare_project_edition.sh +++ b/bin/stable/prepare_project_edition.sh @@ -7,6 +7,8 @@ PROJECT_BUILD_DIR=${HOME}/build/project export COMPOSE_FILE=$3 export PHP_IMAGE=${4-ghcr.io/ibexa/docker/php:8.3-node18} export COMPOSER_MAX_PARALLEL_HTTP=6 # Reduce Composer parallelism to work around Github Actions network errors +# Git ref of ibexa/ci-scripts used for nested script fetches; defaults to main +export CI_SCRIPTS_REF="${CI_SCRIPTS_REF:-main}" DEPENDENCY_PACKAGE_DIR=$(pwd) @@ -24,6 +26,7 @@ docker run --name install_dependencies -d \ -e COMPOSER_MAX_PARALLEL_HTTP \ -e PHP_INI_ENV_memory_limit -e COMPOSER_MEMORY_LIMIT \ -e COMPOSER_NO_INTERACTION=1 \ +-e CI_SCRIPTS_REF \ ${PHP_IMAGE} echo "> Setting up skeleton" @@ -40,7 +43,7 @@ if [[ $PHP_IMAGE == *"8.3"* ]]; then else # Configure composer audit for unresolvable advisories echo "> Adding composer audit.ignore script, if applies" - curl -L "https://raw.githubusercontent.com/ibexa/ci-scripts/main/bin/_common/composer_audit_ignore.sh" > composer_audit_ignore.sh + curl -L "https://raw.githubusercontent.com/ibexa/ci-scripts/${CI_SCRIPTS_REF}/bin/_common/composer_audit_ignore.sh" > composer_audit_ignore.sh source ./composer_audit_ignore.sh add_composer_audit_ignore_config From d5ed104db2111819c68dc754cbac5079edebe27e Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Fri, 3 Jul 2026 16:31:22 +0200 Subject: [PATCH 5/5] [Tests] Added coverage for CI_SCRIPTS_REF propagation Verified that add_composer_audit_ignore_config() fetches configure_composer_audit_ignores.sh from the ref given by CI_SCRIPTS_REF, defaulting to main when the variable is unset. Co-Authored-By: Claude Opus 4.8 --- composer.json | 3 +- tests/bin/composer_audit_ignore_ref_test.sh | 92 +++++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100755 tests/bin/composer_audit_ignore_ref_test.sh diff --git a/composer.json b/composer.json index 0cb2fd0..7f681d3 100644 --- a/composer.json +++ b/composer.json @@ -48,7 +48,8 @@ "check-cs": "@fix-cs --dry-run", "test": [ "phpunit -c phpunit.xml", - "tests/bin/configure_composer_audit_ignores_test.sh" + "tests/bin/configure_composer_audit_ignores_test.sh", + "tests/bin/composer_audit_ignore_ref_test.sh" ] }, "config": { diff --git a/tests/bin/composer_audit_ignore_ref_test.sh b/tests/bin/composer_audit_ignore_ref_test.sh new file mode 100755 index 0000000..eb6b43c --- /dev/null +++ b/tests/bin/composer_audit_ignore_ref_test.sh @@ -0,0 +1,92 @@ +#!/bin/bash + +# Verifies that add_composer_audit_ignore_config() fetches +# configure_composer_audit_ignores.sh from the ref given by CI_SCRIPTS_REF, +# defaulting to `main` when the variable is unset. + +set -o errexit +set -o nounset +set -o pipefail + +ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd) +SCRIPT=${ROOT_DIR}/bin/_common/composer_audit_ignore.sh +TEST_DIR=$(mktemp -d) +CURL_URLS_OUTPUT=${TEST_DIR}/curl-urls +export CURL_URLS_OUTPUT + +cleanup() { + rm -rf "$TEST_DIR" + return 0 +} +trap cleanup EXIT + +# Fake `docker`: emulate `docker exec [-e VAR]... bash -c