Skip to content

Commit 0f1fdf2

Browse files
authored
Merge pull request #19 from ploi/feature/improve-log-streaming
added: deployment log streaming
2 parents fa2ef00 + ddfc451 commit 0f1fdf2

3 files changed

Lines changed: 133 additions & 213 deletions

File tree

app/Commands/DeployCommand.php

Lines changed: 29 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class DeployCommand extends Command
1717
{
1818
use EnsureHasToken, HasPloiConfiguration, InteractWithServer, InteractWithSite;
1919

20-
protected $signature = 'deploy {--server=} {--site=} {--schedule=} {--stream : Stream deployment logs in real-time} {--deployment-id= : Specific deployment ID to stream}';
20+
protected $signature = 'deploy {--server=} {--site=} {--schedule=} {--no-stream : Disable real-time deployment log streaming}';
2121

2222
protected $description = 'Deploy your site to Ploi.io with optional log streaming.';
2323

@@ -34,7 +34,7 @@ public function handle(): void
3434
$data = [];
3535
$isScheduled = false;
3636

37-
if ($this->ploi->getSiteDetails($serverId, $siteId)['data']['has_staging']) {
37+
if ($this->site['has_staging']) {
3838
$this->warn("{$this->site['domain']} has a staging environment.");
3939
$deployToProduction = confirm(
4040
label: 'Do you want to deploy to production? (yes/no)',
@@ -58,17 +58,6 @@ public function handle(): void
5858
}
5959

6060
$this->deploy($serverId, $siteId, $this->site['domain'], $data, $isScheduled);
61-
62-
// Handle streaming after deployment
63-
if ($this->option('stream') && ! $isScheduled) {
64-
$deploymentId = $this->option('deployment-id') ?? $this->getLatestDeploymentId($serverId, $siteId);
65-
66-
if ($deploymentId) {
67-
$this->streamDeploymentLogs($serverId, $siteId, $deploymentId);
68-
} else {
69-
$this->error('No deployment found to stream');
70-
}
71-
}
7261
}
7362

7463
protected function validateScheduleDatetime(string $datetime): void
@@ -106,21 +95,27 @@ protected function deploy($serverId, $siteId, $domain, $data, $isScheduled = fal
10695
return;
10796
}
10897

109-
$this->pollDeploymentStatus($serverId, $siteId, $domain);
98+
if ($this->option('no-stream')) {
99+
$this->pollDeploymentStatus($serverId, $siteId, $domain);
100+
101+
return;
102+
}
103+
104+
$this->streamAndAwait($serverId, $siteId, $domain);
110105
}
111106

112107
protected function pollDeploymentStatus(string $serverId, string $siteId, string $domain): void
113108
{
114-
$maxAttempts = 60; // Maximum number of polling attempts (10 minutes total with 10-second delay)
115-
$delay = 5; // Delay between each attempt in seconds
109+
$maxAttempts = 60; // Maximum number of polling attempts (5 minutes total with 5-second delay)
110+
$delay = 5; // Delay between each attempt in seconds
116111

117112
$this->info('Deployment initiated!');
113+
118114
$status = spin(
119115
callback: function () use ($serverId, $siteId, $domain, $maxAttempts, $delay) {
120116
for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
121117
$deploymentStatus = $this->ploi->getSiteDetails($serverId, $siteId)['data']['status'] ?? 'deploying';
122118

123-
// If we get a final status, return it
124119
if (in_array($deploymentStatus, ['active', 'deploy-failed'])) {
125120
return [
126121
'status' => $deploymentStatus,
@@ -131,7 +126,6 @@ protected function pollDeploymentStatus(string $serverId, string $siteId, string
131126
sleep($delay);
132127
}
133128

134-
// If we've exceeded max attempts, return timeout status
135129
return [
136130
'status' => 'timeout',
137131
'domain' => $domain,
@@ -140,59 +134,41 @@ protected function pollDeploymentStatus(string $serverId, string $siteId, string
140134
message: 'Checking deployment status...'
141135
);
142136

143-
// Handle the deployment result
144137
match ($status['status']) {
145138
'active' => $this->handleSuccessfulDeployment($serverId, $siteId, $status['domain']),
146139
'deploy-failed' => $this->handleFailedDeployment($serverId, $siteId),
147140
'timeout' => $this->warn('Deployment status check timed out. Please check manually.'),
148-
default => $this->warn('Deployment status is unknown. Please check manually.')
141+
default => $this->warn('Deployment status is unknown. Please check manually.'),
149142
};
150143
}
151144

152-
/**
153-
* Stream deployment logs in real-time
154-
*
155-
* @return void
156-
*/
157-
private function streamDeploymentLogs(int $serverId, int $siteId, int $deploymentId)
145+
private function streamAndAwait(int $serverId, int $siteId, string $domain): void
158146
{
159147
$this->info('🔄 Streaming deployment logs...');
160148
$this->newLine();
161149

162-
$poller = new DeploymentLogPoller(config('ploi.token'));
150+
$poller = new DeploymentLogPoller($this->ploi);
163151

164152
try {
165-
$poller->pollDeploymentLogs($serverId, $siteId, $deploymentId, function ($line) {
166-
// Format the log line with timestamp
153+
$status = $poller->pollDeploymentLogs($serverId, $siteId, function ($line) {
167154
$timestamp = now()->format('H:i:s');
168-
$this->line("<fg=gray>[{$timestamp}]</fg=gray> {$line}");
155+
$this->line("<fg=gray>[{$timestamp}]</> {$line}");
169156
});
170-
171-
$this->newLine();
172-
$this->success('✅ Deployment streaming completed!');
173-
174157
} catch (Exception $e) {
175158
$this->newLine();
176-
$this->error('❌ Streaming failed: '.$e->getMessage());
177-
}
178-
}
159+
$this->warn('Log streaming failed ('.$e->getMessage().'), falling back to status checks...');
160+
$this->pollDeploymentStatus($serverId, $siteId, $domain);
179161

180-
/**
181-
* Get the latest deployment ID for streaming
182-
*/
183-
private function getLatestDeploymentId(int $serverId, int $siteId): ?int
184-
{
185-
$poller = new DeploymentLogPoller(config('ploi.token'));
186-
187-
try {
188-
$deployment = $poller->getLatestDeployment($serverId, $siteId);
162+
return;
163+
}
189164

190-
return isset($deployment['id']) ? (int) $deployment['id'] : null;
191-
} catch (Exception $e) {
192-
$this->error('Failed to get latest deployment: '.$e->getMessage());
165+
$this->newLine();
193166

194-
return null;
195-
}
167+
match ($status) {
168+
'active' => $this->handleSuccessfulDeployment($serverId, $siteId, $domain),
169+
'deploy-failed' => $this->handleFailedDeployment($serverId, $siteId),
170+
default => $this->warn('Deployment status check timed out. Please check manually.'),
171+
};
196172
}
197173

198174
/**
@@ -210,8 +186,8 @@ private function handleFailedDeployment(string $serverId, string $siteId): void
210186
{
211187
$this->error('Your recent deployment has failed, please check recent deploy log for errors.');
212188

213-
// Show link to deployment logs if not streaming
214-
if (! $this->option('stream')) {
189+
// When streaming, the failed log output is already shown inline.
190+
if ($this->option('no-stream')) {
215191
$this->showLogLink($serverId, $siteId);
216192
}
217193
}
@@ -222,7 +198,6 @@ private function handleFailedDeployment(string $serverId, string $siteId): void
222198
private function showLogLink(string $serverId, string $siteId): void
223199
{
224200
try {
225-
// Get the latest deployment log ID
226201
$logs = $this->ploi->getSiteLogs($serverId, $siteId, 1)['data'];
227202

228203
if (! empty($logs)) {

app/Commands/LogsCommand.php

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class LogsCommand extends Command
1010
{
1111
use EnsureHasToken;
1212

13-
protected $signature = 'logs:stream {server} {site} {--deployment-id= : Specific deployment ID to stream}';
13+
protected $signature = 'logs:stream {server} {site}';
1414

1515
protected $description = 'Stream deployment logs for a specific site';
1616

@@ -20,39 +20,37 @@ public function handle(): void
2020

2121
$serverId = (int) $this->argument('server');
2222
$siteId = (int) $this->argument('site');
23-
$deploymentId = $this->option('deployment-id');
24-
25-
$poller = new DeploymentLogPoller(config('ploi.token'));
2623

2724
try {
28-
// If no deployment ID provided, get the latest or active deployment
29-
if (! $deploymentId) {
30-
$deployment = $poller->getActiveDeployment($serverId, $siteId)
31-
?? $poller->getLatestDeployment($serverId, $siteId);
25+
$site = $this->ploi->getSiteDetails($serverId, $siteId)['data'] ?? null;
26+
27+
if (! $site) {
28+
$this->error('Site not found.');
29+
30+
return;
31+
}
3232

33-
if (! $deployment) {
34-
$this->error('No deployment found for this site');
33+
$currentLog = $site['current_deploy_log'] ?? null;
34+
$status = $site['status'] ?? null;
3535

36-
return;
37-
}
36+
if ($currentLog === null && $status !== 'deploying') {
37+
$this->info('No deployment in progress for this site.');
3838

39-
$deploymentId = $deployment['id'];
40-
$this->info("Streaming logs for deployment #{$deploymentId} (status: {$deployment['status']})");
41-
} else {
42-
$this->info("Streaming logs for deployment #{$deploymentId}");
39+
return;
4340
}
4441

45-
$this->info('🔄 Streaming deployment logs... (Press Ctrl+C to stop)');
42+
$this->info("🔄 Streaming deployment logs for {$site['domain']}... (Press Ctrl+C to stop)");
4643
$this->newLine();
4744

48-
$poller->pollDeploymentLogs($serverId, $siteId, $deploymentId, function ($line) {
45+
$poller = new DeploymentLogPoller($this->ploi);
46+
47+
$poller->pollDeploymentLogs($serverId, $siteId, function ($line) {
4948
$timestamp = now()->format('H:i:s');
50-
$this->line("<fg=gray>[{$timestamp}]</fg=gray> {$line}");
49+
$this->line("<fg=gray>[{$timestamp}]</> {$line}");
5150
});
5251

5352
$this->newLine();
5453
$this->success('✅ Deployment log streaming completed!');
55-
5654
} catch (Exception $e) {
5755
$this->newLine();
5856
$this->error('❌ Streaming failed: '.$e->getMessage());

0 commit comments

Comments
 (0)