From d54667d93be666f46fdd572555d8421e31fc51fd Mon Sep 17 00:00:00 2001 From: jayesh Date: Sun, 1 Mar 2026 09:42:06 +0530 Subject: [PATCH] feat: Add Gitea commit endpoints (getCommit, getLatestCommit) --- src/VCS/Adapter/Git/Gitea.php | 61 ++++++++++++++++++++++-- tests/VCS/Adapter/GiteaTest.php | 83 ++++++++++++++++++++++++++++++++- 2 files changed, 139 insertions(+), 5 deletions(-) diff --git a/src/VCS/Adapter/Git/Gitea.php b/src/VCS/Adapter/Git/Gitea.php index 10fe1b9..de279cd 100644 --- a/src/VCS/Adapter/Git/Gitea.php +++ b/src/VCS/Adapter/Git/Gitea.php @@ -364,16 +364,71 @@ public function listBranches(string $owner, string $repositoryName): array throw new Exception("Not implemented yet"); } + /** + * Get details of a commit using commit hash + * + * @param string $owner Owner name of the repository + * @param string $repositoryName Name of the repository + * @param string $commitHash SHA of the commit + * @return array Details of the commit + */ public function getCommit(string $owner, string $repositoryName, string $commitHash): array { - throw new Exception("Not implemented yet"); + $url = "/repos/{$owner}/{$repositoryName}/git/commits/{$commitHash}"; + + $response = $this->call(self::METHOD_GET, $url, ['Authorization' => "token $this->accessToken"]); + + $statusCode = $response['headers']['status-code'] ?? 0; + if ($statusCode >= 400) { + throw new Exception("Commit not found or inaccessible"); + } + + $body = $response['body'] ?? []; + $commit = $body['commit'] ?? []; + $author = $body['author'] ?? []; + + return [ + 'commitAuthor' => $commit['author']['name'] ?? 'Unknown', + 'commitMessage' => $commit['message'] ?? 'No message', + 'commitAuthorAvatar' => $author['avatar_url'] ?? '', + 'commitAuthorUrl' => $author['html_url'] ?? '', + 'commitHash' => $body['sha'] ?? '', + 'commitUrl' => $body['html_url'] ?? '', + ]; } + /** + * Get latest commit of a branch + * + * @param string $owner Owner name of the repository + * @param string $repositoryName Name of the repository + * @param string $branch Name of the branch + * @return array Details of the commit + */ public function getLatestCommit(string $owner, string $repositoryName, string $branch): array { - throw new Exception("Not implemented yet"); - } + $url = "/repos/{$owner}/{$repositoryName}/commits?sha={$branch}&limit=1"; + + $response = $this->call(self::METHOD_GET, $url, ['Authorization' => "token $this->accessToken"]); + $statusCode = $response['headers']['status-code'] ?? 0; + if ($statusCode >= 400 || empty($response['body'][0])) { + throw new Exception("Latest commit response is missing required information."); + } + + $body = $response['body'][0]; + $commit = $body['commit'] ?? []; + $author = $body['author'] ?? []; + + return [ + 'commitAuthor' => $commit['author']['name'] ?? 'Unknown', + 'commitMessage' => $commit['message'] ?? 'No message', + 'commitHash' => $body['sha'] ?? '', + 'commitUrl' => $body['html_url'] ?? '', + 'commitAuthorAvatar' => $author['avatar_url'] ?? '', + 'commitAuthorUrl' => $author['html_url'] ?? '', + ]; + } public function updateCommitStatus(string $repositoryName, string $commitHash, string $owner, string $state, string $description = '', string $target_url = '', string $context = ''): void { throw new Exception("Not implemented yet"); diff --git a/tests/VCS/Adapter/GiteaTest.php b/tests/VCS/Adapter/GiteaTest.php index 18f30c3..474fa6f 100644 --- a/tests/VCS/Adapter/GiteaTest.php +++ b/tests/VCS/Adapter/GiteaTest.php @@ -365,12 +365,91 @@ public function testUpdateComment(): void public function testGetCommit(): void { - $this->markTestSkipped('Will be implemented in follow-up PR'); + $repositoryName = 'test-get-commit-' . \uniqid(); + $this->vcsAdapter->createRepository(self::$owner, $repositoryName, false); + + // Create a file to generate a commit + $this->vcsAdapter->createFile(self::$owner, $repositoryName, 'README.md', '# Test Commit'); + + // Get the latest commit to get its SHA + $latestCommit = $this->vcsAdapter->getLatestCommit(self::$owner, $repositoryName, 'main'); + $commitHash = $latestCommit['commitHash']; + + // Now test getCommit with that SHA + $result = $this->vcsAdapter->getCommit(self::$owner, $repositoryName, $commitHash); + + $this->assertIsArray($result); + $this->assertArrayHasKey('commitHash', $result); + $this->assertArrayHasKey('commitMessage', $result); + $this->assertArrayHasKey('commitAuthor', $result); + $this->assertArrayHasKey('commitUrl', $result); + $this->assertArrayHasKey('commitAuthorAvatar', $result); + $this->assertArrayHasKey('commitAuthorUrl', $result); + + $this->assertSame($commitHash, $result['commitHash']); + $this->assertNotEmpty($result['commitMessage']); + + $this->vcsAdapter->deleteRepository(self::$owner, $repositoryName); } public function testGetLatestCommit(): void { - $this->markTestSkipped('Will be implemented in follow-up PR'); + $repositoryName = 'test-get-latest-commit-' . \uniqid(); + $this->vcsAdapter->createRepository(self::$owner, $repositoryName, false); + + // Create files to generate commits + $this->vcsAdapter->createFile(self::$owner, $repositoryName, 'README.md', '# Test'); + $this->vcsAdapter->createFile(self::$owner, $repositoryName, 'test.txt', 'test content'); + + $result = $this->vcsAdapter->getLatestCommit(self::$owner, $repositoryName, 'main'); + + $this->assertIsArray($result); + $this->assertArrayHasKey('commitHash', $result); + $this->assertArrayHasKey('commitMessage', $result); + $this->assertArrayHasKey('commitAuthor', $result); + $this->assertArrayHasKey('commitUrl', $result); + $this->assertArrayHasKey('commitAuthorAvatar', $result); + $this->assertArrayHasKey('commitAuthorUrl', $result); + + $this->assertNotEmpty($result['commitHash']); + $this->assertNotEmpty($result['commitAuthor']); + + $this->vcsAdapter->deleteRepository(self::$owner, $repositoryName); + } + + public function testGetCommitWithInvalidSha(): void + { + $repositoryName = 'test-get-commit-invalid-' . \uniqid(); + $this->vcsAdapter->createRepository(self::$owner, $repositoryName, false); + $this->vcsAdapter->createFile(self::$owner, $repositoryName, 'README.md', '# Test'); + + $this->expectException(\Exception::class); + $this->vcsAdapter->getCommit(self::$owner, $repositoryName, 'invalid-sha-12345'); + } + + public function testGetLatestCommitWithInvalidBranch(): void + { + $repositoryName = 'test-get-latest-commit-invalid-' . \uniqid(); + $this->vcsAdapter->createRepository(self::$owner, $repositoryName, false); + $this->vcsAdapter->createFile(self::$owner, $repositoryName, 'README.md', '# Test'); + + $this->expectException(\Exception::class); + $this->vcsAdapter->getLatestCommit(self::$owner, $repositoryName, 'non-existing-branch'); + } + + public function testGetCommitVerifyMessageContent(): void + { + $repositoryName = 'test-commit-message-' . \uniqid(); + $this->vcsAdapter->createRepository(self::$owner, $repositoryName, false); + + $customMessage = 'Custom commit message'; + $this->vcsAdapter->createFile(self::$owner, $repositoryName, 'README.md', '# Test', $customMessage); + + $latestCommit = $this->vcsAdapter->getLatestCommit(self::$owner, $repositoryName, 'main'); + + $this->assertStringContainsString($customMessage, $latestCommit['commitMessage']); + + $this->vcsAdapter->deleteRepository(self::$owner, $repositoryName); } public function testGetEvent(): void