Reference: GitLab datasource plugin source code for Gitea fork
Original langgenius/gitlab_datasource v0.3.7 files for the Gitea modification planned in Task #128. Claude (Chronicler #82)
This commit is contained in:
committed by
Claude
parent
605bab0ebb
commit
d5bdf7f7a3
@@ -0,0 +1,469 @@
|
||||
from collections.abc import Generator
|
||||
import requests
|
||||
import time
|
||||
import base64
|
||||
import markdown
|
||||
import certifi
|
||||
from typing import Dict, List, Optional, Any
|
||||
from urllib.parse import urlparse
|
||||
from requests.adapters import HTTPAdapter
|
||||
from urllib3.util.retry import Retry
|
||||
|
||||
from dify_plugin.entities.datasource import (
|
||||
DatasourceGetPagesResponse,
|
||||
DatasourceMessage,
|
||||
GetOnlineDocumentPageContentRequest,
|
||||
OnlineDocumentInfo,
|
||||
)
|
||||
from dify_plugin.interfaces.datasource.online_document import OnlineDocumentDatasource
|
||||
|
||||
|
||||
class GitLabDataSource(OnlineDocumentDatasource):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
# GitLab URL will be set from credentials, default to gitlab.com
|
||||
self.gitlab_url = None
|
||||
self.base_url = None
|
||||
|
||||
def _get_requests_session(self) -> requests.Session:
|
||||
"""Create a requests session with retry strategy and SSL verification"""
|
||||
session = requests.Session()
|
||||
retry_strategy = Retry(
|
||||
total=3,
|
||||
backoff_factor=1,
|
||||
status_forcelist=[429, 500, 502, 503, 504],
|
||||
allowed_methods=["HEAD", "GET", "PUT", "DELETE", "OPTIONS", "TRACE", "POST"],
|
||||
)
|
||||
|
||||
adapter = HTTPAdapter(max_retries=retry_strategy)
|
||||
session.mount("http://", adapter)
|
||||
session.mount("https://", adapter)
|
||||
session.verify = certifi.where()
|
||||
return session
|
||||
|
||||
def _safe_json_response(self, response: requests.Response) -> dict:
|
||||
"""Safely parse JSON response with validation"""
|
||||
if response.status_code >= 400:
|
||||
self._handle_rate_limit(response)
|
||||
|
||||
try:
|
||||
data = response.json()
|
||||
if not isinstance(data, dict) and not isinstance(data, list):
|
||||
raise ValueError(f"Invalid response format: expected dict or list, got {type(data)}")
|
||||
return data
|
||||
except ValueError as e:
|
||||
raise ValueError(f"Invalid JSON response: {str(e)}")
|
||||
except Exception as e:
|
||||
raise ValueError(f"Failed to parse response: {str(e)}")
|
||||
|
||||
def _get_headers(self) -> Dict[str, str]:
|
||||
"""获取 API 请求头"""
|
||||
credentials = self.runtime.credentials
|
||||
access_token = credentials.get("access_token")
|
||||
|
||||
if not access_token:
|
||||
raise ValueError("Access token not found in credentials")
|
||||
|
||||
# Validate access token format (basic check)
|
||||
if not isinstance(access_token, str) or len(access_token.strip()) == 0:
|
||||
raise ValueError("Invalid access token format")
|
||||
|
||||
return {
|
||||
"Authorization": f"Bearer {access_token.strip()}",
|
||||
"User-Agent": "Dify-GitLab-Datasource"
|
||||
}
|
||||
|
||||
def _get_gitlab_url(self) -> str:
|
||||
"""获取 GitLab URL"""
|
||||
if self.gitlab_url is None:
|
||||
credentials = self.runtime.credentials
|
||||
gitlab_url = credentials.get("gitlab_url", "https://gitlab.com")
|
||||
|
||||
# Validate URL format
|
||||
if not isinstance(gitlab_url, str):
|
||||
raise ValueError("Invalid GitLab URL: must be a string")
|
||||
|
||||
gitlab_url = gitlab_url.strip().rstrip("/")
|
||||
|
||||
if not gitlab_url.startswith(("http://", "https://")):
|
||||
raise ValueError(f"Invalid GitLab URL format: {gitlab_url}")
|
||||
|
||||
self.gitlab_url = gitlab_url
|
||||
self.base_url = f"{self.gitlab_url}/api/v4"
|
||||
return self.gitlab_url
|
||||
|
||||
def _handle_rate_limit(self, response: requests.Response) -> None:
|
||||
"""处理 API 限流"""
|
||||
if response.status_code == 429:
|
||||
# GitLab uses 429 for rate limiting
|
||||
retry_after = response.headers.get("Retry-After", "60")
|
||||
try:
|
||||
sleep_time = int(retry_after)
|
||||
except ValueError:
|
||||
sleep_time = 60
|
||||
raise ValueError(f"GitLab API rate limit exceeded. Please wait {sleep_time} seconds.")
|
||||
elif response.status_code == 401:
|
||||
raise ValueError("Invalid GitLab access token. Please check your credentials.")
|
||||
elif response.status_code == 403:
|
||||
raise ValueError("Access forbidden. Check your GitLab permissions.")
|
||||
elif response.status_code >= 400:
|
||||
raise ValueError(f"GitLab API error: {response.status_code} - {response.text}")
|
||||
|
||||
def _make_request(self, url: str, params: Optional[Dict] = None) -> Dict:
|
||||
"""发起 API 请求并处理错误"""
|
||||
# Ensure GitLab URL is set
|
||||
self._get_gitlab_url()
|
||||
headers = self._get_headers()
|
||||
|
||||
# Validate URL to prevent SSRF
|
||||
if not url.startswith(("http://", "https://")):
|
||||
raise ValueError(f"Invalid URL format: {url}")
|
||||
|
||||
try:
|
||||
session = self._get_requests_session()
|
||||
response = session.get(url, headers=headers, params=params, timeout=30)
|
||||
return self._safe_json_response(response)
|
||||
except requests.exceptions.RequestException as e:
|
||||
raise ValueError(f"Network error when accessing GitLab API: {str(e)}")
|
||||
|
||||
def _get_pages(self, datasource_parameters: dict[str, Any]) -> DatasourceGetPagesResponse:
|
||||
"""获取 GitLab 页面列表(项目、Issues、MRs)"""
|
||||
access_token = self.runtime.credentials.get("access_token")
|
||||
if not access_token:
|
||||
raise ValueError("Access token not found in credentials")
|
||||
|
||||
# 确保设置了 GitLab URL
|
||||
self._get_gitlab_url()
|
||||
|
||||
# 获取用户信息
|
||||
user_info = self._make_request(f"{self.base_url}/user")
|
||||
workspace_name = f"{user_info.get('name', user_info.get('username'))}'s GitLab"
|
||||
workspace_icon = user_info.get('avatar_url', '')
|
||||
workspace_id = str(user_info.get('id', ''))
|
||||
|
||||
pages = []
|
||||
|
||||
# 获取用户项目
|
||||
projects = self._get_projects()
|
||||
for project in projects:
|
||||
# 添加项目作为页面
|
||||
pages.append({
|
||||
"page_id": f"project:{project['path_with_namespace']}",
|
||||
"page_name": project['name'],
|
||||
"last_edited_time": project.get("last_activity_at", ""),
|
||||
"type": "project",
|
||||
"url": project['web_url'],
|
||||
"metadata": {
|
||||
"description": project.get("description", ""),
|
||||
"language": project.get("default_branch", ""),
|
||||
"stars": project.get("star_count", 0),
|
||||
"updated_at": project.get("last_activity_at", ""),
|
||||
"private": not project.get("visibility", "private") == "public"
|
||||
}
|
||||
})
|
||||
|
||||
# 添加 README 文件(如果存在)
|
||||
try:
|
||||
# GitLab API: GET /projects/:id/repository/files/:file_path
|
||||
project_id = project['id']
|
||||
readme_info = self._make_request(f"{self.base_url}/projects/{project_id}/repository/files/README.md")
|
||||
pages.append({
|
||||
"page_id": f"file:{project['path_with_namespace']}:README.md",
|
||||
"page_name": f"{project['name']} - README",
|
||||
"last_edited_time": project.get("last_activity_at", ""),
|
||||
"type": "file",
|
||||
"url": f"{project['web_url']}/-/blob/{project.get('default_branch', 'main')}/README.md",
|
||||
"metadata": {
|
||||
"project": project['path_with_namespace'],
|
||||
"file_path": "README.md",
|
||||
"size": readme_info.get('size', 0)
|
||||
}
|
||||
})
|
||||
except ValueError:
|
||||
pass # README 不存在
|
||||
|
||||
# 添加热门 Issues
|
||||
try:
|
||||
project_id = project['id']
|
||||
issues = self._make_request(
|
||||
f"{self.base_url}/projects/{project_id}/issues",
|
||||
params={"state": "all", "per_page": 5, "order_by": "updated_at"}
|
||||
)
|
||||
for issue in issues:
|
||||
pages.append({
|
||||
"page_id": f"issue:{project['path_with_namespace']}:{issue['iid']}",
|
||||
"page_name": f"Issue #{issue['iid']}: {issue['title']}",
|
||||
"last_edited_time": issue.get('updated_at', ''),
|
||||
"type": "issue",
|
||||
"url": issue['web_url'],
|
||||
"metadata": {
|
||||
"project": project['path_with_namespace'],
|
||||
"issue_number": issue['iid'],
|
||||
"state": issue['state'],
|
||||
"author": issue['author']['username'],
|
||||
"created_at": issue['created_at']
|
||||
}
|
||||
})
|
||||
except ValueError:
|
||||
pass # Issues 访问失败
|
||||
|
||||
# 添加热门 Merge Requests
|
||||
try:
|
||||
project_id = project['id']
|
||||
merge_requests = self._make_request(
|
||||
f"{self.base_url}/projects/{project_id}/merge_requests",
|
||||
params={"state": "all", "per_page": 5, "order_by": "updated_at"}
|
||||
)
|
||||
for mr in merge_requests:
|
||||
pages.append({
|
||||
"page_id": f"mr:{project['path_with_namespace']}:{mr['iid']}",
|
||||
"page_name": f"MR #{mr['iid']}: {mr['title']}",
|
||||
"last_edited_time": mr.get('updated_at', ''),
|
||||
"type": "merge_request",
|
||||
"url": mr['web_url'],
|
||||
"metadata": {
|
||||
"project": project['path_with_namespace'],
|
||||
"mr_number": mr['iid'],
|
||||
"state": mr['state'],
|
||||
"author": mr['author']['username'],
|
||||
"target_branch": mr['target_branch'],
|
||||
"source_branch": mr['source_branch']
|
||||
}
|
||||
})
|
||||
except ValueError:
|
||||
pass # MRs 访问失败
|
||||
|
||||
online_document_info = OnlineDocumentInfo(
|
||||
workspace_name=workspace_name,
|
||||
workspace_icon=workspace_icon,
|
||||
workspace_id=workspace_id,
|
||||
pages=pages,
|
||||
total=len(pages),
|
||||
)
|
||||
|
||||
return DatasourceGetPagesResponse(result=[online_document_info])
|
||||
|
||||
def _get_projects(self, max_projects: int = 20) -> List[Dict]:
|
||||
"""获取用户项目列表"""
|
||||
params = {
|
||||
"per_page": max_projects,
|
||||
"order_by": "last_activity_at",
|
||||
"sort": "desc",
|
||||
"membership": True # 只获取用户有权限的项目
|
||||
}
|
||||
projects = self._make_request(f"{self.base_url}/projects", params)
|
||||
return projects
|
||||
|
||||
def _get_content(self, page: GetOnlineDocumentPageContentRequest) -> Generator[DatasourceMessage, None, None]:
|
||||
"""获取页面内容"""
|
||||
access_token = self.runtime.credentials.get("access_token")
|
||||
if not access_token:
|
||||
raise ValueError("Access token not found in credentials")
|
||||
|
||||
# 确保设置了 GitLab URL
|
||||
self._get_gitlab_url()
|
||||
|
||||
page_id = page.page_id
|
||||
|
||||
if page_id.startswith("project:"):
|
||||
# 获取项目信息
|
||||
yield from self._get_project_content(page_id)
|
||||
elif page_id.startswith("file:"):
|
||||
# 获取文件内容
|
||||
yield from self._get_file_content(page_id)
|
||||
elif page_id.startswith("issue:"):
|
||||
# 获取 Issue 内容
|
||||
yield from self._get_issue_content(page_id)
|
||||
elif page_id.startswith("mr:"):
|
||||
# 获取 MR 内容
|
||||
yield from self._get_mr_content(page_id)
|
||||
else:
|
||||
raise ValueError(f"Unsupported page type: {page_id}")
|
||||
|
||||
def _get_project_content(self, page_id: str) -> Generator[DatasourceMessage, None, None]:
|
||||
"""获取项目信息内容"""
|
||||
project_path = page_id[8:] # 移除 "project:" 前缀
|
||||
|
||||
# GitLab uses project path with namespace or project ID
|
||||
project_info = self._make_request(f"{self.base_url}/projects/{project_path.replace('/', '%2F')}")
|
||||
|
||||
content = f"# {project_info['name']}\n\n"
|
||||
content += f"**Project:** {project_info['path_with_namespace']}\n"
|
||||
content += f"**Description:** {project_info.get('description', 'No description')}\n"
|
||||
content += f"**Default Branch:** {project_info.get('default_branch', 'main')}\n"
|
||||
content += f"**Stars:** {project_info.get('star_count', 0)}\n"
|
||||
content += f"**Forks:** {project_info.get('forks_count', 0)}\n"
|
||||
content += f"**Created:** {project_info.get('created_at', '')}\n"
|
||||
content += f"**Last Activity:** {project_info.get('last_activity_at', '')}\n"
|
||||
content += f"**URL:** {project_info.get('web_url', '')}\n\n"
|
||||
|
||||
if project_info.get('topics'):
|
||||
topics = ", ".join(project_info['topics'])
|
||||
content += f"**Topics:** {topics}\n\n"
|
||||
|
||||
# 尝试获取 README
|
||||
try:
|
||||
project_id = project_info['id']
|
||||
readme_info = self._make_request(f"{self.base_url}/projects/{project_id}/repository/files/README.md")
|
||||
if readme_info.get("encoding") == "base64":
|
||||
try:
|
||||
readme_content = base64.b64decode(readme_info["content"]).decode("utf-8")
|
||||
content += "## README\n\n" + readme_content
|
||||
except (ValueError, UnicodeDecodeError) as e:
|
||||
content += "## README\n\nError decoding README content."
|
||||
except ValueError:
|
||||
content += "## README\n\nNo README file found."
|
||||
|
||||
yield self.create_variable_message("content", content)
|
||||
yield self.create_variable_message("page_id", page_id)
|
||||
yield self.create_variable_message("title", project_info['name'])
|
||||
yield self.create_variable_message("project", project_path)
|
||||
yield self.create_variable_message("type", "project")
|
||||
|
||||
def _get_file_content(self, page_id: str) -> Generator[DatasourceMessage, None, None]:
|
||||
"""获取文件内容"""
|
||||
# page_id format: "file:namespace/project:path"
|
||||
parts = page_id.split(":", 2)
|
||||
if len(parts) != 3:
|
||||
raise ValueError(f"Invalid file page_id format: {page_id}")
|
||||
project_path = parts[1]
|
||||
file_path = parts[2]
|
||||
|
||||
# Basic input validation
|
||||
if not project_path or not file_path:
|
||||
raise ValueError(f"Invalid project path or file path in page_id: {page_id}")
|
||||
|
||||
# URL encode the project path for GitLab API
|
||||
encoded_project = project_path.replace('/', '%2F')
|
||||
encoded_file_path = file_path.replace('/', '%2F')
|
||||
|
||||
file_info = self._make_request(f"{self.base_url}/projects/{encoded_project}/repository/files/{encoded_file_path}")
|
||||
|
||||
# 获取文件内容
|
||||
if file_info.get("encoding") == "base64":
|
||||
try:
|
||||
content = base64.b64decode(file_info["content"]).decode("utf-8")
|
||||
except (ValueError, UnicodeDecodeError) as e:
|
||||
raise ValueError(f"Failed to decode file content: {str(e)}")
|
||||
else:
|
||||
content = file_info.get("content", "")
|
||||
# Validate that content is a string
|
||||
if not isinstance(content, str):
|
||||
content = str(content)
|
||||
|
||||
# 如果是 Markdown 文件,添加标题
|
||||
file_name = file_path.split('/')[-1] # 获取文件名
|
||||
if file_name.lower().endswith(('.md', '.markdown')):
|
||||
content = f"# {file_name}\n\n{content}"
|
||||
|
||||
yield self.create_variable_message("content", content)
|
||||
yield self.create_variable_message("page_id", page_id)
|
||||
yield self.create_variable_message("title", file_name)
|
||||
yield self.create_variable_message("project", project_path)
|
||||
yield self.create_variable_message("file_path", file_path)
|
||||
yield self.create_variable_message("type", "file")
|
||||
|
||||
def _get_issue_content(self, page_id: str) -> Generator[DatasourceMessage, None, None]:
|
||||
"""获取 Issue 内容"""
|
||||
# page_id format: "issue:namespace/project:iid"
|
||||
parts = page_id.split(":", 2)
|
||||
if len(parts) != 3:
|
||||
raise ValueError(f"Invalid issue page_id format: {page_id}")
|
||||
project_path = parts[1]
|
||||
issue_iid = parts[2]
|
||||
|
||||
# Basic input validation
|
||||
if not project_path or not issue_iid:
|
||||
raise ValueError(f"Invalid project path or issue IID in page_id: {page_id}")
|
||||
|
||||
# URL encode the project path for GitLab API
|
||||
encoded_project = project_path.replace('/', '%2F')
|
||||
|
||||
issue = self._make_request(f"{self.base_url}/projects/{encoded_project}/issues/{issue_iid}")
|
||||
|
||||
content = f"# Issue #{issue['iid']}: {issue['title']}\n\n"
|
||||
content += f"**Project:** {project_path}\n"
|
||||
content += f"**Author:** {issue['author']['username']}\n"
|
||||
content += f"**State:** {issue['state']}\n"
|
||||
content += f"**Created:** {issue['created_at']}\n"
|
||||
content += f"**Updated:** {issue['updated_at']}\n"
|
||||
content += f"**URL:** {issue['web_url']}\n\n"
|
||||
|
||||
if issue.get('labels'):
|
||||
labels = ", ".join(issue['labels'])
|
||||
content += f"**Labels:** {labels}\n\n"
|
||||
|
||||
if issue.get('description'):
|
||||
content += "## Description\n\n"
|
||||
content += issue['description'] + "\n\n"
|
||||
|
||||
# 获取评论 (notes)
|
||||
try:
|
||||
comments = self._make_request(f"{self.base_url}/projects/{encoded_project}/issues/{issue_iid}/notes")
|
||||
if comments:
|
||||
content += "## Comments\n\n"
|
||||
for comment in comments:
|
||||
if not comment.get('system', False): # 排除系统消息
|
||||
content += f"### {comment['author']['username']} - {comment['created_at']}\n\n"
|
||||
content += comment['body'] + "\n\n"
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
yield self.create_variable_message("content", content)
|
||||
yield self.create_variable_message("page_id", page_id)
|
||||
yield self.create_variable_message("title", f"Issue #{issue['iid']}: {issue['title']}")
|
||||
yield self.create_variable_message("project", project_path)
|
||||
yield self.create_variable_message("issue_number", issue_iid)
|
||||
yield self.create_variable_message("type", "issue")
|
||||
|
||||
def _get_mr_content(self, page_id: str) -> Generator[DatasourceMessage, None, None]:
|
||||
"""获取 MR 内容"""
|
||||
# page_id format: "mr:namespace/project:iid"
|
||||
parts = page_id.split(":", 2)
|
||||
if len(parts) != 3:
|
||||
raise ValueError(f"Invalid merge request page_id format: {page_id}")
|
||||
project_path = parts[1]
|
||||
mr_iid = parts[2]
|
||||
|
||||
# Basic input validation
|
||||
if not project_path or not mr_iid:
|
||||
raise ValueError(f"Invalid project path or MR IID in page_id: {page_id}")
|
||||
|
||||
# URL encode the project path for GitLab API
|
||||
encoded_project = project_path.replace('/', '%2F')
|
||||
|
||||
mr = self._make_request(f"{self.base_url}/projects/{encoded_project}/merge_requests/{mr_iid}")
|
||||
|
||||
content = f"# Merge Request #{mr['iid']}: {mr['title']}\n\n"
|
||||
content += f"**Project:** {project_path}\n"
|
||||
content += f"**Author:** {mr['author']['username']}\n"
|
||||
content += f"**State:** {mr['state']}\n"
|
||||
content += f"**Target Branch:** {mr['target_branch']}\n"
|
||||
content += f"**Source Branch:** {mr['source_branch']}\n"
|
||||
content += f"**Created:** {mr['created_at']}\n"
|
||||
content += f"**Updated:** {mr['updated_at']}\n"
|
||||
content += f"**URL:** {mr['web_url']}\n\n"
|
||||
|
||||
if mr.get('description'):
|
||||
content += "## Description\n\n"
|
||||
content += mr['description'] + "\n\n"
|
||||
|
||||
# 获取评论 (notes)
|
||||
try:
|
||||
comments = self._make_request(f"{self.base_url}/projects/{encoded_project}/merge_requests/{mr_iid}/notes")
|
||||
if comments:
|
||||
content += "## Comments\n\n"
|
||||
for comment in comments:
|
||||
if not comment.get('system', False): # 排除系统消息
|
||||
content += f"### {comment['author']['username']} - {comment['created_at']}\n\n"
|
||||
content += comment['body'] + "\n\n"
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
yield self.create_variable_message("content", content)
|
||||
yield self.create_variable_message("page_id", page_id)
|
||||
yield self.create_variable_message("title", f"MR #{mr['iid']}: {mr['title']}")
|
||||
yield self.create_variable_message("project", project_path)
|
||||
yield self.create_variable_message("mr_number", mr_iid)
|
||||
yield self.create_variable_message("type", "merge_request")
|
||||
@@ -0,0 +1,35 @@
|
||||
identity:
|
||||
name: gitlab
|
||||
author: langgenius
|
||||
label:
|
||||
en_US: GitLab Project
|
||||
zh_Hans: GitLab 项目
|
||||
ja_JP: GitLab プロジェクト
|
||||
pt_BR: Projeto GitLab
|
||||
zh_Hant: GitLab 專案
|
||||
icon: icon.png
|
||||
description:
|
||||
en_US: Access GitLab projects, issues, merge requests, and files
|
||||
zh_Hans: 访问 GitLab 项目、问题、合并请求和文件
|
||||
ja_JP: GitLabのプロジェクト、課題、マージリクエスト、ファイルにアクセスします
|
||||
pt_BR: Acesse projetos, issues, merge requests e arquivos do GitLab
|
||||
zh_Hant: 存取 GitLab 專案、議題、合併請求和檔案
|
||||
|
||||
parameters:
|
||||
|
||||
output_schema:
|
||||
type: object
|
||||
properties:
|
||||
page_id:
|
||||
type: string
|
||||
description: page id
|
||||
content:
|
||||
type: string
|
||||
description: page content
|
||||
workspace_id:
|
||||
type: string
|
||||
description: workspace id
|
||||
|
||||
extra:
|
||||
python:
|
||||
source: datasources/gitlab.py
|
||||
@@ -0,0 +1,38 @@
|
||||
version: 0.3.7
|
||||
type: plugin
|
||||
author: langgenius
|
||||
name: gitlab_datasource
|
||||
label:
|
||||
en_US: GitLab
|
||||
ja_JP: GitLab
|
||||
zh_Hans: GitLab
|
||||
pt_BR: GitLab
|
||||
zh_Hant: GitLab
|
||||
description:
|
||||
en_US: GitLab Project Datasource - Access projects, issues, merge requests, and files
|
||||
ja_JP: GitLab プロジェクトデータソース - プロジェクト、課題、マージリクエスト、ファイルへのアクセス
|
||||
zh_Hans: GitLab 项目数据源 - 访问项目、问题、合并请求和文件
|
||||
pt_BR: Fonte de Dados de Projeto GitLab - Acesse projetos, issues, merge requests e arquivos
|
||||
zh_Hant: GitLab 專案資料來源 - 存取專案、議題、合併請求和檔案
|
||||
icon: icon.png
|
||||
resource:
|
||||
memory: 268435456
|
||||
permission: {}
|
||||
plugins:
|
||||
datasources:
|
||||
- provider/gitlab.yaml
|
||||
meta:
|
||||
version: 0.3.0
|
||||
arch:
|
||||
- amd64
|
||||
- arm64
|
||||
runner:
|
||||
language: python
|
||||
version: "3.12"
|
||||
entrypoint: main
|
||||
minimum_dify_version: 1.9.0
|
||||
created_at: 2025-01-27T10:00:00.000000+08:00
|
||||
privacy: PRIVACY.md
|
||||
verified: false
|
||||
tags:
|
||||
- rag
|
||||
@@ -0,0 +1,172 @@
|
||||
identity:
|
||||
author: langgenius
|
||||
name: gitlab
|
||||
label:
|
||||
en_US: GitLab
|
||||
zh_Hans: GitLab
|
||||
ja_JP: GitLab
|
||||
pt_BR: GitLab
|
||||
zh_Hant: GitLab
|
||||
description:
|
||||
en_US: GitLab Project Datasource - Access projects, issues, merge requests, and files
|
||||
zh_Hans: GitLab 项目数据源 - 访问项目、问题、合并请求和文件
|
||||
ja_JP: GitLab プロジェクトデータソース - プロジェクト、課題、マージリクエスト、ファイルへのアクセス
|
||||
pt_BR: Fonte de Dados de Projeto GitLab - Acesse projetos, issues, merge requests e arquivos
|
||||
zh_Hant: GitLab 專案資料來源 - 存取專案、議題、合併請求和檔案
|
||||
icon: icon.png
|
||||
provider_type: online_document
|
||||
help:
|
||||
title:
|
||||
en_US: Get your GitLab credentials
|
||||
zh_Hans: 获取您的 GitLab 凭证
|
||||
ja_JP: GitLabの認証情報を取得する
|
||||
pt_BR: Obtenha suas credenciais do GitLab
|
||||
zh_Hant: 獲取您的 GitLab 憑證
|
||||
url:
|
||||
en_US: https://gitlab.com/-/profile/applications
|
||||
zh_Hans: https://gitlab.com/-/profile/applications
|
||||
oauth_schema:
|
||||
client_schema:
|
||||
- name: client_id
|
||||
type: secret-input
|
||||
label:
|
||||
zh_Hans: Client ID
|
||||
en_US: Client ID
|
||||
ja_JP: クライアントID
|
||||
pt_BR: ID do Cliente
|
||||
zh_Hant: 用戶端ID
|
||||
- name: client_secret
|
||||
type: secret-input
|
||||
label:
|
||||
zh_Hans: Client Secret
|
||||
en_US: Client Secret
|
||||
ja_JP: クライアントシークレット
|
||||
pt_BR: Segredo do Cliente
|
||||
zh_Hant: 用戶端密鑰
|
||||
help:
|
||||
zh_Hans: 从 GitLab Applications 页面获取您的客户端凭证
|
||||
en_US: Get your client credentials from GitLab Applications page
|
||||
ja_JP: GitLabのアプリケーションページからクライアント認証情報を取得します
|
||||
pt_BR: Obtenha suas credenciais de cliente na página de Aplicações do GitLab
|
||||
zh_Hant: 從 GitLab 應用程式頁面取得您的用戶端憑證
|
||||
url: https://gitlab.com/-/profile/applications
|
||||
- name: gitlab_url
|
||||
type: text-input
|
||||
label:
|
||||
zh_Hans: GitLab URL
|
||||
en_US: GitLab URL
|
||||
ja_JP: GitLab URL
|
||||
pt_BR: URL do GitLab
|
||||
zh_Hant: GitLab URL
|
||||
placeholder:
|
||||
zh_Hans: https://gitlab.com
|
||||
en_US: https://gitlab.com
|
||||
ja_JP: https://gitlab.com
|
||||
pt_BR: https://gitlab.com
|
||||
zh_Hant: https://gitlab.com
|
||||
default: https://gitlab.com
|
||||
help:
|
||||
zh_Hans: 您的 GitLab 实例 URL(对于 gitlab.com 使用默认值)
|
||||
en_US: Your GitLab instance URL (use default for gitlab.com)
|
||||
ja_JP: あなたのGitLabインスタンスのURL(gitlab.comの場合はデフォルトを使用)
|
||||
pt_BR: A URL da sua instância do GitLab (use o padrão para gitlab.com)
|
||||
zh_Hant: 您的 GitLab 實例 URL(對於 gitlab.com 使用預設值)
|
||||
credentials_schema:
|
||||
- name: access_token
|
||||
type: secret-input
|
||||
label:
|
||||
zh_Hans: Access Token
|
||||
en_US: Access Token
|
||||
ja_JP: アクセストークン
|
||||
pt_BR: Token de Acesso
|
||||
zh_Hant: 存取權杖
|
||||
- name: refresh_token
|
||||
type: secret-input
|
||||
label:
|
||||
zh_Hans: Refresh Token
|
||||
en_US: Refresh Token
|
||||
ja_JP: リフレッシュトークン
|
||||
pt_BR: Token de Atualização
|
||||
zh_Hant: 刷新權杖
|
||||
- name: client_id
|
||||
type: secret-input
|
||||
label:
|
||||
zh_Hans: Client ID
|
||||
en_US: Client ID
|
||||
ja_JP: クライアントID
|
||||
pt_BR: ID do Cliente
|
||||
zh_Hant: 用戶端ID
|
||||
- name: client_secret
|
||||
type: secret-input
|
||||
label:
|
||||
zh_Hans: Client Secret
|
||||
en_US: Client Secret
|
||||
ja_JP: クライアントシークレット
|
||||
pt_BR: Segredo do Cliente
|
||||
zh_Hant: 用戶端密鑰
|
||||
- name: gitlab_url
|
||||
type: text-input
|
||||
label:
|
||||
zh_Hans: GitLab URL
|
||||
en_US: GitLab URL
|
||||
ja_JP: GitLab URL
|
||||
pt_BR: URL do GitLab
|
||||
zh_Hant: GitLab URL
|
||||
- name: user_login
|
||||
type: secret-input
|
||||
label:
|
||||
zh_Hans: User Login
|
||||
en_US: User Login
|
||||
ja_JP: ユーザーログイン
|
||||
pt_BR: Login do Usuário
|
||||
zh_Hant: 使用者登入
|
||||
credentials_schema:
|
||||
- name: access_token
|
||||
type: secret-input
|
||||
required: true
|
||||
label:
|
||||
en_US: Personal Access Token
|
||||
zh_Hans: 个人访问令牌
|
||||
ja_JP: 個人アクセストークン
|
||||
pt_BR: Token de Acesso Pessoal
|
||||
zh_Hant: 個人存取權杖
|
||||
placeholder:
|
||||
en_US: glpat-xxxxxxxxxxxxxxxxxxxx
|
||||
zh_Hans: glpat-xxxxxxxxxxxxxxxxxxxx
|
||||
ja_JP: glpat-xxxxxxxxxxxxxxxxxxxx
|
||||
pt_BR: glpat-xxxxxxxxxxxxxxxxxxxx
|
||||
zh_Hant: glpat-xxxxxxxxxxxxxxxxxxxx
|
||||
help:
|
||||
en_US: Create a personal access token in GitLab Settings > Access Tokens
|
||||
zh_Hans: 在 GitLab 设置 > 访问令牌中创建个人访问令牌
|
||||
ja_JP: GitLabの「設定」>「アクセストークン」で個人アクセストークンを作成します
|
||||
pt_BR: Crie um token de acesso pessoal em Configurações > Tokens de Acesso do GitLab
|
||||
zh_Hant: 在 GitLab 設定 > 存取權杖中建立個人存取權杖
|
||||
url: https://gitlab.com/-/profile/personal_access_tokens
|
||||
- name: gitlab_url
|
||||
type: text-input
|
||||
required: false
|
||||
label:
|
||||
en_US: GitLab URL
|
||||
zh_Hans: GitLab URL
|
||||
ja_JP: GitLab URL
|
||||
pt_BR: URL do GitLab
|
||||
zh_Hant: GitLab URL
|
||||
placeholder:
|
||||
en_US: https://gitlab.com
|
||||
zh_Hans: https://gitlab.com
|
||||
ja_JP: https://gitlab.com
|
||||
pt_BR: https://gitlab.com
|
||||
zh_Hant: https://gitlab.com
|
||||
default: https://gitlab.com
|
||||
help:
|
||||
en_US: Your GitLab instance URL (use default for gitlab.com)
|
||||
zh_Hans: 您的 GitLab 实例 URL(对于 gitlab.com 使用默认值)
|
||||
ja_JP: あなたのGitLabインスタンスのURL(gitlab.comの場合はデフォルトを使用)
|
||||
pt_BR: A URL da sua instância do GitLab (use o padrão para gitlab.com)
|
||||
zh_Hant: 您的 GitLab 實例 URL(對於 gitlab.com 使用預設值)
|
||||
datasources:
|
||||
- datasources/gitlab.yaml
|
||||
extra:
|
||||
python:
|
||||
source: provider/gitlab.py
|
||||
Reference in New Issue
Block a user