Add get_issue_comments method to GitLabService (#10361)

Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
Tim O'Farrell 2025-08-15 14:55:39 -06:00 committed by GitHub
parent 587b4c311a
commit daec23b5d7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 85 additions and 0 deletions

View File

@ -1,4 +1,5 @@
import os
from datetime import datetime
from typing import Any
import httpx
@ -7,6 +8,7 @@ from pydantic import SecretStr
from openhands.integrations.service_types import (
BaseGitService,
Branch,
Comment,
GitService,
OwnerType,
ProviderType,
@ -673,6 +675,80 @@ class GitLabService(BaseGitService, GitService):
# Parse the content to extract triggers from frontmatter
return self._parse_microagent_content(response, file_path)
async def get_issue_comments(
self, project_id: str, issue_iid: int, limit: int = 100
) -> list[Comment]:
"""Get the last n comments for a specific issue.
Args:
project_id: The GitLab project ID (can be numeric ID or URL-encoded path)
issue_iid: The issue internal ID (iid) in GitLab
limit: Maximum number of comments to retrieve (default: 100)
Returns:
List of Comment objects, ordered by creation date (newest first)
Raises:
UnknownException: If the request fails or the issue is not found
"""
# URL-encode the project_id if it contains special characters
if '/' in str(project_id):
encoded_project_id = str(project_id).replace('/', '%2F')
else:
encoded_project_id = str(project_id)
url = f'{self.BASE_URL}/projects/{encoded_project_id}/issues/{issue_iid}/notes'
all_comments: list[Comment] = []
page = 1
per_page = min(limit, 100) # GitLab API max per_page is 100
while len(all_comments) < limit:
# Get comments with pagination, ordered by creation date descending
params = {
'per_page': per_page,
'page': page,
'order_by': 'created_at',
'sort': 'desc', # Get newest comments first
}
response, headers = await self._make_request(url, params)
if not response: # No more comments
break
# Filter out system comments and convert to Comment objects
for comment_data in response:
if len(all_comments) >= limit:
break
# Skip system-generated comments unless explicitly requested
if comment_data.get('system', False):
continue
comment = Comment(
id=comment_data['id'],
body=comment_data['body'],
author=comment_data.get('author', {}).get('username', 'unknown'),
created_at=datetime.fromisoformat(
comment_data['created_at'].replace('Z', '+00:00')
),
updated_at=datetime.fromisoformat(
comment_data['updated_at'].replace('Z', '+00:00')
),
system=comment_data.get('system', False),
)
all_comments.append(comment)
# Check if we have more pages
link_header = headers.get('Link', '')
if 'rel="next"' not in link_header or len(all_comments) >= limit:
break
page += 1
return all_comments
gitlab_service_cls = os.environ.get(
'OPENHANDS_GITLAB_SERVICE_CLS',

View File

@ -140,6 +140,15 @@ class Repository(BaseModel):
main_branch: str | None = None # The main/default branch of the repository
class Comment(BaseModel):
id: int
body: str
author: str
created_at: datetime
updated_at: datetime
system: bool = False # Whether this is a system-generated comment
class AuthenticationError(ValueError):
"""Raised when there is an issue with GitHub authentication."""