Skip to content

Commit 4c45d13

Browse files
committed
Improve deploy command and add tests
1 parent b389d11 commit 4c45d13

File tree

3 files changed

+92
-23
lines changed

3 files changed

+92
-23
lines changed

src/Console/DeployCommand.php

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22

33
namespace Laravel\Nightwatch\Console;
44

5-
use Exception;
5+
use Carbon\CarbonImmutable;
66
use Illuminate\Console\Command;
7-
use Illuminate\Http\Client\Factory as HttpFactory;
7+
use Illuminate\Support\Facades\Http;
88
use SensitiveParameter;
99
use Symfony\Component\Console\Attribute\AsCommand;
10+
use Throwable;
1011

1112
use function config;
12-
use function now;
13+
use function strlen;
14+
use function substr;
1315

1416
/**
1517
* @internal
@@ -22,51 +24,65 @@ final class DeployCommand extends Command
2224
*/
2325
protected $signature = 'nightwatch:deploy';
2426

25-
protected $hidden = true;
26-
2727
/**
2828
* @var string
2929
*/
3030
protected $description = 'Notify Nightwatch of a deployment.';
3131

32+
/**
33+
* @var bool
34+
*/
35+
protected $hidden = true;
36+
3237
public function __construct(
33-
private HttpFactory $http,
3438
#[SensitiveParameter] private ?string $token,
3539
) {
3640
parent::__construct();
3741
}
3842

39-
public function handle(): void
43+
public function handle(): int
4044
{
41-
$tag = config('nightwatch.deployment') ?? '';
42-
43-
$baseUrl = $_SERVER['NIGHTWATCH_BASE_URL'] ?? 'https://nightwatch.laravel.com';
44-
4545
if (! $this->token) {
46-
$this->error('No Nightwatch token configured.');
46+
$this->error('No NIGHTWATCH_TOKEN environment variable configured.');
4747

48-
return;
48+
return 1;
4949
}
5050

51+
$tag = config('nightwatch.deployment') ?? '';
52+
53+
$baseUrl = $_SERVER['NIGHTWATCH_BASE_URL'] ?? 'https://nightwatch.laravel.com';
54+
5155
try {
52-
$response = $this->http
56+
$response = Http::connectTimeout(5)
57+
->timeout(10)
5358
->withHeaders([
5459
'Authorization' => "Bearer {$this->token}",
5560
'Accept' => 'application/json',
56-
'Content-Type' => 'application/json',
5761
])
5862
->post("{$baseUrl}/api/deployments", [
59-
'timestamp' => now()->timestamp,
63+
'timestamp' => CarbonImmutable::now()->timestamp,
6064
'version' => $tag,
6165
]);
6266

6367
if ($response->successful()) {
6468
$this->info('Deployment successful');
69+
70+
return 0;
6571
} else {
66-
$this->error("Deployment failed: {$response->status()} {$response->body()}");
72+
$message = $response->body();
73+
74+
if (strlen($message) > 1005) {
75+
$message = substr($message, 0, 1000).'[...]';
76+
}
77+
78+
$this->error("Deployment failed: {$response->status()} [{$message}]");
79+
80+
return 1;
6781
}
68-
} catch (Exception $e) {
69-
$this->error("Deployment failed: {$e->getMessage()}");
82+
} catch (Throwable $e) {
83+
$this->error("Deployment failed: [{$e->getMessage()}]");
84+
85+
return 1;
7086
}
7187
}
7288
}

src/NightwatchServiceProvider.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,6 @@ private function registerAgentCommand(): void
231231
private function registerDeployCommand(): void
232232
{
233233
$this->app->singleton(DeployCommand::class, fn () => new DeployCommand(
234-
http: $this->app->make(\Illuminate\Http\Client\Factory::class),
235234
token: $this->nightwatchConfig['token'] ?? null,
236235
));
237236
}

tests/Feature/Console/DeployCommandTest.php

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Tests\Feature\Console;
44

55
use Illuminate\Process\Exceptions\ProcessTimedOutException;
6+
use Illuminate\Support\Facades\Http;
67
use Illuminate\Support\Facades\Process;
78
use RuntimeException;
89
use Tests\TestCase;
@@ -11,11 +12,10 @@
1112

1213
class DeployCommandTest extends TestCase
1314
{
14-
public function test_it_can_run_the_agent_command(): void
15+
public function test_it_can_run_the_deploy_command(): void
1516
{
1617
$output = '';
17-
$process = Process::timeout(10)->start('NIGHTWATCH_TOKEN="test-token" \
18-
NIGHTWATCH_DEPLOY="v1.2.3" \
18+
$process = Process::timeout(10)->start('NIGHTWATCH_DEPLOY="v1.2.3" \
1919
vendor/bin/testbench nightwatch:deploy'
2020
);
2121

@@ -44,4 +44,58 @@ public function test_it_can_run_the_agent_command(): void
4444

4545
$this->assertStringContainsString('Deployment successful', $output);
4646
}
47+
48+
public function test_it_fails_when_the_deploy_command_is_run_without_a_token(): void
49+
{
50+
$process = Process::timeout(10)->start('NIGHTWATCH_DEPLOY="v1.2.3" \
51+
NIGHTWATCH_TOKEN="" \
52+
vendor/bin/testbench nightwatch:deploy');
53+
54+
try {
55+
$process->wait(function ($type, $o) use (&$output, $process) {
56+
$output .= $o;
57+
58+
$process->signal(SIGTERM);
59+
60+
$tries = 0;
61+
62+
while ($tries < 3) {
63+
if (! $process->running()) {
64+
return;
65+
}
66+
67+
$tries++;
68+
sleep(1);
69+
}
70+
71+
$process->signal(SIGKILL);
72+
});
73+
} catch (ProcessTimedOutException $e) {
74+
throw new RuntimeException('Failed to deploy or stop the agent running. Output:'.PHP_EOL.$output, previous: $e);
75+
}
76+
77+
$this->assertStringContainsString('No NIGHTWATCH_TOKEN environment variable configured.', $process->output());
78+
}
79+
80+
public function test_it_handles_http_errors(): void
81+
{
82+
Http::fake([
83+
$_SERVER['NIGHTWATCH_BASE_URL'].'/api/deployments' => Http::response('Whoops!', 500),
84+
]);
85+
86+
$this->artisan('nightwatch:deploy')
87+
->expectsOutput('Deployment failed: 500 [Whoops!]')
88+
->assertExitCode(1);
89+
}
90+
91+
public function test_it_handles_throwable_errors(): void
92+
{
93+
Http::fake([
94+
$_SERVER['NIGHTWATCH_BASE_URL'].'/api/deployments' => Http::failedConnection('Whoops!'),
95+
]);
96+
97+
$this->artisan('nightwatch:deploy')
98+
->expectsOutput('Deployment failed: [Whoops!]')
99+
->assertExitCode(1);
100+
}
47101
}

0 commit comments

Comments
 (0)