setName('update');
$this->setDescription('Update an existing BookStack instance.');
$this->addOption('app-directory', null, InputOption::VALUE_OPTIONAL, 'BookStack install directory to update', '');
}
/**
* @throws CommandError
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$appDir = AppLocator::require($input->getOption('app-directory'));
$output->writeln("Checking system requirements...");
RequirementsValidator::validate();
$output->writeln("Checking composer exists...");
$composerLocator = new ComposerLocator($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($appDir);
$output->writeln("Installing PHP dependencies via composer...");
$this->installComposerDependencies($composer, $appDir);
$output->writeln("Running database migrations...");
$artisan = (new ArtisanRunner($appDir));
$artisan->run(['migrate', '--force']);
$output->writeln("Clearing app caches...");
$artisan->run(['cache:clear']);
$artisan->run(['config:clear']);
$artisan->run(['view:clear']);
$output->writeln("Your BookStack instance at [{$appDir}] has been updated!");
return Command::SUCCESS;
}
/**
* @throws CommandError
*/
protected function updateCodeUsingGit(string $appDir): void
{
$errors = (new ProgramRunner('git', '/usr/bin/git'))
->withTimeout(240)
->withIdleTimeout(15)
->runCapturingStdErr([
'-C', $appDir,
'pull', '-q', 'origin', 'release',
]);
if ($errors) {
throw new CommandError("Failed git pull with errors:\n" . $errors);
}
}
/**
* @throws CommandError
*/
protected function installComposerDependencies(ProgramRunner $composer, string $appDir): void
{
$errors = $composer->runCapturingStdErr([
'install',
'--no-dev', '-n', '-q', '--no-progress',
'-d', $appDir,
]);
if ($errors) {
throw new CommandError("Failed composer install with errors:\n" . $errors);
}
}
}