-
Notifications
You must be signed in to change notification settings - Fork 4
feat: Add Gitea commit endpoints (getCommit, getLatestCommit) #66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -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<mixed> 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'] ?? '', | ||||||||
| ]; | ||||||||
|
Comment on lines
+377
to
+397
|
||||||||
| } | ||||||||
|
|
||||||||
| /** | ||||||||
| * 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<mixed> 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"; | ||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Encode branch when building the query string.
🔧 Proposed fix- $url = "/repos/{$owner}/{$repositoryName}/commits?sha={$branch}&limit=1";
+ $query = http_build_query([
+ 'sha' => $branch,
+ 'limit' => 1,
+ ]);
+ $url = "/repos/{$owner}/{$repositoryName}/commits?{$query}";🤖 Prompt for AI AgentsThere was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The branch is interpolated directly into the query string, so valid ref names containing query-significant characters (for example Useful? React with 👍 / 👎.
|
||||||||
| $url = "/repos/{$owner}/{$repositoryName}/commits?sha={$branch}&limit=1"; | |
| $encodedBranch = rawurlencode($branch); | |
| $url = "/repos/{$owner}/{$repositoryName}/commits?sha={$encodedBranch}&limit=1"; |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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']); | ||||||||||
|
|
||||||||||
|
Comment on lines
+389
to
+391
|
||||||||||
| $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['commitHash']); | |
| $this->assertNotEmpty($result['commitHash']); | |
| $this->assertNotEmpty($result['commitMessage']); | |
| $this->assertNotEmpty($result['commitUrl']); |
Copilot
AI
Mar 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
testGetCommitWithInvalidSha() creates a repository but never deletes it because the test exits via the expected exception. This can leak repositories across test runs and cause flakiness. Wrap the call in a try/finally (or equivalent) so deleteRepository() always runs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure cleanup runs in exception-path tests.
Both negative tests create repositories but never delete them after the expected exception. Wrap assertions in try/finally so cleanup always executes.
🧹 Proposed fix
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');
+ try {
+ $this->expectException(\Exception::class);
+ $this->vcsAdapter->getCommit(self::$owner, $repositoryName, 'invalid-sha-12345');
+ } finally {
+ $this->vcsAdapter->deleteRepository(self::$owner, $repositoryName);
+ }
}
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');
+ try {
+ $this->expectException(\Exception::class);
+ $this->vcsAdapter->getLatestCommit(self::$owner, $repositoryName, 'non-existing-branch');
+ } finally {
+ $this->vcsAdapter->deleteRepository(self::$owner, $repositoryName);
+ }
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@tests/VCS/Adapter/GiteaTest.php` around lines 420 - 438, The two tests
testGetCommitWithInvalidSha and testGetLatestCommitWithInvalidBranch create
repositories via $this->vcsAdapter->createRepository(...) but never delete them
on the exception path; wrap the assertions that call
$this->vcsAdapter->getCommit(...) and $this->vcsAdapter->getLatestCommit(...) in
try/finally blocks that always call the cleanup method (e.g.
$this->vcsAdapter->deleteRepository(self::$owner, $repositoryName)) in the
finally so the repositoryName created in each test is removed regardless of the
thrown exception.
Copilot
AI
Mar 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
testGetLatestCommitWithInvalidBranch() creates a repository but never deletes it because the test exits via the expected exception. Ensure repository cleanup runs even when the exception is thrown (e.g., try/finally around the call).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getCommitcalls/git/commits/{sha}but then parses the response as if it were the repository commit schema (body['commit']['author']['name'],body['commit']['message']). In Gitea, the git-data commit payload does not carry those nested fields, so valid commits will silently return fallback values like'Unknown'and'No message'instead of real metadata, making this new endpoint functionally incorrect for normal inputs.Useful? React with 👍 / 👎.