From 23b44e12a0bff27050baa0b335762861b5e4e1ab Mon Sep 17 00:00:00 2001 From: mattgoud Date: Wed, 9 Sep 2026 19:15:28 +0200 Subject: [PATCH] Pass php-version to PHPStan instead of only to the runtime The action fed its php-version input to shivammathur/setup-php and to nothing else. PHPStan never received it, so it took the PHP language level it analyses with from the analysed project's composer platform declaration, which meant every entry of a module matrix analysed the same level whatever PHP binary it ran on. Derive the level from the input and emit it as its own neon include. The include is placed before the module config so a module that deliberately pins phpVersion keeps the final word: neon resolves a key from the last include that defines it. The config assembly is reworked into an includes list so the injected file reaches all three paths, with or without a module config, merging enabled or disabled. --- .github/actions/php-ci/phpstan/action.yml | 74 ++++++++++++++--------- 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/.github/actions/php-ci/phpstan/action.yml b/.github/actions/php-ci/phpstan/action.yml index 16e5e73..9d46111 100644 --- a/.github/actions/php-ci/phpstan/action.yml +++ b/.github/actions/php-ci/phpstan/action.yml @@ -112,15 +112,25 @@ runs: cd - fi - PHPSTAN_CONFIG="vendor/prestashop/php-dev-tools/phpstan/ps-module-extension.neon" - - if [ -f "$PHPSTAN_CONFIG" ]; then - echo "✓ Using Php-dev-tools PHPStan configuration: $PHPSTAN_CONFIG" + PS_MODULE_EXTENSION="vendor/prestashop/php-dev-tools/phpstan/ps-module-extension.neon" + + if [ -f "$PS_MODULE_EXTENSION" ]; then + echo "✓ Using Php-dev-tools PHPStan configuration: $PS_MODULE_EXTENSION" else - echo "❌ Php-dev-tools PHPStan configuration not found: $PHPSTAN_CONFIG" - echo "Running PHPStan without configuration file..." - PHPSTAN_CONFIG="" + echo "❌ Php-dev-tools PHPStan configuration not found: $PS_MODULE_EXTENSION" + echo "Continuing without it..." + PS_MODULE_EXTENSION="" fi + + # PHPStan takes the PHP language level it analyses with from the analysed project's + # composer platform declaration, never from the PHP binary it runs on. Without this + # the php-version input only changes the runtime, and every entry of a matrix ends up + # analysing the same level. Emitted as its own include, placed before the module + # config below, so a module that deliberately pins phpVersion still wins. + PHP_VERSION_ID=$(echo "${{ inputs.php-version }}" | awk -F. '{ printf "%d%02d00", $1, ($2 == "" ? 0 : $2) }') + PHP_VERSION_CONFIG="phpstan-php-version.neon" + printf 'parameters:\n phpVersion: %s\n' "$PHP_VERSION_ID" > "$PHP_VERSION_CONFIG" + echo "✓ Analysing at PHP language level $PHP_VERSION_ID (from php-version ${{ inputs.php-version }})" echo "Setting PrestaShop environment variable..." export _PS_ROOT_DIR_="../../" @@ -142,35 +152,43 @@ runs: TARGET_DIRS+=("classes/") fi + MODULE_CONFIG_FILE="" if [ -n "${{ inputs.phpstan-config }}" ]; then echo "Processing additional PHPStan configuration..." # Check if the config file exists in the module directory - MODULE_CONFIG_FILE="${{ inputs.phpstan-config }}" - if [ -f "$MODULE_CONFIG_FILE" ]; then + if [ -f "${{ inputs.phpstan-config }}" ]; then + MODULE_CONFIG_FILE="${{ inputs.phpstan-config }}" echo "✓ Found additional PHPStan config: $MODULE_CONFIG_FILE" - - if [ "${{ inputs.phpstan-config-merge }}" = "false" ]; then - # Use the module config directly without merging (module already includes ps-module-extension.neon) - PHPSTAN_CONFIG="$MODULE_CONFIG_FILE" - echo "✓ Using module PHPStan config directly (merge disabled): $PHPSTAN_CONFIG" - else - # Create a temporary PHPStan config that includes both configs - TEMP_CONFIG="phpstan-temp.neon" - echo "includes:" > "$TEMP_CONFIG" - echo " - $PHPSTAN_CONFIG" >> "$TEMP_CONFIG" - echo " - $MODULE_CONFIG_FILE" >> "$TEMP_CONFIG" - - # Use the temporary config instead of the original - PHPSTAN_CONFIG="$TEMP_CONFIG" - echo "✓ Created merged PHPStan configuration: $TEMP_CONFIG" - echo "Generated config content:" - cat "$TEMP_CONFIG" - fi else - echo "⚠️ No additional PHPStan config file found: $MODULE_CONFIG_FILE" + echo "⚠️ No additional PHPStan config file found: ${{ inputs.phpstan-config }}" fi fi + + # Order matters: neon resolves a key from the last include that defines it, so the + # module config comes last and keeps the final word over the injected phpVersion. + INCLUDES=() + + # Skipped when merging is disabled: the module config already includes it itself + if [ -n "$PS_MODULE_EXTENSION" ] \ + && { [ -z "$MODULE_CONFIG_FILE" ] || [ "${{ inputs.phpstan-config-merge }}" != "false" ]; }; then + INCLUDES+=("$PS_MODULE_EXTENSION") + fi + + INCLUDES+=("$PHP_VERSION_CONFIG") + + if [ -n "$MODULE_CONFIG_FILE" ]; then + INCLUDES+=("$MODULE_CONFIG_FILE") + fi + + PHPSTAN_CONFIG="phpstan-temp.neon" + echo "includes:" > "$PHPSTAN_CONFIG" + for INCLUDE in "${INCLUDES[@]}"; do + echo " - $INCLUDE" >> "$PHPSTAN_CONFIG" + done + echo "✓ Created PHPStan configuration: $PHPSTAN_CONFIG" + echo "Generated config content:" + cat "$PHPSTAN_CONFIG" # Build the final command array PHPSTAN_ARGS=("analyse" "--verbose" "--error-format=github")