Skip to content

[v9.0.1 -- PHP Flavor] Cannot override PHP_*_CLI_EXECUTABLE correctly #6223

@llaville

Description

@llaville

Describe the bug
Cannot override CLI executable with a local copy of any of PHP Linters

Don't be afraid of this long report, I'll provide a PR to fix the problem soon. TL;DR only if you want to know more about such kind of issue.

To Reproduce
Steps to reproduce the behavior:

  1. Retrieve a repository that may install PHP Linters as dev tools locally; For example https://github.com/llaville/php-compatinfo-db (master branch)
  2. Run composer install to install standard project dependencies
  3. Run composer bin all install to install all other dev tools locally on this project
  4. Or just install PHPStan for demo purpose (to issue concept), That's mean run : composer bin phpstan install
  5. Run the PHP Flavor with official Docker image : docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:rw -v $(pwd):/tmp/lint:rw -e LOG_LEVEL=debug -e PARALLEL=false ghcr.io/oxsecurity/megalinter-php:v9.0.1

NB: I've enabled debug mode to see additional message that will help to show problems found, and disabled parallel mode to have log grouped by linters.

Expected behavior

All linters should run without found any errors, especially PHPStan if we run local version installed (with command composer bin phpstan install)

Something like this :

Image

Additional context
PHPStan installed with MegaLinter (9.0.1) is detailed at https://github.com/oxsecurity/megalinter/blob/v9.0.1/megalinter/descriptors/php.megalinter-descriptor.yml#L130-L140

On my project to have none errors found by MegaLinter, I should have an extra PHPStan extension, see https://github.com/llaville/php-compatinfo-db/blob/master/vendor-bin/phpstan/composer.json#L5

So, on my first approach, I though I could override CLI executable in MegaLinter config file like this
PHP_PHPSTAN_CLI_EXECUTABLE: "vendor/bin/phpstan" , see llaville/php-compatinfo-db@4b0a09d

But PATH defined does not lookup into /tmp/lint volume (mounted on docker run), and more than that explains are given by doc itself at https://docs.python.org/3/library/shutil.html#shutil.which

If cmd contains a directory component, which() only checks the specified path directly and does not search the directories listed in path or in the system’s PATH environment variable.

So I got this output

❌ Linted [PHP] files with [phpstan]: Found 1 error(s) and 0 warning(s) - (0.0s)
- Using [phpstan vERROR] https://megalinter.io/9.0.1/descriptors/php_phpstan
- MegaLinter key: [PHP_PHPSTAN]
- Rules config: [/.github/linters/phpstan.neon.dist]
- Command: [vendor/bin/phpstan analyse --no-progress --no-ansi --memory-limit 1G -c /tmp/lint/.github/linters/phpstan.neon.dist]
--Error detail:
Fatal error while calling phpstan: [Errno 2] No such file or directory: 'vendor/bin/phpstan'

The solution is given by this little patch

diff --git a/megalinter/Linter.py b/megalinter/Linter.py
index 0cfcf481d8..162bec5728 100644
--- a/megalinter/Linter.py
+++ b/megalinter/Linter.py
@@ -974,7 +974,7 @@ class Linter:
             try:
                 reporter.produce_report()
             except Exception as e:
-                logging.error("Unable to process reporter " + reporter.name + str(e))
+                logging.error("Unable to process reporter " + reporter.name + " " + str(e))

         return self

@@ -1657,6 +1657,8 @@ class Linter:
         cli_absolute = shutil.which(cmd[0])
         if cli_absolute is not None:
             cmd[0] = cli_absolute
+        cmd_resolved = " ".join(str(element) for element in cmd)
+        logging.debug("Linter version command resolved: " + cmd_resolved)
         cmd += self.cli_version_extra_args
         if self.cli_version_arg_name != "":
             cmd += [self.cli_version_arg_name]

First logging error to avoid collapsed message like Unable to process reporter CONSOLEcan only concatenate str (not "list") to str (space missing between reporter name CONSOLE and exception message

Second logging to debug how linter is resolved by shutil.which

BUT to solve my situation context, we should only fix the PATH definition to allow local linter first

diff --git a/megalinter/descriptors/php.megalinter-descriptor.yml b/megalinter/descriptors/php.megalinter-descriptor.yml
index 2fcf4fb5bb..b327a684ac 100644
--- a/megalinter/descriptors/php.megalinter-descriptor.yml
+++ b/megalinter/descriptors/php.megalinter-descriptor.yml
@@ -25,7 +25,7 @@ install:
   dockerfile:
     - RUN update-alternatives --install /usr/bin/php php /usr/bin/php84 110
     - COPY --from=composer/composer:2-bin /composer /usr/bin/composer
-    - ENV PATH="/root/.composer/vendor/bin:${PATH}"
+    - ENV PATH="/tmp/lint/vendor/bin:/root/.composer/vendor/bin:${PATH}"
 linters:
   # PHPCS
   - linter_name: phpcs

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions