From a3b7cc7ba8cd0b913dd74221fcce7694884edae8 Mon Sep 17 00:00:00 2001 From: Veronika Tolkachova Date: Thu, 18 Jun 2026 15:49:41 +0200 Subject: [PATCH 1/3] feat: implement task execute command --- .../src/Command/Task/TaskExecuteCommand.php | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 legacy/src/Command/Task/TaskExecuteCommand.php diff --git a/legacy/src/Command/Task/TaskExecuteCommand.php b/legacy/src/Command/Task/TaskExecuteCommand.php new file mode 100644 index 00000000..ccdbc515 --- /dev/null +++ b/legacy/src/Command/Task/TaskExecuteCommand.php @@ -0,0 +1,110 @@ +addArgument('task', InputArgument::REQUIRED, 'The name of the task to execute') + ->addOption('variable', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A variable to set when running the task, in the format type:name=value'); + + $this->selector->addProjectOption($this->getDefinition()); + $this->selector->addEnvironmentOption($this->getDefinition()); + $this->addCompleter($this->selector); + + $this->addExample('Execute the "migrate" task on the environment "main"', 'migrate --environment main'); + $this->addExample('Execute the "migrate" task, setting environment variable FOO=bar', 'migrate -e main --variable env:FOO=bar'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $selection = $this->selector->getSelection($input); + $environment = $selection->getEnvironment(); + + $taskName = $input->getArgument('task'); + $variables = $this->parseVariables($input->getOption('variable')); + + $this->stdErr->writeln(sprintf( + 'Executing task %s on the environment %s', + $taskName, + $this->api->getEnvironmentLabel($environment), + )); + + $url = $environment->getUri() . '/tasks/' . rawurlencode($taskName) . '/run'; + $response = $this->api->getHttpClient()->post($url, ['json' => ['variables' => (object) $variables]]); + + $result = new Result( + (array) Utils::jsonDecode((string) $response->getBody(), true), + $environment->getUri(), + $this->api->getHttpClient(), + Activity::class, + ); + $activities = $result->getActivities(); + + $this->stdErr->writeln(''); + $this->stdErr->writeln('The task has been triggered.'); + + $executable = $this->config->getStr('application.executable'); + if ($activities !== []) { + // Reference the exact activity ID so the log can be followed even + // when several activities are running in parallel. + $activity = reset($activities); + $this->stdErr->writeln(sprintf( + 'To follow its log, run: %s activity:log %s', + $executable, + $activity->id, + )); + } else { + $this->stdErr->writeln(sprintf( + 'To follow its log, run: %s activity:log --type environment.task -e %s', + $executable, + $environment->id, + )); + } + + return 0; + } + + /** + * Parses variables in the format type:name=value into a nested array. + * + * @param string[] $variables + * + * @return array> + */ + private function parseVariables(array $variables): array + { + $map = []; + $variable = new Variable(); + foreach ($variables as $var) { + [$type, $name, $value] = $variable->parse($var); + $map[$type][$name] = $value; + } + + return $map; + } +} From ee07e1e71c729def31200ca341b184b666ac18bc Mon Sep 17 00:00:00 2001 From: Veronika Tolkachova Date: Fri, 19 Jun 2026 16:08:55 +0200 Subject: [PATCH 2/3] feat: add tasks list command --- legacy/src/Command/Task/TaskListCommand.php | 84 +++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 legacy/src/Command/Task/TaskListCommand.php diff --git a/legacy/src/Command/Task/TaskListCommand.php b/legacy/src/Command/Task/TaskListCommand.php new file mode 100644 index 00000000..d3a296cd --- /dev/null +++ b/legacy/src/Command/Task/TaskListCommand.php @@ -0,0 +1,84 @@ + */ + private array $tableHeader = [ + 'name' => 'Name', + 'type' => 'Type', + 'command' => 'Command', + 'timeout' => 'Timeout (s)', + ]; + + public function __construct(private readonly Api $api, private readonly Selector $selector, private readonly Table $table) + { + parent::__construct(); + } + + protected function configure(): void + { + Table::configureInput($this->getDefinition(), $this->tableHeader); + $this->selector->addProjectOption($this->getDefinition()); + $this->selector->addEnvironmentOption($this->getDefinition()); + $this->addCompleter($this->selector); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $selection = $this->selector->getSelection($input); + $environment = $selection->getEnvironment(); + + try { + $response = $this->api->getHttpClient()->get($environment->getUri() . '/tasks'); + } catch (BadResponseException $e) { + throw ApiResponseException::create($e->getRequest(), $e->getResponse(), $e); + } + $tasks = (array) Utils::jsonDecode((string) $response->getBody(), true); + + if ($tasks === []) { + $this->stdErr->writeln(sprintf( + 'No tasks were found on the environment %s.', + $this->api->getEnvironmentLabel($environment), + )); + + return 0; + } + + $rows = []; + foreach ($tasks as $task) { + $rows[] = [ + 'name' => $task['name'] ?? '', + 'type' => $task['type'] ?? '', + 'command' => isset($task['run']['command']) ? trim((string) $task['run']['command']) : '', + 'timeout' => $task['run']['timeout'] ?? '', + ]; + } + + if (!$this->table->formatIsMachineReadable()) { + $this->stdErr->writeln(sprintf( + 'Tasks on the environment %s:', + $this->api->getEnvironmentLabel($environment), + )); + } + + $this->table->render($rows, $this->tableHeader); + + return 0; + } +} From f9d1f471efcda2033e91902a337492cca4707f3b Mon Sep 17 00:00:00 2001 From: Veronika Tolkachova Date: Fri, 19 Jun 2026 16:11:51 +0200 Subject: [PATCH 3/3] refactor: add task activity to the const list --- legacy/src/Command/Task/TaskExecuteCommand.php | 2 +- legacy/src/Command/Task/TaskListCommand.php | 2 +- legacy/src/Service/ActivityLoader.php | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/legacy/src/Command/Task/TaskExecuteCommand.php b/legacy/src/Command/Task/TaskExecuteCommand.php index ccdbc515..62dc12e6 100644 --- a/legacy/src/Command/Task/TaskExecuteCommand.php +++ b/legacy/src/Command/Task/TaskExecuteCommand.php @@ -55,7 +55,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int )); $url = $environment->getUri() . '/tasks/' . rawurlencode($taskName) . '/run'; - $response = $this->api->getHttpClient()->post($url, ['json' => ['variables' => (object) $variables]]); + $response = $this->api->getHttpClient()->request('POST', $url, ['json' => ['variables' => (object) $variables]]); $result = new Result( (array) Utils::jsonDecode((string) $response->getBody(), true), diff --git a/legacy/src/Command/Task/TaskListCommand.php b/legacy/src/Command/Task/TaskListCommand.php index d3a296cd..40c94303 100644 --- a/legacy/src/Command/Task/TaskListCommand.php +++ b/legacy/src/Command/Task/TaskListCommand.php @@ -45,7 +45,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $environment = $selection->getEnvironment(); try { - $response = $this->api->getHttpClient()->get($environment->getUri() . '/tasks'); + $response = $this->api->getHttpClient()->request('GET', $environment->getUri() . '/tasks'); } catch (BadResponseException $e) { throw ApiResponseException::create($e->getRequest(), $e->getResponse(), $e); } diff --git a/legacy/src/Service/ActivityLoader.php b/legacy/src/Service/ActivityLoader.php index 55d4d4b0..cfb2581a 100644 --- a/legacy/src/Service/ActivityLoader.php +++ b/legacy/src/Service/ActivityLoader.php @@ -201,6 +201,7 @@ public static function getAvailableTypes(): array 'environment.source-operation', 'environment.subscription.update', 'environment.synchronize', + 'environment.task', 'environment.update.http_access', 'environment.update.restrict_robots', 'environment.update.smtp',