Skip to content
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

Feat/gitbal catalog #61

Merged
merged 47 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
e83a5c9
Tech: Refactored action to support multiple Git providers (GitHub, Gi…
utsmannn Jan 29, 2025
b5e3e15
Tech: Introduced GitLab CI support, added configuration model, refact…
utsmannn Jan 29, 2025
1525078
Tech: Refined GitLab CI rules for merge requests, ensuring pipeline e…
utsmannn Jan 29, 2025
3d10ea5
Tech: Migrated GitLab CI config to root level, renaming gitlab-ci.yml…
utsmannn Jan 29, 2025
8b14894
Tech: Updated GitLab CI config, utilizing environment variables for A…
utsmannn Jan 29, 2025
7536be7
Tech: Updated GitLab CI to use src.main-gitlab, utilizing env vars fo…
utsmannn Jan 29, 2025
456eba7
Tech: Enhanced GitLab CI with GITLAB_TOKEN and CI_PROJECT_ID, ensurin…
utsmannn Jan 29, 2025
de7d116
Tech: Updated GitLab CI config to use CI_JOB_TOKEN instead of GITLAB_…
utsmannn Jan 29, 2025
de363b3
Tech: Modified GitLab CI to use '$GITLAB_TOKEN' and '$CI_PROJECT_ID' …
utsmannn Jan 29, 2025
caf8082
Tech: Modified GitLab CI to utilize direct env vars for GITLAB_TOKEN …
utsmannn Jan 29, 2025
9db2c7b
Tech: Updated GitLab CI to utilize '$GITLAB_CI_TOKEN' for secure API …
utsmannn Jan 29, 2025
378fddb
Tech: Enhanced GitLab CI script by adding project ID, GITLAB_CI_TOKEN…
utsmannn Jan 29, 2025
e596684
Tech: Modified GitLab CI script to echo CI_PROJECT_ID, GITLAB_CI_TOKE…
utsmannn Jan 29, 2025
54c4049
Tech: Refined GitLab CI script output, displaying project ID, CI toke…
utsmannn Jan 29, 2025
4c0d4e5
Tech: Enhanced GitLab CI script by removing direct echo of credential…
utsmannn Jan 29, 2025
cd381a8
Tech: Modified GitLab CI script to display environment variables usin…
utsmannn Jan 29, 2025
38ae058
Tech: Enhanced GitLab CI script, displaying API key and CI token with…
utsmannn Jan 29, 2025
23b7bf4
Tech: Enhanced GitLab CI script output with custom variable echos for…
utsmannn Jan 29, 2025
bf13d72
Tech: Modified GitLab CI script to enhance debugging with labeled cus…
utsmannn Jan 29, 2025
3991722
Tech: Modified GitLab CI config, removed direct variable assignment, …
utsmannn Jan 29, 2025
acdb859
Tech: Modified GitLab CI config to assign 'GITLAB_CI_TOKEN', 'CI_PROJ…
utsmannn Jan 29, 2025
e503c6f
Tech: Refined GitLab CI script, removing direct variable echos and ma…
utsmannn Jan 29, 2025
0b1e95c
Tech: Enhanced GitLab diff handling to include base, start, and head …
utsmannn Jan 29, 2025
a2ebc01
Tech: Modified GitLab comment creation to include base, start, and he…
utsmannn Jan 29, 2025
16d9e62
Tech: Enhanced GitLab comment creation with debug logging and file po…
utsmannn Jan 29, 2025
de1927b
Tech: Enhanced PR reviewer's duplicate comment detection by comparing…
utsmannn Jan 29, 2025
97b72e2
Tech: Enhanced PR reviewer's duplicate comment detection by adding de…
utsmannn Jan 29, 2025
6529916
Tech: Refined GitLab comment retrieval to fetch all discussions with …
utsmannn Jan 29, 2025
ebc146a
Tech: Enhanced GitLab comment creation by removing redundant position…
utsmannn Jan 29, 2025
bec7a2a
Tech: Refactored comment processing into a CommentProcessor class, in…
utsmannn Jan 29, 2025
869ca2f
Tech: Integrated AI comment processing in a CommentProcessor class, l…
utsmannn Jan 29, 2025
6069362
Tech: Modified GitLab CI comment bot trigger to activate on any non-b…
utsmannn Jan 29, 2025
b223c70
Merge branch 'feat/interface' into 'gitlab'
utsmannn Jan 29, 2025
391323d
Refactored GitLab CI to trigger comment bot on all non-bot user merge…
utsmannn Jan 29, 2025
748e38a
Refactored GitLab comment processing to use GitLab API, integrated Op…
utsmannn Jan 29, 2025
32ccb30
Refactored GitLab comment handling using the GitLab API, integrated O…
utsmannn Jan 29, 2025
c1a744e
Refactored GitLab CI comment bot trigger to activate on any merge req…
utsmannn Jan 29, 2025
760f795
Refactored GitLab CI configuration to remove hardcoded project and to…
utsmannn Jan 29, 2025
0c71ef7
Enhanced GitLab CI/CD: Streamlined configuration by fetching action c…
utsmannn Jan 29, 2025
3dfccb0
Removed GitLabCommentProcessor, centralizing comment processing withi…
utsmannn Jan 29, 2025
4354472
GitLab CI updated to fetch action code from v4 tag, include curl inst…
utsmannn Jan 29, 2025
7293d45
Enhanced GitLab CI: Upgraded to v4 action code, integrated curl, stre…
utsmannn Jan 29, 2025
3db52b8
GitLab CI updated to use v4 action code, install curl and zip, stream…
utsmannn Jan 29, 2025
ead9ed5
GitLab CI updated to use v4 action code by downloading a zip, install…
utsmannn Jan 29, 2025
61d7d66
GitLab CI updated to use v${VERSION} action code, install curl and zi…
utsmannn Jan 29, 2025
880de02
Refactored action for modularity: Migrated to 'corivai' package, upda…
utsmannn Jan 29, 2025
1679404
Updated GitLab CI and GitHub Action to use v5.rc-1 action code with z…
utsmannn Jan 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
image: python:3.9-slim

code-review:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: always
- if: '$CI_MERGE_REQUEST_EVENT_TYPE =~ /^(open|reopen|update)$/'
when: always
- if: '$CI_MERGE_REQUEST_EVENT_TYPE == "approved"'
when: never
- if: '$CI_PIPELINE_SOURCE == "merge_request_comment"'
when: always
script:
- export VERSION=5.rc-1
- apt-get update
- apt-get install curl -y
- apt-get install zip unzip -y
- curl -L https://github.com/utsmannn/corivai/archive/refs/tags/v${VERSION}.zip -o action_code.zip
- unzip action_code.zip
- cp -R corivai-${VERSION}/corivai .
- cp corivai-${VERSION}/requirements.txt .
- pip install -r requirements.txt
- python -m corivai.main-gitlab
variables:
REVIEWER_OPENAI_URL: "https://generativelanguage.googleapis.com/v1beta/openai/"
REVIEWER_MAX_DIFF_SIZE: "500000"
REVIEWER_MODEL_NAME: "gemini-1.5-flash"
11 changes: 6 additions & 5 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@ runs:

- name: Download Action Code and Requirements
run: |
curl -L https://github.com/utsmannn/corivai/archive/refs/heads/main.zip -o action_code.zip
export VERSION=5.rc-1
curl -L https://github.com/utsmannn/corivai/archive/refs/tags/v${VERSION}.zip -o action_code.zip
unzip action_code.zip
cp -R corivai-main/src .
cp corivai-main/requirements.txt .
cp -R corivai-${VERSION}/corivai .
cp corivai-${VERSION}/requirements.txt .
shell: bash

- name: Install dependencies
Expand All @@ -58,7 +59,7 @@ runs:
INPUT_MODEL-NAME: ${{ inputs.model-name }}
INPUT_CUSTOM-INSTRUCTIONS: ${{ inputs.custom-instructions }}
INPUT_MAX_DIFF_SIZE: ${{ inputs.max-diff-size }}
run: python -m src.main
run: python -m corivai.main
shell: bash

- name: Process Review Comments
Expand All @@ -74,5 +75,5 @@ runs:
REPO: ${{ github.repository }}
REVIEW_THREAD_ID: ${{ github.event.comment.pull_request_review_id }}
USER_LOGIN: ${{ github.event.comment.user.login }}
run: python -m src.comment_processor
run: python -m corivai.github_comment_processor
shell: bash
15 changes: 15 additions & 0 deletions corivai/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from corivai.exceptions import ReviewError
from corivai.decorators import retry
from corivai.models import ReviewComment, ReviewResponse
from corivai.generator_review_interface import ResponseReviewGenerator, AIReviewGenerator
from corivai.pr_reviewer import PRReviewer

__all__ = [
'ReviewError',
'retry',
'ReviewComment',
'ReviewResponse',
'ResponseReviewGenerator',
'AIReviewGenerator',
'PRReviewer'
]
9 changes: 9 additions & 0 deletions corivai/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from pydantic import BaseModel

class CorivaiConfig(BaseModel):
api_key: str
openai_url: str
model_name: str
git_token: str
max_diff_size: int
custom_instruction: str
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import os
from abc import ABC, abstractmethod
from typing import List, Dict, Any
import json
from abc import ABC, abstractmethod
from typing import Dict

from openai import OpenAI, BaseModel
from src.models import ReviewResponse, ReviewComment

from corivai.config import CorivaiConfig
from corivai.models import ReviewResponse, ReviewComment


class ResponseReviewGenerator(ABC):
Expand All @@ -22,11 +23,13 @@ class DiffResponse(BaseModel):
diff: list[DiffItem]

class AIReviewGenerator(ResponseReviewGenerator):
def __init__(self, model_name: str):
self.baseUrl = os.getenv('INPUT_OPENAI-URL', 'https://api.openai.com/v1')
self.apiKey = os.getenv('API_KEY')
self.client = OpenAI(base_url=self.baseUrl, api_key=self.apiKey)
self.model_name = model_name
def __init__(self, config: CorivaiConfig):

# self.baseUrl = os.getenv('INPUT_OPENAI-URL', 'https://api.openai.com/v1')
# self.apiKey = os.getenv('API_KEY')

self.client = OpenAI(base_url=config.openai_url, api_key=config.api_key)
self.model_name = config.model_name

def generate(self, structured_diff: str) -> ReviewResponse:
response = self.client.beta.chat.completions.parse(
Expand Down
61 changes: 61 additions & 0 deletions corivai/git_github.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import os
from typing import Dict, List
import requests
from github import Github
from github.PullRequest import PullRequest

from corivai.git_interface import GitInterface
from corivai.exceptions import ReviewError

class GitGithub(GitInterface):
def __init__(self, token: str, repo_identifier: str):
self.token = token
self.repo_identifier = repo_identifier
self.github = Github(token)
self.repo = self.github.get_repo(repo_identifier)

def get_request_number(self) -> int:
pr_ref = os.getenv('GITHUB_REF')
if not pr_ref:
raise ReviewError("GITHUB_REF not found")
try:
return int(pr_ref.split('/')[-2])
except (IndexError, ValueError) as e:
raise ReviewError(f"Invalid PR reference format: {str(e)}")

def get_request(self, number: int) -> PullRequest:
return self.repo.get_pull(number)

def get_diff(self, request: PullRequest) -> str:
headers = {
'Authorization': f'Bearer {self.token}',
'Accept': 'application/vnd.github.v3.diff'
}
url = f'https://api.github.com/repos/{self.repo_identifier}/pulls/{request.number}'
response = requests.get(url, headers=headers)
response.raise_for_status()
return response.text

def get_review_comments(self, request: PullRequest) -> List[Dict]:
comments = request.get_review_comments()
return [{
'path': comment.path,
'position': comment.position,
'body': comment.body,
'diff_hunk': comment.diff_hunk
} for comment in comments]

def create_review_comment(self, request: PullRequest, file_path: str, position: int, body: str) -> None:
return None

def create_review(self, request: PullRequest, comments: List[Dict]) -> None:
request.create_review(
event="COMMENT",
comments=comments
)

def create_issue_comment(self, request: PullRequest, body: str) -> None:
request.create_issue_comment(body)

def get_head_sha(self, request: PullRequest) -> str:
return request.head.sha
97 changes: 97 additions & 0 deletions corivai/git_gitlab.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import os
from typing import Dict, List
import requests
import gitlab
from gitlab.v4.objects import MergeRequest
import logging

from corivai.git_interface import GitInterface
from corivai.exceptions import ReviewError

logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)


class GitGitlab(GitInterface):
def __init__(self, token: str, repo_identifier: str):
self.token = token
self.project_id = repo_identifier
self.gitlab_url = os.getenv('CI_SERVER_URL', 'https://gitlab.com')
self.gl = gitlab.Gitlab(self.gitlab_url, private_token=token)
self.project = self.gl.projects.get(repo_identifier)

def get_request_number(self) -> int:
mr_iid = os.getenv('CI_MERGE_REQUEST_IID')
if not mr_iid:
raise ReviewError("CI_MERGE_REQUEST_IID not found")
try:
return int(mr_iid)
except ValueError as e:
raise ReviewError(f"Invalid merge request IID format: {str(e)}")

def get_request(self, number: int) -> MergeRequest:
return self.project.mergerequests.get(number)

def get_diff(self, request: MergeRequest) -> str:
headers = {
'PRIVATE-TOKEN': self.token
}
url = f'{self.gitlab_url}/api/v4/projects/{self.project_id}/merge_requests/{request.iid}/changes'
response = requests.get(url, headers=headers)
response.raise_for_status()

changes = response.json().get('changes', [])
diff_content = []

for change in changes:
diff_content.append(f"diff --git a/{change['old_path']} b/{change['new_path']}")
diff_content.append(change['diff'])

return '\n'.join(diff_content)

def get_review_comments(self, request: MergeRequest) -> List[Dict]:
discussions = request.discussions.list(get_all=True)
comments = []

for discussion in discussions:
for note in discussion.attributes.get('notes', []):
if note.get('type') == 'DiffNote':
comments.append({
'path': note.get('position', {}).get('new_path'),
'position': note.get('position', {}).get('new_line'),
'body': note.get('body'),
'diff_hunk': note.get('position', {}).get('new_line')
})

return comments

def create_review_comment(self, request: MergeRequest, file_path: str, position: int, body: str) -> None:
request.discussions.create({
'body': body,
'position': {
'base_sha': request.diff_refs['base_sha'],
'start_sha': request.diff_refs['start_sha'],
'head_sha': request.diff_refs['head_sha'],
'position_type': 'text',
'new_path': file_path,
'new_line': position
}
})

def create_review(self, request: MergeRequest, comments: List[Dict]) -> None:
for comment in comments:
self.create_review_comment(
request,
comment['path'],
comment['position'],
comment['body']
)

def create_issue_comment(self, request: MergeRequest, body: str) -> None:
request.notes.create({'body': body})

def get_head_sha(self, request: MergeRequest) -> str:
return request.sha
49 changes: 49 additions & 0 deletions corivai/git_interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from abc import ABC, abstractmethod
from typing import Dict, List, Optional


class GitInterface(ABC):
@abstractmethod
def __init__(self, token: str, repo_identifier: str):
"""Initialize git interface with token and repository identifier"""
pass

@abstractmethod
def get_request_number(self) -> int:
"""Get pull/merge request number from environment"""
pass

@abstractmethod
def get_request(self, number: int):
"""Get pull/merge request object"""
pass

@abstractmethod
def get_diff(self, request) -> str:
"""Get diff content from pull/merge request"""
pass

@abstractmethod
def get_review_comments(self, request) -> List[Dict]:
"""Get existing review comments"""
pass

@abstractmethod
def create_review_comment(self, request, file_path: str, position: int, body: str) -> None:
"""Create a new review comment"""
pass

@abstractmethod
def create_review(self, request, comments: List[Dict]) -> None:
"""Create a batch of review comments"""
pass

@abstractmethod
def create_issue_comment(self, request, body: str) -> None:
"""Create a general comment on the request"""
pass

@abstractmethod
def get_head_sha(self, request) -> str:
"""Get the current HEAD SHA of the request"""
pass
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from github import Github

from src import ReviewError
from corivai import ReviewError
from openai import OpenAI, BaseModel


Expand Down
Loading
Loading