setName('update'); $this->setDescription('Update an existing BookStack instance.'); } /** * @throws CommandError */ protected function execute(InputInterface $input, OutputInterface $output): int { $output->writeln("Checking system requirements..."); RequirementsValidator::validate(); $output->writeln("Checking composer exists..."); $composerLocator = new ComposerLocator($this->appDir); $composer = $composerLocator->getProgram(); if (!$composer->isFound()) { $output->writeln("Composer does not exist, downloading a local copy..."); $composerLocator->download(); } $output->writeln("Fetching latest code via Git..."); $this->updateCodeUsingGit(); $output->writeln("Installing PHP dependencies via composer..."); $this->installComposerDependencies($composer); $output->writeln("Running database migrations..."); $this->runArtisanCommand(['migrate', '--force']); $output->writeln("Clearing app caches..."); $this->runArtisanCommand(['cache:clear']); $this->runArtisanCommand(['config:clear']); $this->runArtisanCommand(['view:clear']); return Command::SUCCESS; } /** * @throws CommandError */ protected function updateCodeUsingGit(): void { $errors = (new ProgramRunner('git', '/usr/bin/git')) ->withTimeout(240) ->withIdleTimeout(15) ->runCapturingStdErr([ '-C', $this->appDir, 'pull', '-q', 'origin', 'release', ]); if ($errors) { throw new CommandError("Failed git pull with errors:\n" . $errors); } } /** * @throws CommandError */ protected function installComposerDependencies(ProgramRunner $composer): void { $errors = $composer->runCapturingStdErr([ 'install', '--no-dev', '-n', '-q', '--no-progress', '-d', $this->appDir, ]); if ($errors) { throw new CommandError("Failed composer install with errors:\n" . $errors); } } protected function runArtisanCommand(array $commandArgs): void { $errors = (new ProgramRunner('php', '/usr/bin/php')) ->withTimeout(60) ->withIdleTimeout(5) ->withEnvironment(EnvironmentLoader::load($this->appDir)) ->runCapturingAllOutput([ $this->appDir . DIRECTORY_SEPARATOR . 'artisan', '-n', '-q', ...$commandArgs ]); if ($errors) { $cmdString = implode(' ', $commandArgs); throw new CommandError("Failed 'php artisan {$cmdString}' with errors:\n" . $errors); } } }