diff --git a/bin/mager b/bin/mager index 77ac5ec..22ff1f8 100755 --- a/bin/mager +++ b/bin/mager @@ -44,7 +44,6 @@ $exitCode = 0; } catch (ExitException $e) { $exitCode = $e->getStatus(); } - }); exit($exitCode); diff --git a/helpers/functions.php b/helpers/functions.php index 1f03735..bc3e335 100644 --- a/helpers/functions.php +++ b/helpers/functions.php @@ -49,8 +49,8 @@ function runLocally(callable|string|TaskInterface $command, bool $showProgress = return run($command, 'local', local: true, showProgress: $showProgress, throwError: $throwError, tty: $tty); } -function runOnManager(callable|string|TaskInterface $command, string $on, bool $showProgress = true, bool $throwError = true): mixed { - return run($command, $on, managerOnly: true, showProgress: $showProgress, throwError: $throwError); +function runOnManager(callable|string|TaskInterface $command, string $on, bool $showProgress = true, bool $throwError = true, bool $tty = false): mixed { + return run($command, $on, managerOnly: true, showProgress: $showProgress, throwError: $throwError, tty: $tty); } function runOnWorker(callable|string|TaskInterface $command, string $on, bool $showProgress = true, bool $throwError = true): void { diff --git a/src/Command/DeployCommand.php b/src/Command/DeployCommand.php index 76492de..08c560a 100644 --- a/src/Command/DeployCommand.php +++ b/src/Command/DeployCommand.php @@ -234,7 +234,7 @@ private function deploy( // just update image if service exists // TODO: update other configuration like cpu, labels, mount, ram if (yield CommandHelper::isServiceRunning($namespace, $serviceName)) { - yield "Deploying {$fullServiceName}" => "docker service update --image {$imageName} --force {$namespace}-{$serviceName}"; + yield "Deploying {$fullServiceName}" => "docker service update --image {$imageName} --force --task-history-limit 5 {$namespace}-{$serviceName}"; return; } diff --git a/src/Command/LogsCommand.php b/src/Command/LogsCommand.php new file mode 100644 index 0000000..099d36b --- /dev/null +++ b/src/Command/LogsCommand.php @@ -0,0 +1,64 @@ +addArgument('namespace', InputArgument::REQUIRED); + $this->addArgument('serviceName', InputArgument::REQUIRED); + + $this->addOption('follow', 'f', InputOption::VALUE_NONE, 'Stream logs until it cancelled'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $namespace = $input->getArgument('namespace'); + $serviceName = $input->getArgument('serviceName'); + $follow = $input->getOption('follow') ?? false; + + $cmd = ['docker', 'service', 'logs', "{$namespace}-{$serviceName}"]; + $tty = false; + if ($follow) { + $cmd[] = '--follow'; + $tty = true; + } + + $cmd = implode(' ', $cmd); + + $isRunning = runOnManager(fn() => yield CommandHelper::isServiceRunning($namespace, $serviceName), $namespace); + if (empty($isRunning)) { + $io->error("Service {$namespace}-{$serviceName} is not running"); + return Command::FAILURE; + } + + $res = runOnManager(fn() => yield $cmd, $namespace, throwError: false, tty: $tty); + + if (false === $tty) { + $io->writeln($res); + } + + return Command::SUCCESS; + } +} diff --git a/src/Component/TaskRunner/LocalRunner.php b/src/Component/TaskRunner/LocalRunner.php index cb8df78..faddda8 100644 --- a/src/Component/TaskRunner/LocalRunner.php +++ b/src/Component/TaskRunner/LocalRunner.php @@ -4,6 +4,8 @@ namespace App\Component\TaskRunner; +use Swoole\Coroutine; +use Swoole\Coroutine\System; use Swoole\Timer; use Symfony\Component\Console\Helper\ProgressIndicator; use Symfony\Component\Console\Style\SymfonyStyle; @@ -38,6 +40,13 @@ public function run(\Generator $tasks, bool $showProgress = true, bool $throwErr } $timer = Timer::tick(500, fn() => $progress?->advance()); + $cid = go(function() use ($process) { + System::waitSignal(SIGINT); + if (! $process->isRunning()) { + return; + } + $process->stop(signal: SIGINT); + }); try { $process->wait(function () use ($progress, $showProgress) { @@ -51,13 +60,12 @@ public function run(\Generator $tasks, bool $showProgress = true, bool $throwErr throw $e; } + Coroutine::cancel($cid); Timer::clear($timer); $exitCode = $process->getExitCode(); if (0 !== $exitCode && $throwError) { - $this->io->error($process->getErrorOutput()); - $this->io->writeln($process->getOutput()); $tasks->throw(new \Exception($process->getErrorOutput())); } diff --git a/src/Helper/CommandHelper.php b/src/Helper/CommandHelper.php index 430f00b..42f5548 100644 --- a/src/Helper/CommandHelper.php +++ b/src/Helper/CommandHelper.php @@ -33,11 +33,11 @@ public static function generateTlsCertificateLocally(string $namespace, string $ ->withCommand($domain); } - public static function isServiceRunning(string $namespace, string $name, string $mode = 'replicated'): string + public static function isServiceRunning(string $namespace, string $name): string { $fullServiceName = "{$namespace}-{$name}"; - return sprintf('docker service ls --format "{{.ID}}" --filter name=%s --filter mode=%s', $fullServiceName, $mode); + return sprintf('docker service ps --format "{{.ID}}" %s', $fullServiceName); } public static function removeService(string $namespace, string $name, string $mode = 'replicated'): \Generator