-
Notifications
You must be signed in to change notification settings - Fork 0
Add Issue Comments functionality #11
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
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace ConduitUI\Issue\Contracts; | ||
|
|
||
| use ConduitUI\Issue\Data\Comment; | ||
| use ConduitUI\Issue\Data\Reaction; | ||
| use Illuminate\Support\Collection; | ||
|
|
||
| interface ManagesIssueCommentsInterface | ||
| { | ||
| /** | ||
| * @return \Illuminate\Support\Collection<int, \ConduitUI\Issue\Data\Comment> | ||
| */ | ||
| public function listComments(string $owner, string $repo, int $issueNumber): Collection; | ||
|
|
||
| public function getComment(string $owner, string $repo, int $commentId): Comment; | ||
|
|
||
| public function createComment(string $owner, string $repo, int $issueNumber, string $body): Comment; | ||
|
|
||
| public function updateComment(string $owner, string $repo, int $commentId, string $body): Comment; | ||
|
|
||
| public function deleteComment(string $owner, string $repo, int $commentId): bool; | ||
|
|
||
| /** | ||
| * @return \Illuminate\Support\Collection<int, \ConduitUI\Issue\Data\Reaction> | ||
| */ | ||
| public function listCommentReactions(string $owner, string $repo, int $commentId): Collection; | ||
|
|
||
| public function addCommentReaction(string $owner, string $repo, int $commentId, string $content): Reaction; | ||
|
|
||
| public function removeCommentReaction(string $owner, string $repo, int $commentId, int $reactionId): bool; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace ConduitUI\Issue\Data; | ||
|
|
||
| use DateTime; | ||
|
|
||
| readonly class Comment | ||
| { | ||
| public function __construct( | ||
| public int $id, | ||
| public string $body, | ||
| public User $user, | ||
| public DateTime $createdAt, | ||
| public DateTime $updatedAt, | ||
| public string $htmlUrl, | ||
| public string $issueUrl, | ||
| ) {} | ||
|
|
||
| public static function fromArray(array $data): self | ||
| { | ||
| return new self( | ||
| id: $data['id'], | ||
| body: $data['body'], | ||
| user: User::fromArray($data['user']), | ||
| createdAt: new DateTime($data['created_at']), | ||
| updatedAt: new DateTime($data['updated_at']), | ||
| htmlUrl: $data['html_url'], | ||
| issueUrl: $data['issue_url'], | ||
| ); | ||
| } | ||
|
|
||
| public function toArray(): array | ||
| { | ||
| return [ | ||
| 'id' => $this->id, | ||
| 'body' => $this->body, | ||
| 'user' => $this->user->toArray(), | ||
| 'created_at' => $this->createdAt->format('c'), | ||
| 'updated_at' => $this->updatedAt->format('c'), | ||
| 'html_url' => $this->htmlUrl, | ||
| 'issue_url' => $this->issueUrl, | ||
| ]; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace ConduitUI\Issue\Data; | ||
|
|
||
| use DateTime; | ||
|
|
||
| readonly class Reaction | ||
| { | ||
| public function __construct( | ||
| public int $id, | ||
| public string $content, | ||
| public User $user, | ||
| public DateTime $createdAt, | ||
| ) {} | ||
|
|
||
| public static function fromArray(array $data): self | ||
| { | ||
| return new self( | ||
| id: $data['id'], | ||
| content: $data['content'], | ||
| user: User::fromArray($data['user']), | ||
| createdAt: new DateTime($data['created_at']), | ||
| ); | ||
| } | ||
|
|
||
| public function toArray(): array | ||
| { | ||
| return [ | ||
| 'id' => $this->id, | ||
| 'content' => $this->content, | ||
| 'user' => $this->user->toArray(), | ||
| 'created_at' => $this->createdAt->format('c'), | ||
| ]; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace ConduitUI\Issue\Traits; | ||
|
|
||
| use ConduitUI\Issue\Data\Comment; | ||
| use ConduitUI\Issue\Data\Reaction; | ||
| use Illuminate\Support\Collection; | ||
|
|
||
| trait ManagesIssueComments | ||
| { | ||
| /** | ||
| * @return \Illuminate\Support\Collection<int, \ConduitUI\Issue\Data\Comment> | ||
| */ | ||
| public function listComments(string $owner, string $repo, int $issueNumber): Collection | ||
| { | ||
| $response = $this->connector->send( | ||
| $this->connector->get("/repos/{$owner}/{$repo}/issues/{$issueNumber}/comments") | ||
| ); | ||
|
|
||
| return collect($response->json()) | ||
| ->map(fn (array $data) => Comment::fromArray($data)); | ||
| } | ||
|
|
||
| public function getComment(string $owner, string $repo, int $commentId): Comment | ||
| { | ||
| $response = $this->connector->send( | ||
| $this->connector->get("/repos/{$owner}/{$repo}/issues/comments/{$commentId}") | ||
| ); | ||
|
|
||
| return Comment::fromArray($response->json()); | ||
| } | ||
|
|
||
| public function createComment(string $owner, string $repo, int $issueNumber, string $body): Comment | ||
| { | ||
| $response = $this->connector->send( | ||
| $this->connector->post("/repos/{$owner}/{$repo}/issues/{$issueNumber}/comments", [ | ||
| 'body' => $body, | ||
| ]) | ||
| ); | ||
|
|
||
| return Comment::fromArray($response->json()); | ||
| } | ||
|
|
||
| public function updateComment(string $owner, string $repo, int $commentId, string $body): Comment | ||
| { | ||
| $response = $this->connector->send( | ||
| $this->connector->patch("/repos/{$owner}/{$repo}/issues/comments/{$commentId}", [ | ||
| 'body' => $body, | ||
| ]) | ||
| ); | ||
|
|
||
| return Comment::fromArray($response->json()); | ||
| } | ||
|
|
||
| public function deleteComment(string $owner, string $repo, int $commentId): bool | ||
| { | ||
| $response = $this->connector->send( | ||
| $this->connector->delete("/repos/{$owner}/{$repo}/issues/comments/{$commentId}") | ||
| ); | ||
|
|
||
| return $response->successful(); | ||
| } | ||
|
|
||
| /** | ||
| * @return \Illuminate\Support\Collection<int, \ConduitUI\Issue\Data\Reaction> | ||
| */ | ||
| public function listCommentReactions(string $owner, string $repo, int $commentId): Collection | ||
| { | ||
| $response = $this->connector->send( | ||
| $this->connector->get("/repos/{$owner}/{$repo}/issues/comments/{$commentId}/reactions") | ||
| ); | ||
|
|
||
| return collect($response->json()) | ||
| ->map(fn (array $data) => Reaction::fromArray($data)); | ||
| } | ||
|
|
||
| public function addCommentReaction(string $owner, string $repo, int $commentId, string $content): Reaction | ||
| { | ||
| $response = $this->connector->send( | ||
| $this->connector->post("/repos/{$owner}/{$repo}/issues/comments/{$commentId}/reactions", [ | ||
| 'content' => $content, | ||
| ]) | ||
| ); | ||
|
|
||
| return Reaction::fromArray($response->json()); | ||
| } | ||
|
|
||
| public function removeCommentReaction(string $owner, string $repo, int $commentId, int $reactionId): bool | ||
| { | ||
| $response = $this->connector->send( | ||
| $this->connector->delete("/repos/{$owner}/{$repo}/issues/comments/{$commentId}/reactions/{$reactionId}") | ||
| ); | ||
|
|
||
| return $response->successful(); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| use ConduitUI\Issue\Data\Comment; | ||
| use ConduitUI\Issue\Data\User; | ||
|
|
||
| test('can create comment from array', function () { | ||
| $data = [ | ||
| 'id' => 123, | ||
| 'body' => 'This is a test comment', | ||
| 'user' => [ | ||
| 'id' => 456, | ||
| 'login' => 'testuser', | ||
| 'avatar_url' => 'https://github.com/testuser.png', | ||
| 'html_url' => 'https://github.com/testuser', | ||
| 'type' => 'User', | ||
| ], | ||
| 'created_at' => '2023-01-01T12:00:00Z', | ||
| 'updated_at' => '2023-01-02T12:00:00Z', | ||
| 'html_url' => 'https://github.com/owner/repo/issues/comments/123', | ||
| 'issue_url' => 'https://api.github.com/repos/owner/repo/issues/1', | ||
| ]; | ||
|
|
||
| $comment = Comment::fromArray($data); | ||
|
|
||
| expect($comment->id)->toBe(123); | ||
| expect($comment->body)->toBe('This is a test comment'); | ||
| expect($comment->user)->toBeInstanceOf(User::class); | ||
| expect($comment->user->login)->toBe('testuser'); | ||
| expect($comment->htmlUrl)->toBe('https://github.com/owner/repo/issues/comments/123'); | ||
| expect($comment->issueUrl)->toBe('https://api.github.com/repos/owner/repo/issues/1'); | ||
| }); | ||
|
|
||
| test('can convert comment to array', function () { | ||
| $user = new User(456, 'testuser', 'https://github.com/testuser.png', 'https://github.com/testuser', 'User'); | ||
|
|
||
| $comment = new Comment( | ||
| id: 123, | ||
| body: 'This is a test comment', | ||
| user: $user, | ||
| createdAt: new DateTime('2023-01-01T12:00:00Z'), | ||
| updatedAt: new DateTime('2023-01-02T12:00:00Z'), | ||
| htmlUrl: 'https://github.com/owner/repo/issues/comments/123', | ||
| issueUrl: 'https://api.github.com/repos/owner/repo/issues/1', | ||
| ); | ||
|
|
||
| $array = $comment->toArray(); | ||
|
|
||
| expect($array['id'])->toBe(123); | ||
| expect($array['body'])->toBe('This is a test comment'); | ||
| expect($array['user'])->toBeArray(); | ||
| expect($array['user']['login'])->toBe('testuser'); | ||
| expect($array['html_url'])->toBe('https://github.com/owner/repo/issues/comments/123'); | ||
| expect($array['issue_url'])->toBe('https://api.github.com/repos/owner/repo/issues/1'); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| use ConduitUI\Issue\Data\Reaction; | ||
| use ConduitUI\Issue\Data\User; | ||
|
|
||
| test('can create reaction from array', function () { | ||
| $data = [ | ||
| 'id' => 123, | ||
| 'content' => '+1', | ||
| 'user' => [ | ||
| 'id' => 456, | ||
| 'login' => 'testuser', | ||
| 'avatar_url' => 'https://github.com/testuser.png', | ||
| 'html_url' => 'https://github.com/testuser', | ||
| 'type' => 'User', | ||
| ], | ||
| 'created_at' => '2023-01-01T12:00:00Z', | ||
| ]; | ||
|
|
||
| $reaction = Reaction::fromArray($data); | ||
|
|
||
| expect($reaction->id)->toBe(123); | ||
| expect($reaction->content)->toBe('+1'); | ||
| expect($reaction->user)->toBeInstanceOf(User::class); | ||
| expect($reaction->user->login)->toBe('testuser'); | ||
| }); | ||
|
|
||
| test('can convert reaction to array', function () { | ||
| $user = new User(456, 'testuser', 'https://github.com/testuser.png', 'https://github.com/testuser', 'User'); | ||
|
|
||
| $reaction = new Reaction( | ||
| id: 123, | ||
| content: '+1', | ||
| user: $user, | ||
| createdAt: new DateTime('2023-01-01T12:00:00Z'), | ||
| ); | ||
|
|
||
| $array = $reaction->toArray(); | ||
|
|
||
| expect($array['id'])->toBe(123); | ||
| expect($array['content'])->toBe('+1'); | ||
| expect($array['user'])->toBeArray(); | ||
| expect($array['user']['login'])->toBe('testuser'); | ||
| }); | ||
|
|
||
| test('supports various reaction types', function (string $content) { | ||
| $user = new User(456, 'testuser', 'https://github.com/testuser.png', 'https://github.com/testuser', 'User'); | ||
|
|
||
| $reaction = new Reaction( | ||
| id: 123, | ||
| content: $content, | ||
| user: $user, | ||
| createdAt: new DateTime('2023-01-01T12:00:00Z'), | ||
| ); | ||
|
|
||
| expect($reaction->content)->toBe($content); | ||
| })->with([ | ||
| '+1', | ||
| '-1', | ||
| 'laugh', | ||
| 'confused', | ||
| 'heart', | ||
| 'hooray', | ||
| 'rocket', | ||
| 'eyes', | ||
| ]); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
🧩 Analysis chain
🌐 Web query:
GitHub REST API "List issue comments" endpoint per_page page pagination parameters💡 Result:
Endpoint: GET /repos/{owner}/{repo}/issues/{issue_number}/comments. [1]
Pagination query params:
How to iterate: responses include a Link header (rel="next", rel="last", etc.) to follow additional pages; you can also request specific pages via ?per_page=NN&page=MM. [2]
Example: GET https://api.github.com/repos/OWNER/REPO/issues/123/comments?per_page=100&page=2. [1][2]
Sources:
[1] GitHub REST API — List issue comments (issues/comments) (GitHub Docs).
[2] Using pagination in the REST API (GitHub Docs).
🏁 Script executed:
Repository: conduit-ui/issue
Length of output: 42
🏁 Script executed:
Repository: conduit-ui/issue
Length of output: 42
🏁 Script executed:
Repository: conduit-ui/issue
Length of output: 42
🏁 Script executed:
# Show fd connector output fd connector -t fRepository: conduit-ui/issue
Length of output: 42
🏁 Script executed:
Repository: conduit-ui/issue
Length of output: 42
🏁 Script executed:
Repository: conduit-ui/issue
Length of output: 42
🏁 Script executed:
Repository: conduit-ui/issue
Length of output: 846
🏁 Script executed:
Repository: conduit-ui/issue
Length of output: 2847
🏁 Script executed:
Repository: conduit-ui/issue
Length of output: 230
🏁 Script executed:
Repository: conduit-ui/issue
Length of output: 3253
🏁 Script executed:
Repository: conduit-ui/issue
Length of output: 2747
List comments and list comment reactions need pagination support—consumers will silently miss data beyond the first page.
GitHub's "list issue comments" and "list comment reactions" endpoints are paginated with
per_page(default: 30, max: 100) andpage(default: 1) query parameters. BothlistComments()andlistCommentReactions()currently lack pagination parameters, so callers cannot request additional pages or customize page size.Update both methods to accept pagination parameters, for example:
Apply the same change to
listCommentReactions(). Also update theManagesIssueCommentsInterfacecontract to reflect these new parameters.🤖 Prompt for AI Agents