Skip to content
7 changes: 3 additions & 4 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,7 @@ The PIE is built using [Static PHP](https://static-php.dev/), which builds a
self-contained PHP executable with the extensions that PIE needs to run, and
bundles the PHAR as a single distributable executable. Please keep in mind that
this is **experimental**, and we do not recommend this for production use for
the time being. Please also note there are some limitations:

- [php/pie#460](https://github.com/php/pie/discussions/460) - all the binary
versions have the `pie self-update` feature disabled for now.
the time being.

If you find the binary releases useful, please leave feedback or upvote on the
relevant discussions, so we can gauge interest in improving this functionality.
Expand All @@ -128,6 +125,7 @@ stable releases can be downloaded from these links:
| Linux | amd64 / x86_64 | https://github.com/php/pie/releases/latest/download/pie-Linux-X64 |
| OS X | ARM 64 / aarch64 | https://github.com/php/pie/releases/latest/download/pie-macOS-ARM64 |
| Linux | ARM 64 / aarch64 | https://github.com/php/pie/releases/latest/download/pie-Linux-ARM64 |
| Windows | amd64 / x86_64 | https://github.com/php/pie/releases/latest/download/pie-Windows-X64.exe |

The "nightly" versions of these can be found here:

Expand All @@ -136,6 +134,7 @@ The "nightly" versions of these can be found here:
| Linux | amd64 / x86_64 | https://php.github.io/pie/pie-Linux-X64 |
| OS X | ARM 64 / aarch64 | https://php.github.io/pie/pie-macOS-ARM64 |
| Linux | ARM 64 / aarch64 | https://php.github.io/pie/pie-Linux-ARM64 |
| Windows | amd64 / x86_64 | https://php.github.io/pie/pie-Windows-X64.exe |

We *highly* recommend you verify the file came from the PHP GitHub repository
before running it, for example:
Expand Down
28 changes: 23 additions & 5 deletions src/Command/CommandHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,28 @@ public static function configurePhpConfigOptions(Command $command): void
);
}

public static function writeRunningPhpVersion(IOInterface $io): void
{
if (PiePlatform::isRunningStaticPhp()) {
$io->write(sprintf('<info>You are running a PIE Static PHP %s build</info>', PHP_VERSION));

return;
}

$io->write(sprintf('<info>You are running PHP %s</info>', PHP_VERSION));
}

public static function warnPhpConfigOptionsHaveNoEffect(InputInterface $input, IOInterface $io): void
{
foreach ([self::OPTION_WITH_PHP_CONFIG, self::OPTION_WITH_PHP_PATH, self::OPTION_WITH_PHPIZE_PATH] as $option) {
if (! $input->hasOption($option) || $input->getOption($option) === null) {
continue;
}

$io->writeError(sprintf('<warning>The --%s option is now deprecated and has no effect for this command.</warning>', $option));
}
}

public static function configureBuildToolsCheckOptions(Command $command): void
{
$command->addOption(
Expand Down Expand Up @@ -281,11 +303,7 @@ public static function determineTargetPlatformFromInputs(InputInterface $input,

$targetPlatform = TargetPlatform::fromPhpBinaryPath($phpBinaryPath, $makeParallelJobs, $phpizePath);

if (PiePlatform::isRunningStaticPhp()) {
$io->write(sprintf('<info>You are running a PIE Static PHP %s build</info>', PHP_VERSION));
} else {
$io->write(sprintf('<info>You are running PHP %s</info>', PHP_VERSION));
}
self::writeRunningPhpVersion($io);

$io->write(sprintf(
'<info>Target PHP installation:</info> %s %s%s, on %s %s (from %s)',
Expand Down
46 changes: 21 additions & 25 deletions src/Command/SelfUpdateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,23 @@

namespace Php\Pie\Command;

use Composer\Factory;
use Composer\IO\IOInterface;
use Composer\IO\NullIO;
use Php\Pie\ComposerIntegration\PieComposerFactory;
use Php\Pie\ComposerIntegration\PieComposerRequest;
use Php\Pie\ComposerIntegration\QuieterConsoleIO;
use Php\Pie\File\FullPathToSelf;
use Php\Pie\File\ReplaceRunningExecutable;
use Php\Pie\File\SudoFilePut;
use Php\Pie\Platform;
use Php\Pie\SelfManage\Update\Channel;
use Php\Pie\SelfManage\Update\FetchPieReleaseFromGitHub;
use Php\Pie\SelfManage\Update\IsBrewInstallation;
use Php\Pie\SelfManage\Update\PieAssetName;
use Php\Pie\SelfManage\Update\ReleaseIsNewer;
use Php\Pie\SelfManage\Update\ReleaseMetadata;
use Php\Pie\SelfManage\Verify\RecoverFromFailedVerification;
use Php\Pie\SelfManage\Verify\VerifyPieReleaseUsingAttestation;
use Php\Pie\Settings;
use Php\Pie\Util\Emoji;
use Php\Pie\Util\PieVersion;
use Psr\Container\ContainerInterface;
use Safe\Exceptions\FilesystemException;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
Expand Down Expand Up @@ -53,7 +51,6 @@ public function __construct(
private readonly string $githubApiBaseUrl,
private readonly IOInterface $io,
private readonly QuieterConsoleIO $quieterConsoleIo,
private readonly ContainerInterface $container,
private readonly FullPathToSelf $fullPathToSelf,
) {
parent::__construct();
Expand Down Expand Up @@ -86,7 +83,9 @@ public function configure(): void

public function execute(InputInterface $input, OutputInterface $output): int
{
if (! PieVersion::isPharBuild() || Platform::isRunningStaticPhp()) {
CommandHelper::warnPhpConfigOptionsHaveNoEffect($input, $this->io);

if (! PieVersion::isPharBuild()) {
$this->io->writeError('<comment>Aborting! You are not running a PHAR, cannot self-update.</comment>');

return Command::FAILURE;
Expand Down Expand Up @@ -116,36 +115,28 @@ public function execute(InputInterface $input, OutputInterface $output): int
}

$this->io->write(sprintf('Updating using the <info>%s</> channel.', $updateChannel->value));

$targetPlatform = CommandHelper::determineTargetPlatformFromInputs($input, $this->io);
CommandHelper::writeRunningPhpVersion($this->io);

CommandHelper::applyNoCacheOptionIfSet($input, $this->io);

$composer = PieComposerFactory::createPieComposer(
$this->container,
PieComposerRequest::noOperation(
new NullIO(),
$targetPlatform,
),
);
$composerConfig = Factory::createConfig($this->quieterConsoleIo);
$this->quieterConsoleIo->loadConfiguration($composerConfig);

$fetchLatestPieRelease = FetchPieReleaseFromGitHub::factory(
$this->quieterConsoleIo,
$composer->getConfig(),
$composerConfig,
$this->githubApiBaseUrl,
PieAssetName::forRunningPie(),
);
$verifyPiePhar = VerifyPieReleaseUsingAttestation::factory(
$fetchLatestPieRelease,
$this->quieterConsoleIo,
$composer->getConfig(),
$composerConfig,
$this->githubApiBaseUrl,
);

if ($updateChannel === Channel::Nightly) {
$latestRelease = new ReleaseMetadata(
'nightly',
'https://php.github.io/pie/pie-nightly.phar',
);
$latestRelease = $fetchLatestPieRelease->nightlyReleaseMetadata();

$this->io->write('Downloading the latest nightly release.');
} else {
Expand Down Expand Up @@ -201,7 +192,7 @@ public function execute(InputInterface $input, OutputInterface $output): int
try {
$pharContents = file_get_contents($pharFilename->filePath);
} catch (FilesystemException) {
$this->io->writeError(sprintf('<error>%s Failed to read the downloaded PHAR file %s</error>', Emoji::CROSS, $pharFilename->filePath));
$this->io->writeError(sprintf('<error>%s Failed to read the downloaded PIE release file %s</error>', Emoji::CROSS, $pharFilename->filePath));
unlink($pharFilename->filePath);

return Command::FAILURE;
Expand All @@ -210,7 +201,7 @@ public function execute(InputInterface $input, OutputInterface $output): int
try {
$pharFilename->verifyContent($pharContents);
} catch (Throwable) {
$this->io->writeError(sprintf('<error>%s PHAR contents changed after verification; aborting self-update</error>', Emoji::CROSS));
$this->io->writeError(sprintf('<error>%s Downloaded PIE release contents changed after verification; aborting self-update</error>', Emoji::CROSS));
unlink($pharFilename->filePath);

return Command::FAILURE;
Expand All @@ -220,7 +211,12 @@ public function execute(InputInterface $input, OutputInterface $output): int
sprintf('Writing new version to %s', $fullPathToSelf),
verbosity: IOInterface::VERBOSE,
);
SudoFilePut::contents($fullPathToSelf, $pharContents);
if (Platform::isRunningStaticPhp()) {
ReplaceRunningExecutable::contents($fullPathToSelf, $pharContents);
} else {
SudoFilePut::contents($fullPathToSelf, $pharContents);
}

unlink($pharFilename->filePath);

$this->io->write(sprintf(
Expand Down
25 changes: 10 additions & 15 deletions src/Command/SelfVerifyCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,17 @@

namespace Php\Pie\Command;

use Composer\Factory;
use Composer\IO\IOInterface;
use Composer\IO\NullIO;
use Php\Pie\ComposerIntegration\PieComposerFactory;
use Php\Pie\ComposerIntegration\PieComposerRequest;
use Php\Pie\ComposerIntegration\QuieterConsoleIO;
use Php\Pie\File\BinaryFile;
use Php\Pie\File\FullPathToSelf;
use Php\Pie\SelfManage\Update\FetchPieReleaseFromGitHub;
use Php\Pie\SelfManage\Update\PieAssetName;
use Php\Pie\SelfManage\Update\ReleaseMetadata;
use Php\Pie\SelfManage\Verify\VerifyPieReleaseUsingAttestation;
use Php\Pie\Util\Emoji;
use Php\Pie\Util\PieVersion;
use Psr\Container\ContainerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
Expand All @@ -41,7 +39,6 @@ public function __construct(
private readonly FullPathToSelf $fullPathToSelf,
private readonly IOInterface $io,
private readonly QuieterConsoleIO $quieterConsoleIo,
private readonly ContainerInterface $container,
) {
parent::__construct();
}
Expand All @@ -60,6 +57,8 @@ public function configure(): void

public function execute(InputInterface $input, OutputInterface $output): int
{
CommandHelper::warnPhpConfigOptionsHaveNoEffect($input, $this->io);

if (! PieVersion::isPharBuild()) {
$this->io->writeError('<comment>Aborting! You are not running a PHAR, cannot self-verify.</comment>');

Expand All @@ -73,30 +72,26 @@ public function execute(InputInterface $input, OutputInterface $output): int
$this->io->write(sprintf('<comment>No version specified, verifying against the version this PHAR claims to be (%s).</comment>', $expectedVersion));
}

$targetPlatform = CommandHelper::determineTargetPlatformFromInputs($input, $this->io);
CommandHelper::writeRunningPhpVersion($this->io);

CommandHelper::applyNoCacheOptionIfSet($input, $this->io);

$composer = PieComposerFactory::createPieComposer(
$this->container,
PieComposerRequest::noOperation(
new NullIO(),
$targetPlatform,
),
);
$composerConfig = Factory::createConfig($this->quieterConsoleIo);
$this->quieterConsoleIo->loadConfiguration($composerConfig);

$fetchLatestPieRelease = FetchPieReleaseFromGitHub::factory(
$this->quieterConsoleIo,
$composer->getConfig(),
$composerConfig,
$this->githubApiBaseUrl,
PieAssetName::forRunningPie(),
);

$latestRelease = new ReleaseMetadata($expectedVersion, 'blah');
$pharFilename = BinaryFile::fromFileWithSha256Checksum(($this->fullPathToSelf)());
$verifyPiePhar = VerifyPieReleaseUsingAttestation::factory(
$fetchLatestPieRelease,
$this->quieterConsoleIo,
$composer->getConfig(),
$composerConfig,
$this->githubApiBaseUrl,
);

Expand Down
Loading
Loading