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: tools/gitlab #7329

Merged
merged 16 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
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
2 changes: 1 addition & 1 deletion api/core/tools/provider/builtin/gitlab/gitlab.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ def _validate_credentials(self, credentials: dict[str, Any]) -> None:
if response.status_code != 200:
raise ToolProviderCredentialValidationError((response.json()).get('message'))
except Exception as e:
raise ToolProviderCredentialValidationError("Gitlab Access Tokens and Api Version is invalid. {}".format(e))
raise ToolProviderCredentialValidationError("Gitlab Access Tokens is invalid. {}".format(e))
except Exception as e:
raise ToolProviderCredentialValidationError(str(e))
6 changes: 3 additions & 3 deletions api/core/tools/provider/builtin/gitlab/gitlab.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ identity:
en_US: Gitlab
wlrnet marked this conversation as resolved.
Show resolved Hide resolved
zh_Hans: Gitlab
description:
en_US: Gitlab plugin for commit
zh_Hans: 用于获取Gitlab commit的插件
en_US: Gitlab plugin,only support v4 api.
wlrnet marked this conversation as resolved.
Show resolved Hide resolved
zh_Hans: 用于获取Gitlab内容的插件,目前仅支持v4版本api。
wlrnet marked this conversation as resolved.
Show resolved Hide resolved
icon: gitlab.svg
credentials_for_provider:
access_tokens:
Expand Down Expand Up @@ -35,4 +35,4 @@ credentials_for_provider:
help:
en_US: Find your Gitlab url
zh_Hans: 找到你的Gitlab url
url: https://gitlab.com/help
url: https://gitlab.com/help
34 changes: 22 additions & 12 deletions api/core/tools/provider/builtin/gitlab/tools/gitlab_commits.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def _invoke(self,
employee = tool_parameters.get('employee', '')
start_time = tool_parameters.get('start_time', '')
end_time = tool_parameters.get('end_time', '')
change_type = tool_parameters.get('change_type', 'all')

if not project:
return self.create_text_message('Project is required')
Expand All @@ -36,11 +37,11 @@ def _invoke(self,
site_url = 'https://gitlab.com'

# Get commit content
result = self.fetch(user_id, site_url, access_token, project, employee, start_time, end_time)
result = self.fetch(user_id, site_url, access_token, project, employee, start_time, end_time, change_type)

return self.create_text_message(json.dumps(result, ensure_ascii=False))
return [self.create_json_message(item) for item in result]

def fetch(self,user_id: str, site_url: str, access_token: str, project: str, employee: str = None, start_time: str = '', end_time: str = '') -> list[dict[str, Any]]:
def fetch(self,user_id: str, site_url: str, access_token: str, project: str, employee: str = None, start_time: str = '', end_time: str = '', change_type: str = '') -> list[dict[str, Any]]:
domain = site_url
headers = {"PRIVATE-TOKEN": access_token}
results = []
Expand Down Expand Up @@ -74,7 +75,7 @@ def fetch(self,user_id: str, site_url: str, access_token: str, project: str, emp

for commit in commits:
commit_sha = commit['id']
print(f"\tCommit SHA: {commit_sha}")
author_name = commit['author_name']

diff_url = f"{domain}/api/v4/projects/{project_id}/repository/commits/{commit_sha}/diff"
diff_response = requests.get(diff_url, headers=headers)
Expand All @@ -87,14 +88,23 @@ def fetch(self,user_id: str, site_url: str, access_token: str, project: str, emp
removed_lines = diff['diff'].count('\n-')
total_changes = added_lines + removed_lines

if total_changes > 1:
final_code = ''.join([line[1:] for line in diff['diff'].split('\n') if line.startswith('+') and not line.startswith('+++')])
results.append({
"project": project_name,
"commit_sha": commit_sha,
"diff": final_code
})
print(f"Commit code:{final_code}")
if change_type == "new":
if added_lines > 1:
final_code = ''.join([line[1:] for line in diff['diff'].split('\n') if line.startswith('+') and not line.startswith('+++')])
results.append({
"commit_sha": commit_sha,
"author_name": author_name,
"diff": final_code
})
else:
if total_changes > 1:
final_code = ''.join([line[1:] for line in diff['diff'].split('\n') if (line.startswith('+') or line.startswith('-')) and not line.startswith('+++') and not line.startswith('---')])
final_code_escaped = json.dumps(final_code)[1:-1] # Escape the final code
results.append({
"commit_sha": commit_sha,
"author_name": author_name,
"diff": final_code_escaped
})
except requests.RequestException as e:
print(f"Error fetching data from GitLab: {e}")

Expand Down
33 changes: 27 additions & 6 deletions api/core/tools/provider/builtin/gitlab/tools/gitlab_commits.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@ identity:
author: Leo.Wang
label:
en_US: Gitlab Commits
zh_Hans: Gitlab代码提交内容
zh_Hans: Gitlab提交内容查询
wlrnet marked this conversation as resolved.
Show resolved Hide resolved
description:
human:
en_US: A tool for query gitlab commits. Input should be a exists username.
zh_Hans: 一个用于查询gitlab代码提交记录的的工具,输入的内容应该是一个已存在的用户名或者项目名。
zh_Hans: 一个用于查询gitlab代码提交内容的工具,输入的内容应该是一个已存在的用户名或者项目名。
llm: A tool for query gitlab commits. Input should be a exists username or project.
parameters:
- name: employee
- name: username
type: string
required: false
label:
en_US: employee
en_US: username
zh_Hans: 员工用户名
human_description:
en_US: employee
en_US: username
zh_Hans: 员工用户名
llm_description: employee for gitlab
llm_description: username for gitlab
form: llm
- name: project
type: string
Expand Down Expand Up @@ -54,3 +54,24 @@ parameters:
zh_Hans: 结束时间
llm_description: end_time for gitlab
form: llm
- name: change_type
type: select
required: false
options:
- value: all
label:
en_US: all
zh_Hans: 所有
- value: new
label:
en_US: new
zh_Hans: 新增
default: all
label:
en_US: change_type
zh_Hans: 变更类型
human_description:
en_US: change_type
zh_Hans: 变更类型
llm_description: content change type for gitlab
form: llm
94 changes: 94 additions & 0 deletions api/core/tools/provider/builtin/gitlab/tools/gitlab_files.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
from typing import Any, Union
import requests

from core.tools.entities.tool_entities import ToolInvokeMessage
from core.tools.tool.builtin_tool import BuiltinTool


class GitlabFilesTool(BuiltinTool):
def _invoke(self,
user_id: str,
tool_parameters: dict[str, Any]
) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:

project = tool_parameters.get('project', '')
branch = tool_parameters.get('branch', '')
path = tool_parameters.get('path', '')


if not project:
return self.create_text_message('Project is required')
if not branch:
return self.create_text_message('Branch is required')

if not path:
return self.create_text_message('Path is required')

access_token = self.runtime.credentials.get('access_tokens')
site_url = self.runtime.credentials.get('site_url')

if 'access_tokens' not in self.runtime.credentials or not self.runtime.credentials.get('access_tokens'):
return self.create_text_message("Gitlab API Access Tokens is required.")
if 'site_url' not in self.runtime.credentials or not self.runtime.credentials.get('site_url'):
site_url = 'https://gitlab.com'

# Get project ID from project name
project_id = self.get_project_id(site_url, access_token, project)
if not project_id:
return self.create_text_message(f"Project '{project}' not found.")

# Get commit content
result = self.fetch(user_id, project_id, site_url, access_token, branch, path)

return [self.create_json_message(item) for item in result]

def extract_project_name_and_path(self, path: str) -> tuple[str, str]:
parts = path.split('/', 1)
if len(parts) < 2:
return None, None
return parts[0], parts[1]

def get_project_id(self, site_url: str, access_token: str, project_name: str) -> Union[str, None]:
headers = {"PRIVATE-TOKEN": access_token}
try:
url = f"{site_url}/api/v4/projects?search={project_name}"
response = requests.get(url, headers=headers)
response.raise_for_status()
projects = response.json()
for project in projects:
if project['name'] == project_name:
return project['id']
except requests.RequestException as e:
print(f"Error fetching project ID from GitLab: {e}")
return None

def fetch(self,user_id: str, project_id: str, site_url: str, access_token: str, branch: str, path: str = None) -> list[dict[str, Any]]:
domain = site_url
headers = {"PRIVATE-TOKEN": access_token}
results = []

try:
# List files and directories in the given path
url = f"{domain}/api/v4/projects/{project_id}/repository/tree?path={path}&ref={branch}"
response = requests.get(url, headers=headers)
response.raise_for_status()
items = response.json()

for item in items:
item_path = item['path']
if item['type'] == 'tree': # It's a directory
results.extend(self.fetch(project_id, site_url, access_token, branch, item_path))
else: # It's a file
file_url = f"{domain}/api/v4/projects/{project_id}/repository/files/{item_path}/raw?ref={branch}"
file_response = requests.get(file_url, headers=headers)
file_response.raise_for_status()
file_content = file_response.text
results.append({
"path": item_path,
"branch": branch,
"content": file_content
})
except requests.RequestException as e:
print(f"Error fetching data from GitLab: {e}")

return results
45 changes: 45 additions & 0 deletions api/core/tools/provider/builtin/gitlab/tools/gitlab_files.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
identity:
name: gitlab_files
author: Leo.Wang
label:
en_US: Gitlab Files
zh_Hans: Gitlab文件获取
description:
human:
en_US: A tool for query gitlab files. Input should be branch and a exists file or directory path.
zh_Hans: 一个用于查询gitlab文件的工具,输入的内容应该是分支和一个已存在文件或者文件夹路径。
llm: A tool for query gitlab files. Input should be a exists file or directory path.
parameters:
- name: project
type: string
required: true
label:
en_US: project
zh_Hans: 项目
human_description:
en_US: project
zh_Hans: 项目
llm_description: Project for gitlab
form: llm
- name: branch
type: string
required: true
label:
en_US: branch
zh_Hans: 分支
human_description:
en_US: branch
zh_Hans: 分支
llm_description: Branch for gitlab
form: llm
- name: path
type: string
required: true
label:
en_US: path
zh_Hans: 文件路径
human_description:
en_US: path
zh_Hans: 文件路径
llm_description: File path for gitlab
form: llm
Loading