getMessage(); // Check if it's retryable and not the last attempt if ($this->isRetryableSshError($lastErrorMessage) && $attempt < $maxRetries - 1) { $delay = $this->calculateRetryDelay($attempt); // Track SSH retry event in Sentry $this->trackSshRetryEvent($attempt + 1, $maxRetries, $delay, $lastErrorMessage, $context); // Add deployment log if available (for ExecuteRemoteCommand trait) if (isset($this->application_deployment_queue) && method_exists($this, 'addRetryLogEntry')) { $this->addRetryLogEntry($attempt + 1, $maxRetries, $delay, $lastErrorMessage); } sleep($delay); continue; } // Not retryable or max retries reached break; } } // All retries exhausted if ($attempt >= $maxRetries) { Log::error('SSH operation failed after all retries', array_merge($context, [ 'attempts' => $attempt, 'error' => $lastErrorMessage, ])); } if ($throwError && $lastError) { // If the error message is empty, provide a more meaningful one if (empty($lastErrorMessage) || trim($lastErrorMessage) === '') { $contextInfo = isset($context['server']) ? " to server {$context['server']}" : ''; $attemptInfo = $attempt > 1 ? " after {$attempt} attempts" : ''; throw new \RuntimeException("SSH connection failed{$contextInfo}{$attemptInfo}", $lastError->getCode()); } throw $lastError; } return null; } /** * Track SSH retry event in Sentry */ protected function trackSshRetryEvent(int $attempt, int $maxRetries, int $delay, string $errorMessage, array $context = []): void { // Only track in production/cloud instances if (isDev() || ! config('constants.sentry.sentry_dsn')) { return; } try { app('sentry')->captureMessage( 'SSH connection retry triggered', \Sentry\Severity::warning(), [ 'extra' => [ 'attempt' => $attempt, 'max_retries' => $maxRetries, 'delay_seconds' => $delay, 'error_message' => $errorMessage, 'context' => $context, 'retryable_error' => true, ], 'tags' => [ 'component' => 'ssh_retry', 'error_type' => 'connection_retry', ], ] ); } catch (\Throwable $e) { // Don't let Sentry tracking errors break the SSH retry flow Log::warning('Failed to track SSH retry event in Sentry', [ 'error' => $e->getMessage(), 'original_attempt' => $attempt, ]); } } }