From a107b7f1f79af12e0b09f70be47b68e3f69b4504 Mon Sep 17 00:00:00 2001 From: Jonathan Smith <20701-jonathan1055@users.noreply.drupalcode.org> Date: Wed, 18 Dec 2024 09:29:49 +0000 Subject: [PATCH] Issue #3397162 by jonathan1055, alexpott, fjgarlin, cmlara, simonbaese: Tweak PHPStan config so paths are always correct and baseline is more usable --- assets/phpstan.neon | 3 +- docs/jobs/phpstan.md | 12 ++++-- includes/include.drupalci.main.yml | 49 ++++++++++++++----------- includes/include.drupalci.variables.yml | 4 ++ 4 files changed, 43 insertions(+), 25 deletions(-) diff --git a/assets/phpstan.neon b/assets/phpstan.neon index faf3dd1c..8a55bc46 100644 --- a/assets/phpstan.neon +++ b/assets/phpstan.neon @@ -1,5 +1,6 @@ includes: - - phpstan-baseline.neon + # This placeholder filename will be replaced with the value of variable $_PHPSTAN_BASELINE_FILENAME + - BASELINE_PLACEHOLDER parameters: level: 0 fileExtensions: diff --git a/docs/jobs/phpstan.md b/docs/jobs/phpstan.md index afb1c20a..acf09bda 100644 --- a/docs/jobs/phpstan.md +++ b/docs/jobs/phpstan.md @@ -6,14 +6,20 @@ If the project contains a `phpstan.neon` configuration file it will be used. If The pipeline variable `_PHPSTAN_LEVEL` can be set to a value from 0-9 to specify how relaxed or severe the code quality checks should be. This can be used to temporarily override the value in your `phpstan.neon` file. If no value is given, either in the variable or the file, then the default of 0 is used. See the [PHPStan rule levels](https://phpstan.org/user-guide/rule-levels) for more information. -Projects can specify [baseline](https://phpstan.org/user-guide/baseline) file(s) of messages to ignore, using the `includes:` keyword in the `phpstan.neon` file: +Projects can optionally specify [baseline](https://phpstan.org/user-guide/baseline) file(s) of messages to ignore. The default baseline file `phpstan-baseline.neon` stored in the project top-level folder, will be included if using the default `phpstan.neon` config file. If your project's baseline file is called something different, then specify the name in the `_PHPSTAN_BASELINE_FILENAME` variable: +``` +variables: + _PHPSTAN_BASELINE_FILENAME: 'your-baseline-file.neon' +``` + +To include multiple baseline files, your project will need its own `phpstan.neon` config file with a `includes:` keyword, for example: ``` includes: - - your-baseline-file.neon + - phpstan-baseline.neon - second-baseline-file.neon ``` -Any warnings that are found are written to a new baseline file which is available as a job artifact for download. These can be added into the existing baseline file until the code is fixed. Unmatched messages in the baseline file are also reported in the log. +A new baseline file is created which is available as a job artifact for download. This file will contain all warnings found, including those ignored in the single baseline file named in `_PHPSTAN_BASELINE_FILENAME`. Unmatched messages in the baseline file are reported in the log. In addition to testing at the current core version, the `phpstan` job has optional variants for the next major and minor core versions and the maximum PHP version. diff --git a/includes/include.drupalci.main.yml b/includes/include.drupalci.main.yml index f05176c5..0c87b7ce 100644 --- a/includes/include.drupalci.main.yml +++ b/includes/include.drupalci.main.yml @@ -634,34 +634,41 @@ phpcs: - composer script: - *check-composer-end-code - # If present, use PHPStan configuration neon file. + # Run from within project directory so paths are correct. + - cd $CI_PROJECT_DIR/$_WEB_ROOT/modules/custom/$CI_PROJECT_NAME && pwd + # If there is no PHPStan configuration neon file get the default from /assets/phpstan.neon - | - if [ -f $_WEB_ROOT/modules/custom/$CI_PROJECT_NAME/phpstan.neon ]; then - echo "Using the existing phpstan.neon configuration from the project." + if [ ! -f phpstan.neon ]; then + echo "Getting default phpstan.neon from https://git.drupalcode.org/$_CURL_TEMPLATES_REPO/-/raw/$_CURL_TEMPLATES_REF/assets/phpstan.neon" + curl -OL https://git.drupalcode.org/$_CURL_TEMPLATES_REPO/-/raw/$_CURL_TEMPLATES_REF/assets/phpstan.neon + # Change the baseline filename placeholder to the runtime value in $_PHPSTAN_BASELINE_FILENAME + sed -i "s#BASELINE_PLACEHOLDER#$_PHPSTAN_BASELINE_FILENAME#g" phpstan.neon else - echo "Executing curl -L --output $_WEB_ROOT/modules/custom/$CI_PROJECT_NAME/phpstan.neon https://git.drupalcode.org/$_CURL_TEMPLATES_REPO/-/raw/$_CURL_TEMPLATES_REF/assets/phpstan.neon" - curl -L --output $_WEB_ROOT/modules/custom/$CI_PROJECT_NAME/phpstan.neon https://git.drupalcode.org/$_CURL_TEMPLATES_REPO/-/raw/$_CURL_TEMPLATES_REF/assets/phpstan.neon + echo "Using the project's existing phpstan.neon config file" fi - export PHPSTAN_CONFIGURATION="--configuration=$_WEB_ROOT/modules/custom/$CI_PROJECT_NAME/phpstan.neon" - [ -n "$_PHPSTAN_LEVEL" ] && export PHPSTAN_CONFIGURATION="$PHPSTAN_CONFIGURATION --level=$_PHPSTAN_LEVEL" - # Add an empty baseline file to ensure it exists. - - touch $_WEB_ROOT/modules/custom/$CI_PROJECT_NAME/phpstan-baseline.neon - - php vendor/bin/phpstan --version + # Create an empty baseline if the file does not exist, as this is referenced in the default config file. + - touch $_PHPSTAN_BASELINE_FILENAME + - test -n "$_PHPSTAN_LEVEL" && LEVEL="--level=$_PHPSTAN_LEVEL" + - php $CI_PROJECT_DIR/vendor/bin/phpstan --version - php --version # Rely on PHPStan caching to execute analysis multiple times without performance drawback. # Output a copy in junit. - - echo "Executing php vendor/bin/phpstan analyze $_WEB_ROOT/modules/custom/$CI_PROJECT_NAME $PHPSTAN_CONFIGURATION" - - php vendor/bin/phpstan analyze $_WEB_ROOT/modules/custom/$CI_PROJECT_NAME $PHPSTAN_CONFIGURATION --error-format=junit > junit.xml || true + - echo "Executing php $CI_PROJECT_DIR/vendor/bin/phpstan analyze . --autoload-file='$CI_PROJECT_DIR/vendor/autoload.php' $LEVEL" + - php $CI_PROJECT_DIR/vendor/bin/phpstan analyze . --autoload-file="$CI_PROJECT_DIR/vendor/autoload.php" $LEVEL --no-progress --error-format=junit > $CI_PROJECT_DIR/junit.xml || true # Output a copy in GitLab code quality format. - - php vendor/bin/phpstan analyze $_WEB_ROOT/modules/custom/$CI_PROJECT_NAME $PHPSTAN_CONFIGURATION --no-progress --error-format=gitlab > phpstan-quality-report.json || true + - php $CI_PROJECT_DIR/vendor/bin/phpstan analyze . --autoload-file="$CI_PROJECT_DIR/vendor/autoload.php" $LEVEL --no-progress --error-format=gitlab > $CI_PROJECT_DIR/phpstan-quality-report.json || true # Output a copy in plain text for human logs. - - php vendor/bin/phpstan analyze $_WEB_ROOT/modules/custom/$CI_PROJECT_NAME $PHPSTAN_CONFIGURATION --no-progress || EXIT_CODE=$? - # Generate a new baseline. Allow empty baseline to ensure that artifact exists. - - | - php vendor/bin/phpstan analyze $_WEB_ROOT/modules/custom/$CI_PROJECT_NAME $PHPSTAN_CONFIGURATION --no-progress --generate-baseline --allow-empty-baseline || true - echo "This baseline file is an artifact you can download and use in the project." - # Ensure paths in artifacts are git-relative. - - sed -i "s#$_WEB_ROOT/modules/custom/$CI_PROJECT_NAME/##" junit.xml phpstan-baseline.neon phpstan-quality-report.json || true + - php $CI_PROJECT_DIR/vendor/bin/phpstan analyze . --autoload-file="$CI_PROJECT_DIR/vendor/autoload.php" $LEVEL --no-progress || EXIT_CODE=$? + # Delete the phpstan baseline file so that the new one will contain all errors ignored in that baseline file. + # This has to be delete (not just erase the contents) so that the symlink is broken, which will allow the file to be moved afterwards. + - rm -v $_PHPSTAN_BASELINE_FILENAME + - echo "Generating a PHPStan baseline file '$_PHPSTAN_BASELINE_FILENAME' available as a job artifact to download. This file will contain any new errors reported above, plus those already ignored in '$_PHPSTAN_BASELINE_FILENAME' if that file is being used." + # The baseline is created in the current directory so that the paths are correctly relative. Then the file is moved to the top level folder. + - php $CI_PROJECT_DIR/vendor/bin/phpstan analyze . --autoload-file="$CI_PROJECT_DIR/vendor/autoload.php" $LEVEL --no-progress --generate-baseline=$_PHPSTAN_BASELINE_FILENAME --allow-empty-baseline || true + - mv -v $_PHPSTAN_BASELINE_FILENAME $CI_PROJECT_DIR + # Fix paths in message text in the reports. + - cd $CI_PROJECT_DIR && pwd + - sed -i "s#$CI_PROJECT_DIR/$_WEB_ROOT/modules/custom/$CI_PROJECT_NAME/##g" junit.xml $_PHPSTAN_BASELINE_FILENAME phpstan-quality-report.json - exit $EXIT_CODE allow_failure: true artifacts: @@ -674,7 +681,7 @@ phpcs: name: artifacts-$CI_PIPELINE_ID-$CI_JOB_NAME_SLUG paths: - junit.xml - - phpstan-baseline.neon + - $_PHPSTAN_BASELINE_FILENAME - phpstan-quality-report.json phpstan: diff --git a/includes/include.drupalci.variables.yml b/includes/include.drupalci.variables.yml index 183e04cc..01992952 100644 --- a/includes/include.drupalci.variables.yml +++ b/includes/include.drupalci.variables.yml @@ -140,6 +140,10 @@ variables: value: '' description: 'Specify the PHPStan level to use (0-9). If left blank it will use the `level` value in your phpstan.neon configuration file, or default to 0 if there is no `level` parameter. See https://phpstan.org/user-guide/rule-levels for more information.' + _PHPSTAN_BASELINE_FILENAME: + value: 'phpstan-baseline.neon' + description: 'The PHPStan baseline file of warnings to ignore. The default is `phpstan-baseline.neon` but a project can have a custom filename if required.' + _SHOW_ENVIRONMENT_VARIABLES: value: '0' description: 'Set to 1 to show all the environment variables in the Composer and PhpUnit jobs. Known variables with Personal Identifiable Information will still be hidden. The default is 0 for no output at all.' -- GitLab