1
0
mirror of https://github.com/php/pie.git synced 2026-03-23 23:12:17 +01:00

435: added flags to control system dependency scanning behaviour

This commit is contained in:
James Titcumb
2026-03-05 11:55:54 +00:00
parent 0c48a668a5
commit 4d3ec06e97
6 changed files with 126 additions and 23 deletions

View File

@@ -63,6 +63,8 @@ final class CommandHelper
private const OPTION_NO_CACHE = 'no-cache';
private const OPTION_AUTO_INSTALL_BUILD_TOOLS = 'auto-install-build-tools';
private const OPTION_SUPPRESS_BUILD_TOOLS_CHECK = 'no-build-tools-check';
private const OPTION_AUTO_INSTALL_SYSTEM_DEPENDENCIES = 'auto-install-system-dependencies';
private const OPTION_SUPPRESS_SYSTEM_DEPENDENCIES_CHECK = 'no-system-dependencies-check';
private function __construct()
{
@@ -154,6 +156,19 @@ final class CommandHelper
'Do not perform the check to see if build tools are present on the system.',
);
$command->addOption(
self::OPTION_AUTO_INSTALL_SYSTEM_DEPENDENCIES,
null,
InputOption::VALUE_NONE,
'If system dependencies missing, automatically install them, instead of prompting.',
);
$command->addOption(
self::OPTION_SUPPRESS_SYSTEM_DEPENDENCIES_CHECK,
null,
InputOption::VALUE_NONE,
'Do not perform the check to see if system dependencies are present on the system.',
);
/**
* Allows additional options for the `./configure` command to be passed here.
* Note, this means you probably need to call {@see self::validateInput()} to validate the input manually...
@@ -267,6 +282,22 @@ final class CommandHelper
|| ! $input->getOption(self::OPTION_SUPPRESS_BUILD_TOOLS_CHECK);
}
public static function autoInstallSystemDependencies(InputInterface $input): bool
{
return $input->hasOption(self::OPTION_AUTO_INSTALL_SYSTEM_DEPENDENCIES)
&& $input->getOption(self::OPTION_AUTO_INSTALL_SYSTEM_DEPENDENCIES);
}
public static function shouldCheckSystemDependencies(InputInterface $input): bool
{
if (Platform::isWindows()) {
return false;
}
return ! $input->hasOption(self::OPTION_SUPPRESS_SYSTEM_DEPENDENCIES_CHECK)
|| ! $input->getOption(self::OPTION_SUPPRESS_SYSTEM_DEPENDENCIES_CHECK);
}
public static function requestedNameAndVersionPair(InputInterface $input): RequestedPackageAndVersion
{
$requestedPackageString = $input->getArgument(self::ARG_REQUESTED_PACKAGE_AND_VERSION);

View File

@@ -105,14 +105,20 @@ final class InstallCommand extends Command
),
);
// @todo flag to disable this check
try {
($this->prescanSystemDependencies)($composer, $targetPlatform, $requestedNameAndVersion);
} catch (Throwable $anything) {
$this->io->writeError(
'<comment>Skipping system dependency pre-scan due to exception:</comment> ' . $anything->getMessage(),
verbosity: IOInterface::VERBOSE,
);
if (CommandHelper::shouldCheckSystemDependencies($input)) {
try {
($this->prescanSystemDependencies)(
$composer,
$targetPlatform,
$requestedNameAndVersion,
CommandHelper::autoInstallSystemDependencies($input),
);
} catch (Throwable $anything) {
$this->io->writeError(
'<comment>Skipping system dependency pre-scan due to exception:</comment> ' . $anything->getMessage(),
verbosity: IOInterface::VERBOSE,
);
}
}
try {

View File

@@ -36,8 +36,12 @@ class PrescanSystemDependencies
) {
}
public function __invoke(Composer $composer, TargetPlatform $targetPlatform, RequestedPackageAndVersion $requestedNameAndVersion): void
{
public function __invoke(
Composer $composer,
TargetPlatform $targetPlatform,
RequestedPackageAndVersion $requestedNameAndVersion,
bool $autoInstallIfMissing,
): void {
if ($this->packageManager === null) {
$this->io->writeError('<comment>Skipping pre-scan of system dependencies, as a supported package manager could not be detected.</comment>', verbosity: IOInterface::VERBOSE);
@@ -83,10 +87,29 @@ class PrescanSystemDependencies
}
$proposedInstallCommand = implode(' ', $this->packageManager->installCommand($packageManagerPackages));
$this->io->write(sprintf('<info>Installing missing system dependencies:</info> %s', $proposedInstallCommand));
if (! $this->io->isInteractive() && ! $autoInstallIfMissing) {
$this->io->writeError('<warning>You are not running in interactive mode, and you did not provide the --auto-install-system-dependencies flag.');
$this->io->writeError('You may need to run: ' . $proposedInstallCommand . '</warning>');
$this->io->writeError('');
return;
}
$this->io->write(sprintf('<info>Need to install missing system dependencies:</info> %s', $proposedInstallCommand));
if ($this->io->isInteractive() && ! $autoInstallIfMissing) {
if (! $this->io->askConfirmation('<question>Would you like to install them now?</question>', false)) {
$this->io->write('<comment>Ok, but things might not work. Just so you know.</comment>');
return;
}
}
try {
$this->packageManager->install($packageManagerPackages);
$this->io->write('<info>Missing system dependencies have been installed.</info>');
} catch (Throwable $anything) {
$this->io->writeError(sprintf('<info>Failed to install missing system dependencies:</info> %s', $anything->getMessage()));
}

View File

@@ -47,14 +47,14 @@ RUN mkdir -p /opt/php \
&& make install
ENV PATH="$PATH:/opt/php/bin"
COPY --from=build_pie_phar /app/pie.phar /usr/local/bin/pie
RUN pie install -v php/sodium
RUN pie install -v --auto-install-system-dependencies php/sodium
FROM alpine AS test_pie_installs_system_deps_on_alpine
RUN apk add php php-phar php-mbstring php-iconv php-openssl bzip2-dev libbz2 build-base autoconf bison re2c libtool php84-dev
COPY --from=build_pie_phar /app/pie.phar /usr/local/bin/pie
RUN pie install -v php/sodium
RUN pie install -v --auto-install-system-dependencies php/sodium
FROM fedora AS test_pie_installs_system_deps_on_fedora
RUN dnf install -y php php-pecl-zip unzip gcc make autoconf bison re2c libtool php-devel
COPY --from=build_pie_phar /app/pie.phar /usr/local/bin/pie
RUN pie install -v php/sodium
RUN pie install -v --auto-install-system-dependencies php/sodium

View File

@@ -53,7 +53,7 @@ final class PrescanSystemDependenciesTest extends TestCase
$this->io,
);
($scanner)($this->composer, $this->targetPlatform, new RequestedPackageAndVersion('foo/foo', null));
($scanner)($this->composer, $this->targetPlatform, new RequestedPackageAndVersion('foo/foo', null), true);
self::assertStringContainsString(
'Skipping pre-scan of system dependencies, as a supported package manager could not be detected.',
@@ -89,7 +89,7 @@ final class PrescanSystemDependenciesTest extends TestCase
new DependencyStatus('lib-bar', $versionParser->parseConstraints('^2.0'), new Constraint('=', '2.5.1.0')),
]);
($scanner)($this->composer, $this->targetPlatform, $request);
($scanner)($this->composer, $this->targetPlatform, $request, true);
self::assertStringContainsString(
'All system dependencies are already installed.',
@@ -124,7 +124,7 @@ final class PrescanSystemDependenciesTest extends TestCase
new DependencyStatus('lib-bar', $versionParser->parseConstraints('^1.0'), null),
]);
($scanner)($this->composer, $this->targetPlatform, $request);
($scanner)($this->composer, $this->targetPlatform, $request, true);
$outputString = $this->io->getOutput();
self::assertStringContainsString('Extension foo/foo has unmet dependencies: lib-bar', $outputString);
@@ -164,7 +164,7 @@ final class PrescanSystemDependenciesTest extends TestCase
new DependencyStatus('lib-bar', $versionParser->parseConstraints('^1.0'), null),
]);
($scanner)($this->composer, $this->targetPlatform, $request);
($scanner)($this->composer, $this->targetPlatform, $request, true);
$outputString = $this->io->getOutput();
self::assertStringContainsString('Extension foo/foo has unmet dependencies: lib-bar', $outputString);
@@ -204,7 +204,7 @@ final class PrescanSystemDependenciesTest extends TestCase
new DependencyStatus('lib-bar', $versionParser->parseConstraints('^1.0'), null),
]);
($scanner)($this->composer, $this->targetPlatform, $request);
($scanner)($this->composer, $this->targetPlatform, $request, true);
$outputString = $this->io->getOutput();
self::assertStringContainsString('Extension foo/foo has unmet dependencies: lib-bar', $outputString);
@@ -244,11 +244,54 @@ final class PrescanSystemDependenciesTest extends TestCase
new DependencyStatus('lib-bar', $versionParser->parseConstraints('^1.0'), null),
]);
($scanner)($this->composer, $this->targetPlatform, $request);
($scanner)($this->composer, $this->targetPlatform, $request, true);
$outputString = $this->io->getOutput();
self::assertStringContainsString('Extension foo/foo has unmet dependencies: lib-bar', $outputString);
self::assertStringContainsString('Adding test package libbar-dev to be installed for lib-bar', $outputString);
self::assertStringContainsString('Installing missing system dependencies: echo "fake installing libbar-dev"', $outputString);
self::assertStringContainsString('Need to install missing system dependencies: echo "fake installing libbar-dev"', $outputString);
}
public function testMissingDependenciesAreNotInstalledWhenShouldNotAutoInstallAndNonInteractive(): void
{
$scanner = new PrescanSystemDependencies(
$this->dependencyResolver,
$this->fetchDependencyStatuses,
new SystemDependenciesDefinition([
'bar' => [
PackageManager::Apt->value => 'libbar-dev',
PackageManager::Apk->value => 'libbar-dev',
PackageManager::Test->value => 'libbar-dev',
],
]),
PackageManager::Test,
$this->io,
);
$request = new RequestedPackageAndVersion('foo/foo', null);
$composerPackage = new CompletePackage('foo/foo', '1.0.0.0', '1.0.0');
$piePackage = Package::fromComposerCompletePackage($composerPackage);
$this->dependencyResolver->expects(self::once())
->method('__invoke')
->with($this->composer, $this->targetPlatform, $request, true)
->willReturn($piePackage);
$versionParser = new VersionParser();
$this->fetchDependencyStatuses->expects(self::once())
->method('__invoke')
->with($this->targetPlatform, $this->composer, $composerPackage)
->willReturn([
new DependencyStatus('lib-bar', $versionParser->parseConstraints('^1.0'), null),
]);
($scanner)($this->composer, $this->targetPlatform, $request, false);
$outputString = $this->io->getOutput();
self::assertStringContainsString('Extension foo/foo has unmet dependencies: lib-bar', $outputString);
self::assertStringContainsString('Adding test package libbar-dev to be installed for lib-bar', $outputString);
self::assertStringContainsString('You are not running in interactive mode, and you did not provide the --auto-install-system-dependencies flag.', $outputString);
self::assertStringContainsString('You may need to run: echo "fake installing libbar-dev"', $outputString);
self::assertStringNotContainsString('Need to install missing system dependencies', $outputString);
}
}

View File

@@ -45,8 +45,8 @@ final class FetchDependencyStatusesTest extends TestCase
self::assertCount(3, $deps);
self::assertSame('ext-core: == 8.4.17.0 ✅', $deps[0]->asPrettyString());
self::assertSame('ext-core: == ' . $php->version() . '.0 ✅', $deps[0]->asPrettyString());
self::assertSame('ext-nonsense_extension: == * 🚫 (not installed)', $deps[1]->asPrettyString());
self::assertSame('ext-standard: < 1.0.0.0 🚫 (your version is 8.4.17.0)', $deps[2]->asPrettyString());
self::assertSame('ext-standard: < 1.0.0.0 🚫 (your version is ' . $php->version() . '.0)', $deps[2]->asPrettyString());
}
}