From e99146209e02de0271e00d055094a20ddbd6b425 Mon Sep 17 00:00:00 2001 From: Saeed Vaziry <61919774+saeedvaziry@users.noreply.github.com> Date: Sun, 23 Feb 2025 12:50:46 +0100 Subject: [PATCH] Fix auto-deployment branch (#506) --- .../Controllers/API/GitHookController.php | 3 +- .../AbstractSourceControlProvider.php | 5 + app/SourceControlProviders/Bitbucket.php | 5 + app/SourceControlProviders/Gitlab.php | 5 + .../SourceControlProvider.php | 2 + tests/Feature/ApplicationTest.php | 182 ++++++++++++++++-- 6 files changed, 189 insertions(+), 13 deletions(-) diff --git a/app/Http/Controllers/API/GitHookController.php b/app/Http/Controllers/API/GitHookController.php index 5d254da..dde091a 100644 --- a/app/Http/Controllers/API/GitHookController.php +++ b/app/Http/Controllers/API/GitHookController.php @@ -29,7 +29,8 @@ public function __invoke(Request $request) ->firstOrFail(); foreach ($gitHook->actions as $action) { - if ($action == 'deploy') { + $webhookBranch = $gitHook->site->sourceControl->provider()->getWebhookBranch($request->array()); + if ($action == 'deploy' && $gitHook->site->branch === $webhookBranch) { try { app(Deploy::class)->run($gitHook->site); } catch (SourceControlIsNotConnected) { diff --git a/app/SourceControlProviders/AbstractSourceControlProvider.php b/app/SourceControlProviders/AbstractSourceControlProvider.php index b9492e5..c39c8ff 100755 --- a/app/SourceControlProviders/AbstractSourceControlProvider.php +++ b/app/SourceControlProviders/AbstractSourceControlProvider.php @@ -70,4 +70,9 @@ protected function handleResponseErrors(Response $res, string $repo): void throw new RepositoryPermissionDenied($repo); } } + + public function getWebhookBranch(array $payload): string + { + return str($payload['ref'] ?? '')->after('refs/heads/')->toString(); + } } diff --git a/app/SourceControlProviders/Bitbucket.php b/app/SourceControlProviders/Bitbucket.php index d22da8f..9f13672 100755 --- a/app/SourceControlProviders/Bitbucket.php +++ b/app/SourceControlProviders/Bitbucket.php @@ -183,4 +183,9 @@ private function getAuthenticationHeaders(): array 'Authorization' => 'Basic '.$basicAuth, ]; } + + public function getWebhookBranch(array $payload): string + { + return data_get($payload, 'push.changes.0.new.name', 'default-branch'); + } } diff --git a/app/SourceControlProviders/Gitlab.php b/app/SourceControlProviders/Gitlab.php index 430f0cc..1b661c2 100755 --- a/app/SourceControlProviders/Gitlab.php +++ b/app/SourceControlProviders/Gitlab.php @@ -176,4 +176,9 @@ public function getApiUrl(): string return $host.$this->apiVersion; } + + public function getWebhookBranch(array $payload): string + { + return $payload['ref'] ?? ''; + } } diff --git a/app/SourceControlProviders/SourceControlProvider.php b/app/SourceControlProviders/SourceControlProvider.php index 9c08af2..e692888 100755 --- a/app/SourceControlProviders/SourceControlProvider.php +++ b/app/SourceControlProviders/SourceControlProvider.php @@ -36,4 +36,6 @@ public function getLastCommit(string $repo, string $branch): ?array; * @throws FailedToDeployGitKey */ public function deployKey(string $title, string $repo, string $key): void; + + public function getWebhookBranch(array $payload): string; } diff --git a/tests/Feature/ApplicationTest.php b/tests/Feature/ApplicationTest.php index 5a63c63..117a241 100644 --- a/tests/Feature/ApplicationTest.php +++ b/tests/Feature/ApplicationTest.php @@ -206,19 +206,21 @@ public function test_update_env_file(): void SSH::assertExecutedContains('APP_ENV="production"'); } - public function test_git_hook_deployment(): void + /** + * @dataProvider hookData + */ + public function test_git_hook_deployment(string $provider, array $webhook, string $url, array $payload, bool $skip): void { SSH::fake(); Http::fake([ - 'github.com/*' => Http::response([ - 'sha' => '123', - 'commit' => [ - 'message' => 'test commit message', - 'name' => 'test commit name', - 'email' => 'user@example.com', - 'url' => 'https://github.com', - ], - ], 200), + $url => Http::response($payload), + ]); + + $this->site->update([ + 'branch' => 'main', + ]); + $this->site->sourceControl->update([ + 'provider' => $provider, ]); GitHook::factory()->create([ @@ -233,15 +235,29 @@ public function test_git_hook_deployment(): void 'content' => 'git pull', ]); - $this->post(route('api.git-hooks'), [ + $this->post(route('api.git-hooks', [ 'secret' => 'secret', - ])->assertSessionDoesntHaveErrors(); + ]), $webhook)->assertSessionDoesntHaveErrors(); + + if ($skip) { + $this->assertDatabaseMissing('deployments', [ + 'site_id' => $this->site->id, + 'deployment_script_id' => $this->site->deploymentScript->id, + 'status' => DeploymentStatus::FINISHED, + ]); + + return; + } $this->assertDatabaseHas('deployments', [ 'site_id' => $this->site->id, 'deployment_script_id' => $this->site->deploymentScript->id, 'status' => DeploymentStatus::FINISHED, ]); + + $deployment = $this->site->deployments()->first(); + $this->assertEquals('saeed', $deployment->commit_data['name']); + $this->assertEquals('saeed@vitodeploy.com', $deployment->commit_data['email']); } public function test_git_hook_deployment_invalid_secret(): void @@ -271,4 +287,146 @@ public function test_git_hook_deployment_invalid_secret(): void 'status' => DeploymentStatus::FINISHED, ]); } + + public static function hookData(): array + { + return [ + [ + 'github', + [ + 'ref' => 'refs/heads/main', + ], + 'github.com/*', + [ + 'sha' => '123', + 'commit' => [ + 'committer' => [ + 'name' => 'saeed', + 'email' => 'saeed@vitodeploy.com', + ], + 'message' => 'test commit message', + 'url' => 'https://github.com', + ], + ], + false, + ], + [ + 'github', + [ + 'ref' => 'refs/heads/other-branch', + ], + 'github.com/*', + [ + 'sha' => '123', + 'commit' => [ + 'committer' => [ + 'name' => 'saeed', + 'email' => 'saeed@vitodeploy.com', + ], + 'message' => 'test commit message', + 'url' => 'https://github.com', + ], + ], + true, + ], + [ + 'gitlab', + [ + 'ref' => 'main', + ], + 'gitlab.com/*', + [ + [ + 'id' => '123', + 'committer_name' => 'saeed', + 'committer_email' => 'saeed@vitodeploy.com', + 'title' => 'test', + 'web_url' => 'https://gitlab.com', + ], + ], + false, + ], + [ + 'gitlab', + [ + 'ref' => 'other-branch', + ], + 'gitlab.com/*', + [ + [ + 'id' => '123', + 'committer_name' => 'saeed', + 'committer_email' => 'saeed@vitodeploy.com', + 'title' => 'test', + 'web_url' => 'https://gitlab.com', + ], + ], + true, + ], + [ + 'bitbucket', + [ + 'push' => [ + 'changes' => [ + [ + 'new' => [ + 'name' => 'main', + ], + ], + ], + ], + ], + 'bitbucket.org/*', + [ + 'values' => [ + [ + 'hash' => '123', + 'author' => [ + 'raw' => 'saeed ', + ], + 'message' => 'test', + 'links' => [ + 'html' => [ + 'href' => 'https://bitbucket.org', + ], + ], + ], + ], + ], + false, + ], + [ + 'bitbucket', + [ + 'push' => [ + 'changes' => [ + [ + 'new' => [ + 'name' => 'other-branch', + ], + ], + ], + ], + ], + 'bitbucket.org/*', + [ + 'values' => [ + [ + 'hash' => '123', + 'author' => [ + 'raw' => 'saeed ', + ], + 'message' => 'test', + 'links' => [ + 'html' => [ + 'href' => 'https://bitbucket.org', + ], + ], + ], + ], + ], + true, + ], + ]; + } }