Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Phar class not found #988

Closed
SpiGAndromeda opened this issue Apr 8, 2023 · 24 comments
Closed

Phar class not found #988

SpiGAndromeda opened this issue Apr 8, 2023 · 24 comments

Comments

@SpiGAndromeda
Copy link

Bug report

Question Answer
Box version 4.3.8@5534406
PHP version 8.2.4
Platform with version popos 22.04

The box compile command results in a Class "Phar" not found in/.../autoload_runtime.php:11 error. PHAR is installed. Readonly is Off. The '/usr/local/bin/composer' 'dump-autoload' '--classmap-authoritative' '--no-dev' '--ansi' command doesn't fail if executed manually in the project directory.

box.json.dist
{
 "files-bin": [
   ".env.local.php",
   "autoload_runtime.template",
   "vendor/humbug/php-scoper/vendor-hotfix/.gitkeep"
 ],
 "directories": [
   "config",
   "public",
   "var"
 ],
 "force-autodiscovery": true,
 "check-requirements": false,
 "exclude-composer-files": false,
 "main": "bin/console"
}
Output
$ php vendor/bin/box compile
> 
   ____
  / __ )____  _  __
 / __  / __ \| |/_/
/ /_/ / /_/ />  <
/_____/\____/_/|_|


Box version 4.3.8@5534406

// Loading the configuration file                                                                                      
// "/home/project-dir/box.json".                               

🔨  Building the PHAR "/home/project-dir/bin/console.phar"

? Checking Composer compatibility
   > Supported version detected
? No compactor to register
? Adding main file: /home/project-dir/bin/console
? Skip requirements checker
? Adding binary files
   > 3 file(s)
? Auto-discover files? Yes
? Exclude dev files? Yes
? Adding files
   > 5050 file(s)
? Generating new stub
 - Using shebang line: #!/usr/bin/env php
 - Using banner:
   > Generated by Humbug Box 4.3.8@5534406.
   > 
   > @link https://github.com/humbug/box
? Dumping the Composer autoloader

In ComposerOrchestrator.php line 207:
                                 
 Could not dump the autoloader.  
                                 

In ComposerOrchestrator.php line 210:
                                                                                                                   
 The command "'/usr/local/bin/composer' 'dump-autoload' '--classmap-authoritative' '--no-dev' '--ansi'" failed.    
                                                                                                                   
 Exit Code: 255(Unknown error)                                                                                     
                                                                                                                   
 Working directory: /tmp/box/Box37232                                                                              
                                                                                                                   
 Output:                                                                                                           
 ================                                                                                                  
 Generating optimized autoload files (authoritative)                                                       
                                                                                                                   
                                                                                                                   
 Error Output:                                                                                                     
 ================                                                                                                  
 Executing script cache:clear [KO]                                                                   
  [KO]                                                                                               
 Script cache:clear returned with error code 255                                                     
 !!  PHP Fatal error:  Uncaught Error: Class "Phar" not found in /tmp/box/Box37232/vendor/autoload_runtime.php:11  
 !!  Stack trace:                                                                                                  
 !!  #0 /tmp/box/Box37232/bin/console(10): require_once()                                                          
 !!  #1 {main}                                                                                                     
 !!    thrown in /tmp/box/Box37232/vendor/autoload_runtime.php on line 11                                          
 !!                                                                                                                
 Script @auto-scripts was called via post-autoload-dump

Because it's a Symfony project:

autoload_runtime.template
<?php

// autoload_runtime.php @generated by Symfony Runtime

$scriptFileName = $_SERVER['APP_SCRIPT_FILENAME'] ?? $_SERVER['SCRIPT_FILENAME'] ?? null;

if (true === (require_once __DIR__.'/autoload.php') || null === $scriptFileName || '' === $scriptFileName) {
   return;
}

$pharPath = Phar::running();

if (strlen($pharPath) > 0 && !str_starts_with($scriptFileName, 'phar://')) {
   $scriptFileName = $pharPath.DIRECTORY_SEPARATOR.$scriptFileName;
}

$app = require $scriptFileName;

if (!is_object($app)) {
   throw new TypeError(sprintf('Invalid return value: callable object expected, "%s" returned from "%s".', get_debug_type($app), $_SERVER['SCRIPT_FILENAME']));
}

$runtime = $_SERVER['APP_RUNTIME'] ?? $_ENV['APP_RUNTIME'] ?? %runtime_class%;
$runtime = new $runtime(($_SERVER['APP_RUNTIME_OPTIONS'] ?? $_ENV['APP_RUNTIME_OPTIONS'] ?? []) + %runtime_options%);

[$app, $args] = $runtime
   ->getResolver($app)
   ->resolve();

$app = $app(...$args);

exit(
   $runtime
       ->getRunner($app)
       ->run()
);
@theofidry
Copy link
Member

This looks really strange: I really don't think it's possible for the PHAR class to not exist yet especially since Box itself uses it. Is the script used really the one you linked? Isn't there a namespace declared or something?

@SpiGAndromeda
Copy link
Author

I can't explain it either. I tried executing box from global installation and from project installation. Same result.

I just added a use Phar; statement to the autoload_runtime template. The result is the same. Error line changed naturally. Which also means this template is used for sure.

I also checked if the Phar extension is enabled. It is.

@theofidry
Copy link
Member

Would you have a reproducer by any chance?

Out of curiosity could you also try to run the Box Symfony E2E test?

@theofidry
Copy link
Member

It should be make e2e_symfony_runtime or something

@SpiGAndromeda
Copy link
Author

Would you have a reproducer by any chance?

Out of curiosity could you also try to run the Box Symfony E2E test?

I created a minimal repository with which I was able to reproduce the issue: https://github.com/it-bens/box-test

@SpiGAndromeda
Copy link
Author

The E2E test leads to the same result:

$ make e2e_symfony_runtime
> php fixtures/build/dir018/new-bin/console --version --no-ansi \
        1>dist/dir018/expected-stdout \
        2>dist/dir018/expected-stderr
fixtures/build/dir018/new-bin/console cache:pool:clear cache.global_clearer --env=prod --ansi

 // Calling cache clearer: cache.global_clearer                                                                         

                                                                                                                        
 [OK] Cache was successfully cleared.                                                                                   
                                                                                                                        

fixtures/build/dir018/new-bin/console cache:clear --env=prod --ansi

 // Clearing the cache for the prod environment with debug false                                                        

                                                                                                                        
 [OK] Cache for the "prod" environment (debug=false) was successfully cleared.                                          
                                                                                                                        

rm -rf fixtures/build/dir018/var/cache/prod/*
bin/box.phar compile --working-dir=fixtures/build/dir018 --no-parallel --ansi

    ____
   / __ )____  _  __
  / __  / __ \| |/_/
 / /_/ / /_/ />  <
/_____/\____/_/|_|


Box version dev-main@25cb301 2023-04-10 13:25:29 UTC

 // Loading the configuration file "/home/box/fixtures/build/dir018/box.json.dist".              

🔨  Building the PHAR "/home/box/fixtures/build/dir018/new-bin/console.phar"

? Checking Composer compatibility
    > Supported version detected
? No compactor to register
? Adding main file: /home/box/fixtures/build/dir018/new-bin/console
? Skip requirements checker
? Adding binary files
    > 3 file(s)
? Auto-discover files? Yes
? Exclude dev files? Yes
? Adding files
    > 1275 file(s)
? Generating new stub
  - Using shebang line: #!/usr/bin/env php
  - Using banner:
    > Generated by Humbug Box dev-main@25cb301.
    > 
    > @link https://github.com/humbug/box
? Dumping the Composer autoloader

In ComposerOrchestrator.php line 102:
                                  
  Could not dump the autoloader.  
                                  

In ComposerOrchestrator.php line 102:
                                                                                                                    
  The command "'/usr/local/bin/composer' 'dump-autoload' '--classmap-authoritative' '--no-dev' '--ansi'" failed.    
                                                                                                                    
  Exit Code: 255(Unknown error)                                                                                     
                                                                                                                    
  Working directory: /tmp/box/Box33769                                                                              
                                                                                                                    
  Output:                                                                                                           
  ================                                                                                                  
  Generating optimized autoload files (authoritative)                                                       
                                                                                                                    
                                                                                                                    
  Error Output:                                                                                                     
  ================                                                                                                  
  Executing script cache:clear [KO]                                                                   
   [KO]                                                                                               
  Script cache:clear returned with error code 255                                                     
  !!  PHP Fatal error:  Uncaught Error: Class "Phar" not found in /tmp/box/Box33769/vendor/autoload_runtime.php:11  
  !!  Stack trace:                                                                                                  
  !!  #0 /tmp/box/Box33769/new-bin/console(12): require_once()                                                      
  !!  #1 {main}                                                                                                     
  !!    thrown in /tmp/box/Box33769/vendor/autoload_runtime.php on line 11                                          
  !!                                                                                                                
  Script @auto-scripts was called via post-autoload-dump                                              
                                                                                                                    

compile [--debug] [--no-parallel] [--no-restart] [--dev] [--no-config] [--with-docker] [--composer-bin COMPOSER-BIN] [--allow-composer-check-failure] [-c|--config CONFIG] [-d|--working-dir WORKING-DIR]

make: *** [Makefile.e2e:318: e2e_symfony_runtime] Error 1

@maartendekeizer
Copy link

maartendekeizer commented Oct 10, 2023

Same issue here. Try to run box compile with GitHub actions.
Tested in 4.2.0 and 4.3.8.

Added some debug points in autoload_runtime.template

Output
  Script cache:clear returned with error code 255

PHP version 
8.1.2-1ubuntu2.14

Loaded extension 
Array 
( 
    [0] => Core 
    [1] => date 
    [2] => libxml 
    [3] => openssl 
    [4] => pcre 
    [5] => zlib 
    [6] => filter 
    [7] => hash 
    [8] => json 
    [9] => pcntl 
    [10] => Reflection 
    [11] => SPL 
    [12] => session 
    [13] => standard 
    [14] => sodium 
)

Phar class not found, declared classes 
Array 
( 
    [0] => stdClass 
    [1] => InternalIterator 
    [2] => Exception 
    [3] => ErrorException 
    [4] => Error 
    [5] => CompileError 
    [6] => ParseError 
    [7] => TypeError 
    [8] => ArgumentCountError 
    [9] => ValueError 
    [10] => ArithmeticError 
    [11] => DivisionByZeroError 
    [12] => UnhandledMatchError 
    [13] => Closure 
    [14] => Generator 
    [15] => ClosedGeneratorException 
    [16] => WeakReference 
    [17] => WeakMap 
    [18] => Attribute 
    [19] => ReturnTypeWillChange 
    [20] => Fiber 
    [21] => FiberError 
    [22] => DateTime 
    [23] => DateTimeImmutable 
    [24] => DateTimeZone 
    [25] => DateInterval 
    [26] => DatePeriod 
    [27] => LibXMLError 
    [28] => OpenSSLCertificate 
    [29] => OpenSSLCertificateSigningRequest 
    [30] => OpenSSLAsymmetricKey 
    [31] => InflateContext 
    [32] => DeflateContext 
    [33] => HashContext 
    [34] => JsonException 
    [35] => ReflectionException 
    [36] => Reflection 
    [37] => ReflectionFunctionAbstract 
    [38] => ReflectionFunction 
    [39] => ReflectionGenerator 
    [40] => ReflectionParameter 
    [41] => ReflectionType 
    [42] => ReflectionNamedType 
    [43] => ReflectionUnionType 
    [44] => ReflectionIntersectionType 
    [45] => ReflectionMethod 
    [46] => ReflectionClass 
    [47] => ReflectionObject 
    [48] => ReflectionProperty 
    [49] => ReflectionClassConstant 
    [50] => ReflectionExtension 
    [51] => ReflectionZendExtension 
    [52] => ReflectionReference 
    [53] => ReflectionAttribute 
    [54] => ReflectionEnum 
    [55] => ReflectionEnumUnitCase 
    [56] => ReflectionEnumBackedCase 
    [57] => ReflectionFiber 
    [58] => LogicException 
    [59] => BadFunctionCallException 
    [60] => BadMethodCallException 
    [61] => DomainException 
    [62] => InvalidArgumentException 
    [63] => LengthException 
    [64] => OutOfRangeException 
    [65] => RuntimeException 
    [66] => OutOfBoundsException 
    [67] => OverflowException 
    [68] => RangeException 
    [69] => UnderflowException 
    [70] => UnexpectedValueException 
    [71] => RecursiveIteratorIterator 
    [72] => IteratorIterator 
    [73] => FilterIterator 
    [74] => RecursiveFilterIterator 
    [75] => CallbackFilterIterator 
    [76] => RecursiveCallbackFilterIterator 
    [77] => ParentIterator 
    [78] => LimitIterator 
    [79] => CachingIterator 
    [80] => RecursiveCachingIterator 
    [81] => NoRewindIterator 
    [82] => AppendIterator 
    [83] => InfiniteIterator 
    [84] => RegexIterator 
    [85] => RecursiveRegexIterator 
    [86] => EmptyIterator 
    [87] => RecursiveTreeIterator 
    [88] => ArrayObject 
    [89] => ArrayIterator 
    [90] => RecursiveArrayIterator 
    [91] => SplFileInfo 
    [92] => DirectoryIterator 
    [93] => FilesystemIterator 
    [94] => RecursiveDirectoryIterator 
    [95] => GlobIterator 
    [96] => SplFileObject 
    [97] => SplTempFileObject 
    [98] => SplDoublyLinkedList 
    [99] => SplQueue 
    [100] => SplStack 
    [101] => SplHeap 
    [102] => SplMinHeap 
    [103] => SplMaxHeap 
    [104] => SplPriorityQueue 
    [105] => SplFixedArray 
    [106] => SplObjectStorage 
    [107] => MultipleIterator 
    [108] => SessionHandler 
    [109] => __PHP_Incomplete_Class 
    [110] => AssertionError 
    [111] => php_user_filter 
    [112] => Directory 
    [113] => SodiumException 
    [114] => ComposerAutoloaderInit8e615dc7e0504e7a0fac65a0fd86b04f 
    [115] => Composer\Autoload\ClassLoader 
    [116] => Composer\Autoload\ComposerStaticInit8e615dc7e0504e7a0fac65 
  a0fd86b04f 
) 

It looks like that some kind of minimal PHP version is used todo the dump.

When running /usr/bin/composer dump-autoload --classmap-authoritative --no-dev outside Box everything works fine.

@theofidry
Copy link
Member

It looks like that some kind of minimal PHP version is used todo the dump.

Is there such a thing available in your CI? Running the command with -vvv should be able to show it. But IIRC box doesn't try to pick another PHP version, only the Composer binary to dump the autoloader.

@maartendekeizer
Copy link

maartendekeizer commented Oct 11, 2023

Not that I'm aware of. When running php -i / php -m as seperated job Phar is listed.
Output when running with -vvv https://github.com/Markei/kopio/actions/runs/6478641608/job/17590749216

In the output it is visible that two kind of ini files are used:

Box Requirements Checker
========================

> Using PHP [8](https://github.com/Markei/kopio/actions/runs/6478641608/job/17590749216#step:9:9).1.2-1ubuntu2.14
> PHP is using the following php.ini file:
  /etc/php/8.1/cli/php.ini
.....
Box Requirements Checker
========================

> Using PHP 8.1.2-1ubuntu2.[14](https://github.com/Markei/kopio/actions/runs/6478641608/job/17590749216#step:9:15)
> PHP is using the following php.ini file:
  /tmp/lsJiBG

@theofidry
Copy link
Member

@maartendekeizer isn't your issue a timeout rather than Phar not found though?

@maartendekeizer
Copy link

The timeout did not happen without -vvv, than the Phar class issue will come up. See https://github.com/Markei/kopio/actions/runs/6474508303/job/17579581668
How can I change the timeout in the case of -vvv

@theofidry
Copy link
Member

@maartendekeizer I am a bit confused by your CI though: https://github.com/Markei/kopio/blob/main/.github/workflows/build-phar.yml

How is PHP installed there? It appears you pick whatever ubuntu latest has which IMO is a bad idea. I am not sure if it's the root of the problem, as I am not aware of a PHP binary that comes without the PHAR extension, but looking at your workflow that's the only thing I can pick up.

@theofidry
Copy link
Member

I actually missed #988 (comment). Might be another lead I'll have to check ASAP. I'm focusing on finishing to fix the diff command for the next release and can check this afterwards (or before the release)

@maartendekeizer
Copy link

Upgraded to 4.4.0, issue still exists.

Add a dump of php_ini_scanned_files(). See https://github.com/Markei/kopio/actions/runs/6525975372/job/17719227836

In the step Cache warm up multiple ini files are loaded, each ini file will activate an extension (for instance Phar).
In the step Run box no other ini files are loaded, only the php.ini.

@maartendekeizer
Copy link

Setting BOX_ALLOW_XDEBUG=1 will fix the problem which bring us maybe to the composer xdebug handler https://github.com/composer/xdebug-handler/blob/main/src/XdebugHandler.php

@theofidry
Copy link
Member

Indeed if removing the restart fixes it it likely a bug there. @maartendekeizer do you have any local (potentially via docker) reproducer? I would like to avoid pulling in johnstevenson without one if I can help it

@maartendekeizer
Copy link

maartendekeizer commented Oct 16, 2023

Sorry local under Windows and no xdebug. Unsure how to reproduce this is under Docker, but the linked repository can be used as an example.

I see that Box is using XdebugHandler too.
So we have the situation that XdebugHandler set the PHP_INI_SCAN_DIR (saved the original value to BOX_ORIGINAL_INIS) when Box restarts.
When Box is starting Composer/PHP the PHP_INI_SCAN_DIR environment variabel is empty, the normal php.ini is used, and the default scanned directories will not scanned (because env is empty).

Thinking about a solution it should be something like:
When Box is starting Composer, PHP_INI_SCAN_DIR should be filled with the BOX_ORIGINAL_INIS value.

@theofidry
Copy link
Member

Ha I see, that would make sense, will give it a go ASAP

@theofidry
Copy link
Member

@maartendekeizer I am a bit perplexed as I can't reproduce your issue here: #1089

@theofidry
Copy link
Member

Hm actually didn't check but could also be from the Flex plugin too...

@theofidry
Copy link
Member

I managed to reproduce and isolate the issue in https://github.com/box-project/box/actions/runs/6592295374/job/17912645537#logs.

My findings:

  • It is related to the symfony/flex plugin
  • It happens as soon as the process in which the plugin is used is restarted
  • This happens only for the symfony-cmd scripts, the script and php-script are both working fine
  • It is NOT related to the Symfony command used (which makes sense, the problem is about the ini settings of the PHP process used).

Looking at https://github.com/symfony/flex/blob/3e8d6c423092ca89dd8fb998ddb9d7a91139e52f/src/ScriptExecutor.php#L94 I have no clue why this would result in a PHP process with non-sensical ini values.

For the record: this is not a problem of Box restarting the process. I mean it is linked, but Composer is executed within it and the PHP scripts started by flex also work fine.

So I am a bit at a loss

@maartendekeizer
Copy link

I figured out https://github.com/symfony/flex/blob/3e8d6c423092ca89dd8fb998ddb9d7a91139e52f/src/ScriptExecutor.php#L120C9-L120C9 is a bad way to find out if the xdebughandler has restarted composer.

The code will check for a specific environment variabel, if it set it assumed it will need to use another ini file instead of the used php.ini (in the case this tmp ini is created in the no-xdebug-restart and is passed via PHPRC env to composer).

Cleaning the env will not trigger the bad flex code and will continue to use the right tmpIni.

Successfull run: https://github.com/maartendekeizer/box/actions/runs/6593003554/job/17914732375
Diff here: https://github.com/theofidry/box/pull/3/files

@theofidry
Copy link
Member

That does the trick! Prob worth fixing on Flex side :o

theofidry added a commit to theofidry/flex that referenced this issue Oct 20, 2023
> [!WARNING]
> Note: this PR is more of draft. I am not confident I understand fully
the issue neither that this is the right fix (and I could not test it).
Do NOT assume this code just works.

After a lot of digging in box-project/box#988,
@maartendekeizer could identify the root of the issue.

My understanding is that Flex tries to detect if the current PHP process
was restarted by Composer and forwards its restarted settings to the
sub-processes it is going to launch. There is currently two things done:

- symfony#91 which if took code from SensioDistributionBundle.
- symfony#899 which kind of followed the suite.

    I suspect the mentioned code predates `composer/xdebug-handler`. Now
with this package, there is two things to take into account:

- The `composer/xdebug-handler` API is likely much safer, more robust
  and a lot less hacky to use.
- There is other applications that can restart a PHP process. As an
  example Box restarts the PHP process to be able to correct the
`phar.readonly` setting that cannot be changed at runtime. It matters as
the restarted process by be executing a Composer command.

As mentioned in the warning, I could not test this, not even run the
tests locally, so I would be careful about this PR. I just wanted to
give a base about a potential fix with context about the original issue
encountered.

On my side to not have to wait on Flex and avoid the users to have to
update it to have the fix, Box launches its Composer commands with
`COMPOSER_ORIGINAL_INIS=''` to avoid Flex to trigger this bad piece of
code.
theofidry added a commit to theofidry/box that referenced this issue Oct 20, 2023
- Use the persistent setting: any sub-process should use the same
  settings.
- Reset `COMPOSER_ORIGINAL_INIS` to avoid the buggy Flex code (see symfony/flex#995).

Closes box-project#1089, box-project#988.
theofidry added a commit that referenced this issue Oct 21, 2023
- Use the persistent setting: any sub-process should use the same
  settings.
- Reset `COMPOSER_ORIGINAL_INIS` to avoid the buggy Flex code (see symfony/flex#995).

Closes #1089, #988.
@theofidry
Copy link
Member

Closed by #1091, thank you a lot @maartendekeizer for figuring it out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants