diff --git a/src/Builder/Concerns/PrunesVendorDirectory.php b/src/Builder/Concerns/PrunesVendorDirectory.php index 7551aaf1..4d60b380 100644 --- a/src/Builder/Concerns/PrunesVendorDirectory.php +++ b/src/Builder/Concerns/PrunesVendorDirectory.php @@ -24,10 +24,14 @@ public function pruneVendorDirectory() $this->buildPath('app/vendor/nativephp/php-bin'), ]); - // Remove custom php binary package directory - $binaryPackageDirectory = $this->binaryPackageDirectory(); - if (! empty($binaryPackageDirectory) && $filesystem->exists($this->buildPath("app/{$binaryPackageDirectory}"))) { - $filesystem->remove($this->buildPath("app/{$binaryPackageDirectory}")); - } + // Remove the bundled PHP binaries for a custom binary path. + // They get duplicated into the app's build resources, so + // the copies left in the source tree are dead weight. + // + // We remove only the archives we manage, never the + // parent directory, so the user's files are kept, + // and a root path never wipes the app (#115). + $binaryDirectory = $this->buildPath('app/'.$this->binaryPackageDirectory().'bin'); + $filesystem->remove(glob("{$binaryDirectory}/*/*/php-*.zip")); } } diff --git a/src/Client/Client.php b/src/Client/Client.php index d6dd7749..cbafee66 100644 --- a/src/Client/Client.php +++ b/src/Client/Client.php @@ -16,7 +16,7 @@ public function __construct() ->baseUrl(config('nativephp-internal.api_url', '')) ->timeout(60 * 60) ->withHeaders([ - 'X-NativePHP-Secret' => config('nativephp-internal.secret'), + 'X-NativePHP-Secret' => (string) config('nativephp-internal.secret'), ]) ->asJson(); } diff --git a/tests/Build/PruneVendorDirectoryTest.php b/tests/Build/PruneVendorDirectoryTest.php new file mode 100644 index 00000000..c85d56de --- /dev/null +++ b/tests/Build/PruneVendorDirectoryTest.php @@ -0,0 +1,101 @@ +remove($buildPath); +}); + +afterEach(function () use ($buildPath) { + putenv('NATIVEPHP_PHP_BINARY_PATH'); + + $filesystem = new Filesystem; + $filesystem->remove($buildPath); +}); + +/* +|-------------------------------------------------------------------------- +| Mock Build command with anonymous class +|-------------------------------------------------------------------------- +*/ +$command = new class($buildPath) +{ + use LocatesPhpBinary; + use PrunesVendorDirectory; + + public function __construct( + public $buildPath + ) {} + + public function sourcePath(string $path = ''): string + { + return app()->joinPaths($this->buildPath, $path); + } + + public function buildPath(string $path = ''): string + { + return app()->joinPaths($this->buildPath, $path); + } +}; + +/* +|-------------------------------------------------------------------------- +| Tests +|-------------------------------------------------------------------------- +*/ +it('prunes the bundled php binary archives from a custom binary directory', function () use ($buildPath, $command) { + putenv('NATIVEPHP_PHP_BINARY_PATH=php-bin/'); + + createFiles([ + "$buildPath/app/index.php", + "$buildPath/app/php-bin/bin/win/x64/php-8.4.zip", + "$buildPath/app/php-bin/bin/mac/arm64/php-8.4.zip", + ]); + + $command->pruneVendorDirectory(); + + // The redundant archives are stripped... + expect("$buildPath/app/php-bin/bin/win/x64/php-8.4.zip")->not->toBeFile(); + expect("$buildPath/app/php-bin/bin/mac/arm64/php-8.4.zip")->not->toBeFile(); + + // ...while the rest of the app is left intact. + expect("$buildPath/app/index.php")->toBeFile(); +}); + +it('does not delete the app when the binary path is the project root', function () use ($buildPath, $command) { + // Regression test for #115: a binary path that normalises to the app root + // (e.g. binaries kept directly in the project's bin/ directory) must not + // take the whole app down with the prune. + putenv('NATIVEPHP_PHP_BINARY_PATH=./'); + + createFiles([ + "$buildPath/app/index.php", + "$buildPath/app/bin/win/x64/php-8.4.zip", + "$buildPath/app/bin/mac/arm64/php-8.4.zip", + // Unrelated tooling a user happens to keep in bin/ must survive. + "$buildPath/app/bin/deploy.sh", + ]); + + $command->pruneVendorDirectory(); + + // The app and any non-NativePHP files in bin/ are preserved... + expect("$buildPath/app/index.php")->toBeFile(); + expect("$buildPath/app/bin/deploy.sh")->toBeFile(); + + // ...but the bundled php archives are still pruned. + expect("$buildPath/app/bin/win/x64/php-8.4.zip")->not->toBeFile(); + expect("$buildPath/app/bin/mac/arm64/php-8.4.zip")->not->toBeFile(); +});