From 8a2f3b00dbb542e9963c45d2b34fcc36345881d2 Mon Sep 17 00:00:00 2001 From: Patrick Dawkins Date: Mon, 24 Jul 2023 10:01:08 +0100 Subject: [PATCH] Improve activity log formatting - Prioritize displaying the log if there is one non-integration activity - Add a newline before waiting - Standardize how activity descriptions are displayed --- .../Activity/ActivityCancelCommand.php | 6 +- .../Environment/EnvironmentResumeCommand.php | 1 - src/Service/ActivityMonitor.php | 74 +++++++++++++------ 3 files changed, 51 insertions(+), 30 deletions(-) diff --git a/src/Command/Activity/ActivityCancelCommand.php b/src/Command/Activity/ActivityCancelCommand.php index f6d985fbf..f41d1e322 100644 --- a/src/Command/Activity/ActivityCancelCommand.php +++ b/src/Command/Activity/ActivityCancelCommand.php @@ -96,11 +96,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $activity = $byId[$id]; } - $this->stdErr->writeln(sprintf( - 'Cancelling the activity %s (%s)...', - $activity->id, - ActivityMonitor::getFormattedDescription($activity) - )); + $this->stdErr->writeln('Cancelling the activity ' . ActivityMonitor::getFormattedDescription($activity, true, true, 'cyan')); try { $activity->cancel(); diff --git a/src/Command/Environment/EnvironmentResumeCommand.php b/src/Command/Environment/EnvironmentResumeCommand.php index 0f53914ca..8507992d1 100644 --- a/src/Command/Environment/EnvironmentResumeCommand.php +++ b/src/Command/Environment/EnvironmentResumeCommand.php @@ -39,7 +39,6 @@ protected function execute(InputInterface $input, OutputInterface $output) if (!$questionHelper->confirm('Are you sure you want to resume the paused environment ' . $environment->id . '?')) { return 1; } - $this->stdErr->writeln(''); $activity = $environment->resume(); $this->api()->clearEnvironmentsCache($environment->project); diff --git a/src/Service/ActivityMonitor.php b/src/Service/ActivityMonitor.php index 3aa8186f9..1a88dd61b 100644 --- a/src/Service/ActivityMonitor.php +++ b/src/Service/ActivityMonitor.php @@ -81,11 +81,8 @@ public function waitAndLog(Activity $activity, $pollInterval = 3, $timestamps = $logOutput = $logOutput ?: $stdErr; if ($context) { - $stdErr->writeln(sprintf( - 'Waiting for the activity %s (%s):', - $activity->id, - self::getFormattedDescription($activity) - )); + $stdErr->writeln(''); + $stdErr->writeln('Waiting for the activity: ' . self::getFormattedDescription($activity, true, true, 'cyan')); $stdErr->writeln(''); } @@ -205,23 +202,24 @@ public function waitAndLog(Activity $activity, $pollInterval = 3, $timestamps = } $bar->finish(); $stdErr->writeln(''); + $stdErr->writeln(''); // Display the success or failure messages. switch ($activity->result) { case Activity::RESULT_SUCCESS: - $stdErr->writeln("Activity {$activity->id} succeeded"); + $stdErr->writeln('The activity succeeded: ' . self::getFormattedDescription($activity, true, true, 'green')); return true; case Activity::RESULT_FAILURE: if ($activity->state === Activity::STATE_CANCELLED) { - $stdErr->writeln("The activity {$activity->id} was cancelled"); + $stdErr->writeln('The activity was cancelled: ' . self::getFormattedDescription($activity, true, true, 'yellow')); } else { - $stdErr->writeln("Activity {$activity->id} failed"); + $stdErr->writeln('The activity failed: ' . self::getFormattedDescription($activity, true, true, 'red')); } return false; } - $stdErr->writeln("The log for activity {$activity->id} finished with an unknown result"); + $stdErr->writeln('The activity finished with an unknown result: ' . self::getFormattedDescription($activity, true, true, 'yellow')); return false; } @@ -290,6 +288,7 @@ public function waitMultiple(array $activities, Project $project) { $stdErr = $this->getStdErr(); + // If there is 1 activity then display its log. $count = count($activities); if ($count == 0) { return true; @@ -297,9 +296,25 @@ public function waitMultiple(array $activities, Project $project) return $this->waitAndLog(reset($activities)); } + // If there is 1 non-integration activity, then display its log, and + // wait for the integration activities separately. + $nonIntegrationActivities = array_filter($activities, function (Activity $a) { + return strpos($a->type, 'integration.') !== 0; + }); + if (count($nonIntegrationActivities) === 1) { + $nonIntegrationActivity = reset($nonIntegrationActivities); + $integrationActivities = array_filter($activities, function (Activity $a) { + return strpos($a->type, 'integration.') === 0; + }); + $nonIntegrationSuccess = $this->waitAndLog($nonIntegrationActivity); + $integrationSuccess = $this->waitMultiple($integrationActivities, $project); + return $nonIntegrationSuccess && $integrationSuccess; + } + + // For more than one activity, display a progress bar with the status of each. $stdErr->writeln(sprintf('Waiting for %d activities...', $count)); foreach ($activities as $activity) { - $stdErr->writeln(sprintf(' %s: %s', $activity->id, self::getFormattedDescription($activity))); + $stdErr->writeln(' ', self::getFormattedDescription($activity, true, true, 'cyan')); } // The progress bar will show elapsed time and all of the activities' @@ -366,19 +381,18 @@ public function waitMultiple(array $activities, Project $project) // Display success or failure messages for each activity. $success = true; foreach ($activities as $activity) { - $description = self::getFormattedDescription($activity); switch ($activity['result']) { case Activity::RESULT_SUCCESS: - $stdErr->writeln(sprintf('Activity %s succeeded: %s', $activity->id, $description)); + $stdErr->writeln('Activity succeeded: ' . self::getFormattedDescription($activity, true, true, 'green')); break; case Activity::RESULT_FAILURE: $success = false; - $stdErr->writeln(sprintf('Activity %s failed', $activity->id)); + $stdErr->writeln(sprintf('Activity failed: %s', $activity->id)); // If the activity failed, show the complete log. - $stdErr->writeln(' Description: ' . $description); - $stdErr->writeln(' Log:'); + $stdErr->writeln(' Description: ' . self::getFormattedDescription($activity)); + $stdErr->writeln(' Log:'); $stdErr->writeln($this->indent($this->formatLog($activity->readLog()))); break; } @@ -435,31 +449,43 @@ protected function newProgressBar(OutputInterface $output) /** * Get the formatted description of an activity. * - * @param \Platformsh\Client\Model\Activity $activity - * @param bool $withDecoration + * @param \Platformsh\Client\Model\Activity $activity The activity. + * @param bool $withDecoration Add decoration to activity tags. + * @param bool $withId Add the activity ID. + * @param string $fgColor Define a foreground color e.g. 'green', 'red', 'cyan'. * * @return string */ - public static function getFormattedDescription(Activity $activity, $withDecoration = true) + public static function getFormattedDescription(Activity $activity, $withDecoration = true, $withId = false, $fgColor = '') { if (!$withDecoration) { + if ($withId) { + return '[' . $activity->id . '] ' . $activity->getDescription(false); + } return $activity->getDescription(false); } - $value = $activity->getDescription(true); + $descr = $activity->getDescription(true); // Replace description HTML elements with Symfony Console decoration // tags. - $value = preg_replace('@<[^/][^>]+>@', '', $value); - $value = preg_replace('@]+>@', '', $value); + $descr = preg_replace('@<[^/][^>]+>@', '', $descr); + $descr = preg_replace('@]+>@', '', $descr); // Replace literal tags like "<info&;gt;" with escaped tags like // "\". - $value = preg_replace('@<(/?[a-z][a-z0-9,_=;-]*+)>@i', '\\\<$1>', $value); + $descr = preg_replace('@<(/?[a-z][a-z0-9,_=;-]*+)>@i', '\\\<$1>', $descr); // Decode other HTML entities. - $value = html_entity_decode($value, ENT_QUOTES, 'utf-8'); + $descr = html_entity_decode($descr, ENT_QUOTES, 'utf-8'); + + if ($withId) { + if ($fgColor) { + return sprintf('[%s] %s', $fgColor, $activity->id, $descr); + } + return sprintf('[%s] %s', $activity->id, $descr); + } - return $value; + return $descr; } /**