Skip to content

feat: Add Gitea pull request and comment endpoints#68

Merged
Meldiron merged 9 commits intoutopia-php:mainfrom
jaysomani:feat/gitea-pull-request-endpoints
Mar 18, 2026
Merged

feat: Add Gitea pull request and comment endpoints#68
Meldiron merged 9 commits intoutopia-php:mainfrom
jaysomani:feat/gitea-pull-request-endpoints

Conversation

@jaysomani
Copy link
Contributor

@jaysomani jaysomani commented Mar 9, 2026

  • Implement getPullRequest to fetch PR details
  • Implement getPullRequestFromBranch to find PR by branch name
  • Implement createPullRequest to create new PRs
  • Implement createComment, getComment, updateComment for PR comments
  • Add comprehensive tests with full workflow coverage
  • Add edge case tests for invalid inputs
  • Follow PR fix: Ensure installation ID is set correctly in GitHub payload handling #64 null safety pattern

Tests: 7 new tests, all passing

Summary by CodeRabbit

  • New Features

    • Pull request management now fully supported—create, retrieve, and update capabilities enabled
    • Comment operations on pull requests enhanced with full create, fetch, and update functionality
    • Added ability to locate pull requests by branch reference
    • File creation now supports specifying a branch and returns errors for failed uploads
  • Tests

    • Comprehensive test coverage added for pull request and comment workflows, including error scenarios

- Implement getPullRequest to fetch PR details
- Implement getPullRequestFromBranch to find PR by branch name
- Implement createPullRequest to create new PRs
- Implement createComment, getComment, updateComment for PR comments
- Add comprehensive tests with full workflow coverage
- Add edge case tests for invalid inputs
- Follow PR utopia-php#64 null safety pattern

Tests: 7 new tests, all passing
@coderabbitai
Copy link

coderabbitai bot commented Mar 9, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 08342c23-e3c2-4ade-b986-64402566f770

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

The Gitea VCS adapter was extended: createFile signature now accepts an optional branch and throws on HTTP ≥400; createPullRequest was added; createComment now validates responses and returns comment IDs; getComment, updateComment, getPullRequest, and getPullRequestFromBranch were implemented to fetch/update PRs and comments. Tests were added/expanded in tests/VCS/Adapter/GiteaTest.php with multiple new cases covering PR and comment workflows, error paths, and branch-based PR retrieval.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: implementing Gitea pull request and comment endpoints (createPullRequest, getPullRequest, getPullRequestFromBranch, createComment, getComment, updateComment).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can use OpenGrep to find security vulnerabilities and bugs across 17+ programming languages.

OpenGrep is compatible with Semgrep configurations. Add an opengrep.yml or semgrep.yml configuration file to your project to enable OpenGrep analysis.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3277ea7614

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/VCS/Adapter/GiteaTest.php (1)

106-116: These PR tests never add a commit to the head branch.

Lines 106-108 and the same pattern in the other PR tests create a feature branch, but the subsequent createFile() calls still write to the default branch. src/VCS/Adapter/Git/Gitea.php's createFile() payload has no branch/ref field, so these cases are not actually exercising a branch with head-only changes and can get flaky if Gitea rejects no-op PRs.

I’d either extend createFile() to accept a branch/ref for tests, or create the feature-branch commit through the contents API directly before opening the PR.

Also applies to: 152-163, 448-463, 665-676

🤖 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 106 - 116, The tests create a
branch with createBranch() but then call createFile() which currently writes to
the default branch (Gitea::createFile lacks a branch/ref), so the PR head has no
commits; update the tests by either (A) extending createFile() to accept an
optional branch/ref parameter and using that when creating test files on
'comment-test' (and adjust the Gitea adapter implementation to include the ref
in the payload), or (B) create the branch commit directly via the Gitea contents
API before calling createPullRequest(); apply the chosen approach consistently
for the other failing tests that use createBranch() + createFile() (the blocks
around lines referenced).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/VCS/Adapter/Git/Gitea.php`:
- Around line 449-464: The current call builds $url with
"?state=open&sort=recentupdate&limit=1" and then filters $responseBody for the
branch, which can miss PRs; remove the "limit=1" (or replace with a server-side
head filter if Gitea supports it) so the API returns all matching open PRs, then
keep the existing loop over $responseBody ($response, $responseBody, $prHead,
$prHeadRef) to find the PR whose head ref equals $branch and return it; ensure
you still handle an empty result by returning [].

---

Nitpick comments:
In `@tests/VCS/Adapter/GiteaTest.php`:
- Around line 106-116: The tests create a branch with createBranch() but then
call createFile() which currently writes to the default branch
(Gitea::createFile lacks a branch/ref), so the PR head has no commits; update
the tests by either (A) extending createFile() to accept an optional branch/ref
parameter and using that when creating test files on 'comment-test' (and adjust
the Gitea adapter implementation to include the ref in the payload), or (B)
create the branch commit directly via the Gitea contents API before calling
createPullRequest(); apply the chosen approach consistently for the other
failing tests that use createBranch() + createFile() (the blocks around lines
referenced).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ff55d472-6fd1-4ebf-86db-9d78ff264369

📥 Commits

Reviewing files that changed from the base of the PR and between 907a3c6 and 3277ea7.

📒 Files selected for processing (2)
  • src/VCS/Adapter/Git/Gitea.php
  • tests/VCS/Adapter/GiteaTest.php

- Remove limit=1 from getPullRequestFromBranch to fetch all PRs
- Add branch parameter to createFile for branch-specific commits
- Update tests to commit files to feature branches
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
tests/VCS/Adapter/GiteaTest.php (2)

101-145: Always delete the test repo in finally.

This test creates remote state and only cleans it up on the happy path. Any failed assertion or API error before Line 144 leaks repositories into the shared Gitea instance and can make later runs flaky.

♻️ Suggested cleanup pattern
     public function testCommentWorkflow(): void
     {
         $repositoryName = 'test-comment-workflow-' . \uniqid();
-        $this->vcsAdapter->createRepository(self::$owner, $repositoryName, false);
-
-        $this->vcsAdapter->createFile(self::$owner, $repositoryName, 'README.md', '# Test');
-        $this->vcsAdapter->createBranch(self::$owner, $repositoryName, 'comment-test', 'main');
-        $this->vcsAdapter->createFile(self::$owner, $repositoryName, 'test.txt', 'test', 'Add test file', 'comment-test');
-
-        $pr = $this->vcsAdapter->createPullRequest(
-            self::$owner,
-            $repositoryName,
-            'Comment Test PR',
-            'comment-test',
-            'main'
-        );
+        $this->vcsAdapter->createRepository(self::$owner, $repositoryName, false);
+
+        try {
+            $this->vcsAdapter->createFile(self::$owner, $repositoryName, 'README.md', '# Test');
+            $this->vcsAdapter->createBranch(self::$owner, $repositoryName, 'comment-test', 'main');
+            $this->vcsAdapter->createFile(self::$owner, $repositoryName, 'test.txt', 'test', 'Add test file', 'comment-test');
+
+            $pr = $this->vcsAdapter->createPullRequest(
+                self::$owner,
+                $repositoryName,
+                'Comment Test PR',
+                'comment-test',
+                'main'
+            );
 
-        $prNumber = $pr['number'] ?? 0;
-        $this->assertGreaterThan(0, $prNumber);
+            $prNumber = $pr['number'] ?? 0;
+            $this->assertGreaterThan(0, $prNumber);
 
-        $originalComment = 'This is a test comment';
-        $commentId = $this->vcsAdapter->createComment(self::$owner, $repositoryName, $prNumber, $originalComment);
+            $originalComment = 'This is a test comment';
+            $commentId = $this->vcsAdapter->createComment(self::$owner, $repositoryName, $prNumber, $originalComment);
 
-        $this->assertNotEmpty($commentId);
-        $this->assertIsString($commentId);
+            $this->assertNotEmpty($commentId);
+            $this->assertIsString($commentId);
 
-        $retrievedComment = $this->vcsAdapter->getComment(self::$owner, $repositoryName, $commentId);
-        $this->assertSame($originalComment, $retrievedComment);
+            $retrievedComment = $this->vcsAdapter->getComment(self::$owner, $repositoryName, $commentId);
+            $this->assertSame($originalComment, $retrievedComment);
+        } finally {
+            $this->vcsAdapter->deleteRepository(self::$owner, $repositoryName);
+        }
-
-        $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 101 - 145, The
testCommentWorkflow method currently only deletes the created repository on the
happy path; wrap the main test logic in a try/finally so the cleanup always
runs: declare repositoryName as you already do, then enclose creation/assertions
(calls to createRepository, createFile, createBranch, createPullRequest,
createComment, getComment, updateComment, etc.) in a try block and call
$this->vcsAdapter->deleteRepository(self::$owner, $repositoryName) inside a
finally block to ensure the repo is removed even on failures.

193-205: Make the invalid-case tests assert one concrete contract.

These tests currently pass on any string/array, including raw Gitea error payloads, so they do not lock in the adapter’s not-found behavior. Assert a specific outcome ('' / [] or expectException()), not just the type.

Also applies to: 481-493

🤖 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 193 - 205, The test
testGetCommentInvalidId currently only asserts the return is a string allowing
raw API errors; update it (and the similar tests around the other block) to
assert a single concrete contract for the "not found" case: either
assertSame('', $result) if adapter should return an empty string, or change the
test to expectException(...) if the adapter should throw; locate and modify the
call to getComment in testGetCommentInvalidId (and the analogous tests) and
replace the loose assertIsString/assertIsArray with a specific assertion
matching the adapter's intended behavior, keeping
createRepository/createFile/deleteRepository setup/teardown intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/VCS/Adapter/Git/Gitea.php`:
- Around line 191-203: The Gitea adapter added an optional $branch parameter to
Gitea::createFile(string $owner, string $repositoryName, string $filepath,
string $content, string $message = 'Add file', string $branch = '') but the
abstract Git::createFile() contract still defines only five parameters; make the
branch behavior part of the shared contract by updating the abstract method
signature in Git::createFile to accept the optional sixth parameter (string
$branch = '') and then update all concrete implementations and any call sites to
accept/forward this optional $branch argument (or alternatively add a new
branch-aware method on Git if you prefer to keep the old signature, ensuring
Git::createFile remains unchanged and adding e.g. createFileOnBranch with the
same parameters used in Gitea::createFile).
- Around line 456-471: Replace the paginated list fetch with a direct PR lookup
using Gitea's dedicated endpoint: construct the URL
"/repos/{$owner}/{$repositoryName}/pulls/{$targetBranch}/{$branch}" (using the
current target/base branch variable and the source $branch), call
$this->call(self::METHOD_GET, $url, ['Authorization' => "token
$this->accessToken"]), then parse the returned response body and return the PR
if present (or [] on not-found/error). Update the logic that currently iterates
$responseBody/$prHeadRef to instead use this single-call flow so pagination is
avoided.
- Around line 382-391: The createPullRequest() and getPullRequest() methods
currently return $response['body'] without checking HTTP status, so non-2xx
responses (e.g. 422/404/401) propagate error payloads; update both methods to
mirror the existing pattern used in createBranch()/createFile(): read $status =
$response['status'], if $status is not in the expected 2xx range then
throw/return an error (include the response body/message) or call the same error
handling routine used elsewhere, otherwise return $response['body']; reference
the createPullRequest(), getPullRequest(), $response['status'] and
$response['body'] symbols and reuse the same guard logic already implemented for
createBranch()/createFile().

---

Nitpick comments:
In `@tests/VCS/Adapter/GiteaTest.php`:
- Around line 101-145: The testCommentWorkflow method currently only deletes the
created repository on the happy path; wrap the main test logic in a try/finally
so the cleanup always runs: declare repositoryName as you already do, then
enclose creation/assertions (calls to createRepository, createFile,
createBranch, createPullRequest, createComment, getComment, updateComment, etc.)
in a try block and call $this->vcsAdapter->deleteRepository(self::$owner,
$repositoryName) inside a finally block to ensure the repo is removed even on
failures.
- Around line 193-205: The test testGetCommentInvalidId currently only asserts
the return is a string allowing raw API errors; update it (and the similar tests
around the other block) to assert a single concrete contract for the "not found"
case: either assertSame('', $result) if adapter should return an empty string,
or change the test to expectException(...) if the adapter should throw; locate
and modify the call to getComment in testGetCommentInvalidId (and the analogous
tests) and replace the loose assertIsString/assertIsArray with a specific
assertion matching the adapter's intended behavior, keeping
createRepository/createFile/deleteRepository setup/teardown intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f8ed472e-7adc-479f-84ea-6a2939c54353

📥 Commits

Reviewing files that changed from the base of the PR and between 3277ea7 and 4b9c470.

📒 Files selected for processing (2)
  • src/VCS/Adapter/Git/Gitea.php
  • tests/VCS/Adapter/GiteaTest.php

- Add HTTP status checks to createPullRequest and getPullRequest
- Add try/finally blocks to tests for proper cleanup on failures
- Make error test assertions concrete (empty string or exception)
- Improve testGetPullRequestWithInvalidNumber to use try/finally

Note: Issue utopia-php#1 (adding branch parameter to abstract Git::createFile)
requires architectural decision - will address after maintainer feedback
@Meldiron Meldiron requested a review from Copilot March 16, 2026 10:00
@Meldiron Meldiron added the test Enables E2E tests in CI/CD label Mar 16, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Gitea adapter support for pull-request and pull-request-comment workflows, and expands the Gitea test suite to cover those new endpoints end-to-end.

Changes:

  • Add Gitea API methods to create PRs, fetch PR details, and locate an open PR by source branch.
  • Implement PR comment create/get/update endpoints for Gitea.
  • Update createFile to optionally target a specific branch and add integration tests covering PR + comment workflows and error cases.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.

File Description
src/VCS/Adapter/Git/Gitea.php Adds PR/comment endpoints and extends file creation with an optional branch payload field.
tests/VCS/Adapter/GiteaTest.php Adds integration tests for PR and comment workflows, plus invalid-input scenarios.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@jaysomani jaysomani force-pushed the feat/gitea-pull-request-endpoints branch from 51603f0 to 3bb14cb Compare March 17, 2026 08:55
@Meldiron Meldiron added test Enables E2E tests in CI/CD and removed test Enables E2E tests in CI/CD labels Mar 17, 2026
Your Name and others added 2 commits March 18, 2026 21:32
Co-authored-by: Matej Bačo <matejbaco2000@gmail.com>
@Meldiron Meldiron added test Enables E2E tests in CI/CD and removed test Enables E2E tests in CI/CD labels Mar 18, 2026
@greptile-apps
Copy link

greptile-apps bot commented Mar 18, 2026

Greptile Summary

This PR implements Gitea pull request and comment management endpoints (createPullRequest, getPullRequest, getPullRequestFromBranch, createComment, getComment, updateComment), adds $branch support to createFile for both Gitea and GitHub, and stubs createPullRequest on the GitHub adapter. It also extends the abstract Git base class with the new createPullRequest signature and adds 7 integration tests.

Key issues found:

  • createComment and updateComment (Gitea.php): Both methods skip HTTP status code validation before inspecting the response body. An API error (e.g., 404 for an invalid PR) will surface as the misleading "Comment creation/update response is missing comment ID." rather than an actionable HTTP error. All other methods in this file check the status code first.
  • getPullRequestFromBranch (Gitea.php): Only fetches the first page of open PRs and filters client-side. For repositories with many open PRs, the target PR can silently go missing. The Gitea API supports a head query parameter for server-side branch filtering (mirroring the GitHub adapter's approach), which should be used instead.
  • testGetPullRequestWithInvalidNumber (GiteaTest.php): A second deleteRepository call appears after the try-finally block (line 489). It is unreachable when the expected exception is thrown (since the exception propagates through the finally), but if the exception is somehow absent the test would fail with a confusing "repository not found" error from the duplicate delete, obscuring the real expectException failure.

Confidence Score: 3/5

  • This PR has several logic gaps in the Gitea adapter that should be addressed before merging.
  • The core feature work is solid and the overall structure follows existing patterns, but three logic issues lower confidence: missing HTTP status checks in createComment/updateComment that produce misleading exceptions, a pagination gap in getPullRequestFromBranch that silently misses PRs in busy repos, and a duplicate cleanup call in a test that can generate confusing failures. None are critical blockers individually, but together they represent a consistent gap in defensive error handling that has been established as the pattern elsewhere in the file.
  • src/VCS/Adapter/Git/Gitea.php (comment methods and getPullRequestFromBranch) and tests/VCS/Adapter/GiteaTest.php (testGetPullRequestWithInvalidNumber).

Important Files Changed

Filename Overview
src/VCS/Adapter/Git/Gitea.php Implements createPullRequest, getPullRequest, getPullRequestFromBranch, createComment, getComment, and updateComment for Gitea; createComment and updateComment are missing HTTP status checks before body inspection, and getPullRequestFromBranch only iterates the first page of results.
src/VCS/Adapter/Git/GitHub.php Implements createFile with branch support and stubs createPullRequest as not-yet-implemented; the changes are straightforward and correct with proper error handling.
src/VCS/Adapter/Git.php Adds $branch parameter to createFile abstract signature and a new createPullRequest abstract method; straightforward and safe interface update.
tests/VCS/Adapter/GiteaTest.php Adds 7 new integration tests covering PR and comment workflows; testGetPullRequestWithInvalidNumber has a redundant deleteRepository call after the try-finally block that is dead code in the success path but would cause a confusing failure in the error path.

Last reviewed commit: "Apply suggestions fr..."

@Meldiron Meldiron added test Enables E2E tests in CI/CD and removed test Enables E2E tests in CI/CD labels Mar 18, 2026
@Meldiron Meldiron added test Enables E2E tests in CI/CD and removed test Enables E2E tests in CI/CD labels Mar 18, 2026
@Meldiron Meldiron merged commit 9201e5b into utopia-php:main Mar 18, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test Enables E2E tests in CI/CD

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants