适配gitea 取消gogs(没有对应接口支持)
This commit is contained in:
@ -57,6 +57,10 @@ type GitConfig struct {
|
|||||||
Name string `mapstructure:"name"` // 平台名称
|
Name string `mapstructure:"name"` // 平台名称
|
||||||
Type string `mapstructure:"type"` // 平台类型
|
Type string `mapstructure:"type"` // 平台类型
|
||||||
Token string `mapstructure:"token"` // 访问令牌
|
Token string `mapstructure:"token"` // 访问令牌
|
||||||
|
Username string `mapstructure:"username"` // 用户名(用于基本认证)
|
||||||
|
Password string `mapstructure:"password"` // 密码(用于基本认证)
|
||||||
|
SudoUser string `mapstructure:"sudo_user"` // sudo 用户
|
||||||
|
TOTP string `mapstructure:"totp"` // TOTP 令牌
|
||||||
Secret string `mapstructure:"webhook_secret"` // webhook 密钥
|
Secret string `mapstructure:"webhook_secret"` // webhook 密钥
|
||||||
APIBase string `mapstructure:"api_base"` // API 基础 URL
|
APIBase string `mapstructure:"api_base"` // API 基础 URL
|
||||||
SignatureHeader string `mapstructure:"signature_header"` // webhook 签名的 header 名称
|
SignatureHeader string `mapstructure:"signature_header"` // webhook 签名的 header 名称
|
||||||
@ -148,7 +152,10 @@ func Save(newConfig *Config) error {
|
|||||||
if err := yamlEncoder.Encode(configMap); err != nil {
|
if err := yamlEncoder.Encode(configMap); err != nil {
|
||||||
// 如果保存失败,恢复备份
|
// 如果保存失败,恢复备份
|
||||||
if _, err := os.Stat(backupFile); err == nil {
|
if _, err := os.Stat(backupFile); err == nil {
|
||||||
os.Rename(backupFile, "config.yaml")
|
err := os.Rename(backupFile, "config.yaml")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return fmt.Errorf("save config failed: %w", err)
|
return fmt.Errorf("save config failed: %w", err)
|
||||||
}
|
}
|
||||||
@ -188,6 +195,10 @@ func (c *Config) ToMap() map[string]interface{} {
|
|||||||
"name": platform.Name,
|
"name": platform.Name,
|
||||||
"type": platform.Type,
|
"type": platform.Type,
|
||||||
"token": platform.Token,
|
"token": platform.Token,
|
||||||
|
"username": platform.Username,
|
||||||
|
"password": platform.Password,
|
||||||
|
"sudo_user": platform.SudoUser,
|
||||||
|
"totp": platform.TOTP,
|
||||||
"webhook_secret": platform.Secret,
|
"webhook_secret": platform.Secret,
|
||||||
"api_base": platform.APIBase,
|
"api_base": platform.APIBase,
|
||||||
"signature_header": platform.SignatureHeader,
|
"signature_header": platform.SignatureHeader,
|
||||||
@ -237,6 +248,7 @@ func (c *Config) ToMapHtml() map[string]interface{} {
|
|||||||
"name": platform.Name,
|
"name": platform.Name,
|
||||||
"type": platform.Type,
|
"type": platform.Type,
|
||||||
"token": platform.Token,
|
"token": platform.Token,
|
||||||
|
"username": platform.Username,
|
||||||
"webhook_secret": platform.Secret,
|
"webhook_secret": platform.Secret,
|
||||||
"api_base": platform.APIBase,
|
"api_base": platform.APIBase,
|
||||||
"signature_header": platform.SignatureHeader,
|
"signature_header": platform.SignatureHeader,
|
||||||
|
@ -112,29 +112,36 @@ func (h *WebhookHandler) parseWebhookEvent(c *gin.Context, platform string) (ser
|
|||||||
return nil, fmt.Errorf("未找到事件类型 header: %s", platformConfig.EventHeader)
|
return nil, fmt.Errorf("未找到事件类型 header: %s", platformConfig.EventHeader)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 创建认证配置
|
||||||
|
auth := &platforms.AuthConfig{
|
||||||
|
Token: platformConfig.Token,
|
||||||
|
Username: platformConfig.Username,
|
||||||
|
Password: platformConfig.Password,
|
||||||
|
SudoUser: platformConfig.SudoUser,
|
||||||
|
TOTP: platformConfig.TOTP,
|
||||||
|
UseBasicAuth: platformConfig.Username != "" && platformConfig.Password != "",
|
||||||
|
UseSudoHeader: platformConfig.SudoUser != "",
|
||||||
|
UseSudoParam: platformConfig.SudoUser != "",
|
||||||
|
UseTOTPHeader: platformConfig.TOTP != "",
|
||||||
|
}
|
||||||
|
|
||||||
var event services.WebhookEvent
|
var event services.WebhookEvent
|
||||||
switch platformConfig.Type {
|
switch platformConfig.Type {
|
||||||
case "gogs":
|
|
||||||
event = platforms.NewGogsEvent(
|
|
||||||
platformConfig.APIBase,
|
|
||||||
platformConfig.Token,
|
|
||||||
eventType,
|
|
||||||
)
|
|
||||||
case "gitea":
|
case "gitea":
|
||||||
event = platforms.NewGiteaEvent(
|
event = platforms.NewGiteaEvent(
|
||||||
platformConfig.APIBase,
|
platformConfig.APIBase,
|
||||||
platformConfig.Token,
|
auth,
|
||||||
eventType,
|
eventType,
|
||||||
)
|
)
|
||||||
//case "gitee":
|
// case "gitee":
|
||||||
// event = &platforms.GiteeEvent{
|
// event = platforms.NewGiteeEvent(
|
||||||
// ApiBase: platformConfig.APIBase,
|
// platformConfig.APIBase,
|
||||||
// Token: platformConfig.Token,
|
// auth,
|
||||||
// }
|
// )
|
||||||
case "gitlab":
|
case "gitlab":
|
||||||
event = platforms.NewGitlabEvent(
|
event = platforms.NewGitlabEvent(
|
||||||
platformConfig.APIBase,
|
platformConfig.APIBase,
|
||||||
platformConfig.Token,
|
auth,
|
||||||
eventType,
|
eventType,
|
||||||
)
|
)
|
||||||
default:
|
default:
|
||||||
|
@ -9,20 +9,43 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type AuthConfig struct {
|
||||||
|
Token string
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
SudoUser string
|
||||||
|
TOTP string
|
||||||
|
UseBasicAuth bool
|
||||||
|
UseSudoHeader bool
|
||||||
|
UseSudoParam bool
|
||||||
|
UseTOTPHeader bool
|
||||||
|
}
|
||||||
|
|
||||||
type httpClient struct {
|
type httpClient struct {
|
||||||
url string
|
url string
|
||||||
token string
|
auth *AuthConfig
|
||||||
client *http.Client
|
client *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func newHTTPClient(baseURL, token string) *httpClient {
|
func newHTTPClient(baseURL string, authConfig *AuthConfig) *httpClient {
|
||||||
return &httpClient{
|
return &httpClient{
|
||||||
url: baseURL,
|
url: baseURL,
|
||||||
token: token,
|
auth: authConfig,
|
||||||
client: &http.Client{},
|
client: &http.Client{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *httpClient) setAuthHeaders(req *http.Request) {
|
||||||
|
if c.auth == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置 Token 认证
|
||||||
|
if c.auth.Token != "" {
|
||||||
|
req.Header.Set("Authorization", "token "+c.auth.Token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *httpClient) get(path string, result interface{}) error {
|
func (c *httpClient) get(path string, result interface{}) error {
|
||||||
url := fmt.Sprintf("%s%s", c.url, path)
|
url := fmt.Sprintf("%s%s", c.url, path)
|
||||||
log.Printf("发送 GET 请求: url=%s", url)
|
log.Printf("发送 GET 请求: url=%s", url)
|
||||||
@ -34,9 +57,7 @@ func (c *httpClient) get(path string, result interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
if c.token != "" {
|
c.setAuthHeaders(req)
|
||||||
req.Header.Set("Authorization", "token "+c.token)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.client.Do(req)
|
resp, err := c.client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -77,9 +98,7 @@ func (c *httpClient) post(path string, data interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
if c.token != "" {
|
c.setAuthHeaders(req)
|
||||||
req.Header.Set("Authorization", "token "+c.token)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.client.Do(req)
|
resp, err := c.client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -113,6 +132,8 @@ func (c *httpClient) getWithHeaders(path string, result interface{}, headers map
|
|||||||
req.Header.Set(key, value)
|
req.Header.Set(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.setAuthHeaders(req)
|
||||||
|
|
||||||
resp, err := c.client.Do(req)
|
resp, err := c.client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("发送 GET 请求失败: url=%s, error=%v", url, err)
|
log.Printf("发送 GET 请求失败: url=%s, error=%v", url, err)
|
||||||
@ -156,6 +177,8 @@ func (c *httpClient) postWithHeaders(path string, data interface{}, headers map[
|
|||||||
req.Header.Set(key, value)
|
req.Header.Set(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.setAuthHeaders(req)
|
||||||
|
|
||||||
resp, err := c.client.Do(req)
|
resp, err := c.client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("发送 POST 请求失败: url=%s, error=%v", url, err)
|
log.Printf("发送 POST 请求失败: url=%s, error=%v", url, err)
|
||||||
|
@ -10,40 +10,191 @@ import (
|
|||||||
|
|
||||||
type GiteaEvent struct {
|
type GiteaEvent struct {
|
||||||
apiBase string
|
apiBase string
|
||||||
token string
|
auth *AuthConfig
|
||||||
Event string
|
Event string
|
||||||
client *httpClient
|
client *httpClient
|
||||||
|
|
||||||
|
Secret string `json:"secret"`
|
||||||
Ref string `json:"ref"`
|
Ref string `json:"ref"`
|
||||||
Before string `json:"before"`
|
Before string `json:"before"`
|
||||||
After string `json:"after"`
|
After string `json:"after"`
|
||||||
CompareURL string `json:"compare_url"`
|
CompareURL string `json:"compare_url"`
|
||||||
Commits []struct {
|
Commits []struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"sha"`
|
||||||
Message string `json:"message"`
|
Message string `json:"commit.message"`
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
Author Author `json:"author"`
|
HTMLURL string `json:"html_url"`
|
||||||
Committer Author `json:"committer"`
|
Created string `json:"created"`
|
||||||
Timestamp string `json:"timestamp"`
|
Author struct {
|
||||||
|
Active bool `json:"active"`
|
||||||
|
AvatarURL string `json:"avatar_url"`
|
||||||
|
Created string `json:"created"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
FollowersCount int `json:"followers_count"`
|
||||||
|
FollowingCount int `json:"following_count"`
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
ID int `json:"id"`
|
||||||
|
IsAdmin bool `json:"is_admin"`
|
||||||
|
Language string `json:"language"`
|
||||||
|
LastLogin string `json:"last_login"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Login string `json:"login"`
|
||||||
|
LoginName string `json:"login_name"`
|
||||||
|
ProhibitLogin bool `json:"prohibit_login"`
|
||||||
|
Restricted bool `json:"restricted"`
|
||||||
|
SourceID int `json:"source_id"`
|
||||||
|
Visibility string `json:"visibility"`
|
||||||
|
Website string `json:"website"`
|
||||||
|
} `json:"author"`
|
||||||
|
Committer struct {
|
||||||
|
Active bool `json:"active"`
|
||||||
|
AvatarURL string `json:"avatar_url"`
|
||||||
|
Created string `json:"created"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
FollowersCount int `json:"followers_count"`
|
||||||
|
FollowingCount int `json:"following_count"`
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
ID int `json:"id"`
|
||||||
|
IsAdmin bool `json:"is_admin"`
|
||||||
|
Language string `json:"language"`
|
||||||
|
LastLogin string `json:"last_login"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Login string `json:"login"`
|
||||||
|
LoginName string `json:"login_name"`
|
||||||
|
ProhibitLogin bool `json:"prohibit_login"`
|
||||||
|
Restricted bool `json:"restricted"`
|
||||||
|
SourceID int `json:"source_id"`
|
||||||
|
Visibility string `json:"visibility"`
|
||||||
|
Website string `json:"website"`
|
||||||
|
} `json:"committer"`
|
||||||
|
Commit struct {
|
||||||
|
Author struct {
|
||||||
|
Date string `json:"date"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"author"`
|
||||||
|
Committer struct {
|
||||||
|
Date string `json:"date"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"committer"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Tree struct {
|
||||||
|
Created string `json:"created"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
} `json:"tree"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Verification struct {
|
||||||
|
Payload string `json:"payload"`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
Signature string `json:"signature"`
|
||||||
|
Signer struct {
|
||||||
|
Email string `json:"email"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
} `json:"signer"`
|
||||||
|
Verified bool `json:"verified"`
|
||||||
|
} `json:"verification"`
|
||||||
|
} `json:"commit"`
|
||||||
|
Files []struct {
|
||||||
|
Filename string `json:"filename"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
} `json:"files"`
|
||||||
|
Parents []struct {
|
||||||
|
Created string `json:"created"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
} `json:"parents"`
|
||||||
|
Stats struct {
|
||||||
|
Additions int `json:"additions"`
|
||||||
|
Deletions int `json:"deletions"`
|
||||||
|
Total int `json:"total"`
|
||||||
|
} `json:"stats"`
|
||||||
} `json:"commits"`
|
} `json:"commits"`
|
||||||
Repository struct {
|
Repository struct {
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
FullName string `json:"full_name"`
|
FullName string `json:"full_name"`
|
||||||
HTMLURL string `json:"html_url"`
|
Description string `json:"description"`
|
||||||
Private bool `json:"private"`
|
Private bool `json:"private"`
|
||||||
|
Fork bool `json:"fork"`
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
SSHURL string `json:"ssh_url"`
|
||||||
|
CloneURL string `json:"clone_url"`
|
||||||
|
Website string `json:"website"`
|
||||||
|
StarsCount int `json:"stars_count"`
|
||||||
|
ForksCount int `json:"forks_count"`
|
||||||
|
WatchersCount int `json:"watchers_count"`
|
||||||
|
OpenIssuesCount int `json:"open_issues_count"`
|
||||||
|
DefaultBranch string `json:"default_branch"`
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
|
Owner struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Login string `json:"login"`
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
AvatarURL string `json:"avatar_url"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
} `json:"owner"`
|
||||||
} `json:"repository"`
|
} `json:"repository"`
|
||||||
|
Pusher struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Login string `json:"login"`
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
AvatarURL string `json:"avatar_url"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
} `json:"pusher"`
|
||||||
|
Sender struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Login string `json:"login"`
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
AvatarURL string `json:"avatar_url"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
} `json:"sender"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGiteaEvent 创建 Gitea 事件
|
// NewGiteaEvent 创建 Gitea 事件
|
||||||
func NewGiteaEvent(apiBase, token string, event string) *GiteaEvent {
|
func NewGiteaEvent(apiBase string, auth *AuthConfig, event string) *GiteaEvent {
|
||||||
return &GiteaEvent{
|
return &GiteaEvent{
|
||||||
apiBase: apiBase,
|
apiBase: apiBase,
|
||||||
token: token,
|
auth: auth,
|
||||||
Event: event,
|
Event: event,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 定义 Gitea commit 响应的结构
|
||||||
|
type giteaCommitResponse struct {
|
||||||
|
Commit struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
Author struct {
|
||||||
|
Date string `json:"date"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"author"`
|
||||||
|
Committer struct {
|
||||||
|
Date string `json:"date"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"committer"`
|
||||||
|
} `json:"commit"`
|
||||||
|
Files []struct {
|
||||||
|
Filename string `json:"filename"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
Additions int `json:"additions"`
|
||||||
|
Deletions int `json:"deletions"`
|
||||||
|
Changes int `json:"changes"`
|
||||||
|
Content string `json:"content"`
|
||||||
|
} `json:"files"`
|
||||||
|
}
|
||||||
|
|
||||||
func (e *GiteaEvent) ExtractChanges() (*types.CodeChanges, error) {
|
func (e *GiteaEvent) ExtractChanges() (*types.CodeChanges, error) {
|
||||||
// 检查是否有提交记录
|
// 检查是否有提交记录
|
||||||
if len(e.Commits) == 0 {
|
if len(e.Commits) == 0 {
|
||||||
@ -53,14 +204,14 @@ func (e *GiteaEvent) ExtractChanges() (*types.CodeChanges, error) {
|
|||||||
|
|
||||||
// 检查是否跳过代码审查
|
// 检查是否跳过代码审查
|
||||||
for _, commit := range e.Commits {
|
for _, commit := range e.Commits {
|
||||||
if strings.Contains(commit.Message, "[skip codereview]") {
|
if strings.Contains(commit.Commit.Message, "[skip codereview]") {
|
||||||
log.Printf("跳过代码审查: commit=%s", commit.ID)
|
log.Printf("跳过代码审查: commit=%s", commit.ID)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.client == nil {
|
if e.client == nil {
|
||||||
e.client = newHTTPClient(e.apiBase, e.token)
|
e.client = newHTTPClient(e.apiBase, e.auth)
|
||||||
log.Printf("初始化 HTTP 客户端: url=%s", e.apiBase)
|
log.Printf("初始化 HTTP 客户端: url=%s", e.apiBase)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,89 +224,46 @@ func (e *GiteaEvent) ExtractChanges() (*types.CodeChanges, error) {
|
|||||||
|
|
||||||
for _, commit := range e.Commits {
|
for _, commit := range e.Commits {
|
||||||
// 直接获取 diff 内容
|
// 直接获取 diff 内容
|
||||||
apiPath := fmt.Sprintf("/api/v1/repos/%s/git/commits/%s.diff?access_token=%s", e.Repository.FullName, commit.ID, e.token)
|
apiPath := fmt.Sprintf("/api/v1/repos/%s/%s/git/commits/%s", e.Repository.Owner.Login, e.Repository.Name, e.After)
|
||||||
var diffContent string
|
var diffContent giteaCommitResponse
|
||||||
|
|
||||||
if err := e.client.get(apiPath, &diffContent); err != nil {
|
if err := e.client.get(apiPath, &diffContent); err != nil {
|
||||||
log.Printf("获取提交详情失败: commit=%s, error=%v", commit.ID, err)
|
log.Printf("获取提交详情失败: commit=%s, error=%v", commit.ID, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 去除首尾空白
|
// 处理每个文件的变更
|
||||||
diffContent = strings.TrimSpace(diffContent)
|
for _, file := range diffContent.Files {
|
||||||
if diffContent == "" {
|
|
||||||
log.Printf("提交没有变更内容: commit=%s", commit.ID)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析 diff 内容
|
|
||||||
diffBlocks := strings.Split(diffContent, "diff --git ")
|
|
||||||
// 去除空块
|
|
||||||
for _, block := range diffBlocks {
|
|
||||||
if strings.TrimSpace(block) == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 移除 'diff --git ' 前缀
|
|
||||||
block = strings.TrimPrefix(block, "diff --git ")
|
|
||||||
|
|
||||||
// 解析文件名和变更类型
|
|
||||||
lines := strings.Split(block, "\n")
|
|
||||||
if len(lines) < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取文件名
|
|
||||||
filename := ""
|
|
||||||
status := "modified"
|
|
||||||
for _, line := range lines {
|
|
||||||
if strings.HasPrefix(line, "--- a/") {
|
|
||||||
filename = strings.TrimPrefix(line, "--- a/")
|
|
||||||
break
|
|
||||||
} else if strings.HasPrefix(line, "+++ b/") {
|
|
||||||
filename = strings.TrimPrefix(line, "+++ b/")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果没有找到文件名,跳过
|
|
||||||
if filename == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确定变更类型
|
|
||||||
if strings.Contains(block, "new file mode") {
|
|
||||||
status = "added"
|
|
||||||
} else if strings.Contains(block, "deleted file mode") {
|
|
||||||
status = "deleted"
|
|
||||||
} else if strings.Contains(block, "rename from") {
|
|
||||||
status = "renamed"
|
|
||||||
}
|
|
||||||
|
|
||||||
var content strings.Builder
|
var content strings.Builder
|
||||||
content.WriteString(fmt.Sprintf("### 变更说明\n"))
|
content.WriteString(fmt.Sprintf("### 变更说明\n"))
|
||||||
content.WriteString(fmt.Sprintf("提交信息: %s\n\n", commit.Message))
|
content.WriteString(fmt.Sprintf("提交信息: %s\n\n", diffContent.Commit.Message))
|
||||||
|
|
||||||
switch status {
|
status := "modified"
|
||||||
|
switch file.Status {
|
||||||
case "added":
|
case "added":
|
||||||
content.WriteString(fmt.Sprintf("新增文件: %s\n\n", filename))
|
status = "added"
|
||||||
case "modified":
|
content.WriteString(fmt.Sprintf("新增文件: %s\n\n", file.Filename))
|
||||||
content.WriteString(fmt.Sprintf("修改文件: %s\n\n", filename))
|
case "removed":
|
||||||
case "deleted":
|
status = "deleted"
|
||||||
content.WriteString(fmt.Sprintf("删除文件: %s\n\n", filename))
|
content.WriteString(fmt.Sprintf("删除文件: %s\n\n", file.Filename))
|
||||||
case "renamed":
|
case "renamed":
|
||||||
content.WriteString(fmt.Sprintf("重命名文件: %s\n\n", filename))
|
status = "renamed"
|
||||||
|
content.WriteString(fmt.Sprintf("重命名文件: %s\n\n", file.Filename))
|
||||||
|
default:
|
||||||
|
content.WriteString(fmt.Sprintf("修改文件: %s\n\n", file.Filename))
|
||||||
}
|
}
|
||||||
|
|
||||||
content.WriteString("### 变更内容\n")
|
if file.Content != "" {
|
||||||
content.WriteString("```diff\n")
|
content.WriteString("### 变更内容\n")
|
||||||
content.WriteString(block)
|
content.WriteString("```diff\n")
|
||||||
content.WriteString("\n```\n")
|
content.WriteString(file.Content)
|
||||||
|
content.WriteString("\n```\n")
|
||||||
|
}
|
||||||
|
|
||||||
changes.Files = append(changes.Files, types.FileChange{
|
changes.Files = append(changes.Files, types.FileChange{
|
||||||
Path: filename,
|
Path: file.Filename,
|
||||||
Content: content.String(),
|
Content: content.String(),
|
||||||
Type: parseFileType(status),
|
Type: utils.ParseFileType(status),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,11 +273,11 @@ func (e *GiteaEvent) ExtractChanges() (*types.CodeChanges, error) {
|
|||||||
|
|
||||||
func (e *GiteaEvent) PostComments(result *types.ReviewResult) error {
|
func (e *GiteaEvent) PostComments(result *types.ReviewResult) error {
|
||||||
if e.client == nil {
|
if e.client == nil {
|
||||||
e.client = newHTTPClient(e.apiBase, e.token)
|
e.client = newHTTPClient(e.apiBase, e.auth)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建 issue
|
// 创建 issue
|
||||||
path := fmt.Sprintf("/api/v1/repos/%s/issues", e.Repository.FullName)
|
path := fmt.Sprintf("/api/v1/repos/%s/%s/issues", e.Repository.Owner.Login, e.Repository.Name)
|
||||||
issueData := map[string]interface{}{
|
issueData := map[string]interface{}{
|
||||||
"title": fmt.Sprintf("AI 代码审查 - %s", e.After[:7]),
|
"title": fmt.Sprintf("AI 代码审查 - %s", e.After[:7]),
|
||||||
"body": utils.FormatReviewResult(result),
|
"body": utils.FormatReviewResult(result),
|
||||||
|
@ -2,11 +2,15 @@ package platforms
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"code-review/services/types"
|
"code-review/services/types"
|
||||||
|
"code-review/utils"
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GiteeEvent Gitee 平台的 webhook 事件
|
// GiteeEvent Gitee 平台的 webhook 事件
|
||||||
type GiteeEvent struct {
|
type GiteeEvent struct {
|
||||||
|
apiBase string
|
||||||
|
auth *AuthConfig
|
||||||
|
Event string
|
||||||
client *httpClient
|
client *httpClient
|
||||||
Action string `json:"action"`
|
Action string `json:"action"`
|
||||||
ActionDesc string `json:"action_desc"`
|
ActionDesc string `json:"action_desc"`
|
||||||
@ -43,9 +47,11 @@ type GiteeEvent struct {
|
|||||||
} `json:"pull_request"`
|
} `json:"pull_request"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGiteeEvent(baseURL, token string) *GiteeEvent {
|
func NewGiteeEvent(baseURL string, auth *AuthConfig) *GiteeEvent {
|
||||||
return &GiteeEvent{
|
return &GiteeEvent{
|
||||||
client: newHTTPClient(baseURL, token),
|
apiBase: baseURL,
|
||||||
|
auth: auth,
|
||||||
|
client: newHTTPClient(baseURL, auth),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,16 +77,7 @@ func (e *GiteeEvent) ExtractChanges() (*types.CodeChanges, error) {
|
|||||||
OldPath: change.OldPath,
|
OldPath: change.OldPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
switch change.Type {
|
fileChange.Type = utils.ParseFileType(change.Type)
|
||||||
case "added":
|
|
||||||
fileChange.Type = types.Added
|
|
||||||
case "modified":
|
|
||||||
fileChange.Type = types.Modified
|
|
||||||
case "deleted":
|
|
||||||
fileChange.Type = types.Deleted
|
|
||||||
case "renamed":
|
|
||||||
fileChange.Type = types.Renamed
|
|
||||||
}
|
|
||||||
|
|
||||||
changes.Files = append(changes.Files, fileChange)
|
changes.Files = append(changes.Files, fileChange)
|
||||||
}
|
}
|
||||||
@ -90,12 +87,12 @@ func (e *GiteeEvent) ExtractChanges() (*types.CodeChanges, error) {
|
|||||||
|
|
||||||
func (e *GiteeEvent) PostComments(result *types.ReviewResult) error {
|
func (e *GiteeEvent) PostComments(result *types.ReviewResult) error {
|
||||||
if e.client == nil {
|
if e.client == nil {
|
||||||
return fmt.Errorf("client not initialized")
|
e.client = newHTTPClient(e.apiBase, e.auth)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, comment := range result.Comments {
|
for _, comment := range result.Comments {
|
||||||
body := map[string]interface{}{
|
body := map[string]interface{}{
|
||||||
"access_token": e.client.token,
|
"access_token": e.auth.Token,
|
||||||
"body": fmt.Sprintf("**Code Review Comment**\n\nFile: %s\nLine: %d\nSeverity: %s\n\n%s",
|
"body": fmt.Sprintf("**Code Review Comment**\n\nFile: %s\nLine: %d\nSeverity: %s\n\n%s",
|
||||||
comment.Path,
|
comment.Path,
|
||||||
comment.Line,
|
comment.Line,
|
||||||
@ -119,7 +116,7 @@ func (e *GiteeEvent) PostComments(result *types.ReviewResult) error {
|
|||||||
// 发送总结评论
|
// 发送总结评论
|
||||||
if result.Summary != "" {
|
if result.Summary != "" {
|
||||||
body := map[string]interface{}{
|
body := map[string]interface{}{
|
||||||
"access_token": e.client.token,
|
"access_token": e.auth.Token,
|
||||||
"body": fmt.Sprintf("**Code Review Summary**\n\n%s", result.Summary),
|
"body": fmt.Sprintf("**Code Review Summary**\n\n%s", result.Summary),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
// GitlabEvent Gitlab 平台的 webhook 事件
|
// GitlabEvent Gitlab 平台的 webhook 事件
|
||||||
type GitlabEvent struct {
|
type GitlabEvent struct {
|
||||||
apiBase string
|
apiBase string
|
||||||
token string
|
auth *AuthConfig
|
||||||
Event string
|
Event string
|
||||||
client *httpClient
|
client *httpClient
|
||||||
|
|
||||||
@ -34,10 +34,10 @@ type GitlabEvent struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewGitlabEvent 创建 GitLab 事件实例
|
// NewGitlabEvent 创建 GitLab 事件实例
|
||||||
func NewGitlabEvent(baseURL, token string, event string) *GitlabEvent {
|
func NewGitlabEvent(baseURL string, auth *AuthConfig, event string) *GitlabEvent {
|
||||||
return &GitlabEvent{
|
return &GitlabEvent{
|
||||||
apiBase: baseURL,
|
apiBase: baseURL,
|
||||||
token: token,
|
auth: auth,
|
||||||
Event: event,
|
Event: event,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,7 +70,7 @@ func (e *GitlabEvent) ExtractChanges() (*types.CodeChanges, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if e.client == nil {
|
if e.client == nil {
|
||||||
e.client = newHTTPClient(e.apiBase, e.token)
|
e.client = newHTTPClient(e.apiBase, e.auth)
|
||||||
log.Printf("初始化 HTTP 客户端: url=%s", e.apiBase)
|
log.Printf("初始化 HTTP 客户端: url=%s", e.apiBase)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ func (e *GitlabEvent) ExtractChanges() (*types.CodeChanges, error) {
|
|||||||
e.Project.ID, commit.ID)
|
e.Project.ID, commit.ID)
|
||||||
|
|
||||||
headers := map[string]string{
|
headers := map[string]string{
|
||||||
"PRIVATE-TOKEN": e.token,
|
"PRIVATE-TOKEN": e.auth.Token,
|
||||||
}
|
}
|
||||||
|
|
||||||
var diffs []gitlabDiff
|
var diffs []gitlabDiff
|
||||||
@ -109,7 +109,7 @@ func (e *GitlabEvent) ExtractChanges() (*types.CodeChanges, error) {
|
|||||||
changes.Files = append(changes.Files, types.FileChange{
|
changes.Files = append(changes.Files, types.FileChange{
|
||||||
Path: diff.NewPath,
|
Path: diff.NewPath,
|
||||||
Content: diff.Diff,
|
Content: diff.Diff,
|
||||||
Type: parseFileType(status),
|
Type: utils.ParseFileType(status),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,7 +119,7 @@ func (e *GitlabEvent) ExtractChanges() (*types.CodeChanges, error) {
|
|||||||
|
|
||||||
func (e *GitlabEvent) PostComments(result *types.ReviewResult) error {
|
func (e *GitlabEvent) PostComments(result *types.ReviewResult) error {
|
||||||
if e.client == nil {
|
if e.client == nil {
|
||||||
e.client = newHTTPClient(e.apiBase, e.token)
|
e.client = newHTTPClient(e.apiBase, e.auth)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建 issue
|
// 创建 issue
|
||||||
@ -130,7 +130,7 @@ func (e *GitlabEvent) PostComments(result *types.ReviewResult) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
headers := map[string]string{
|
headers := map[string]string{
|
||||||
"PRIVATE-TOKEN": e.token,
|
"PRIVATE-TOKEN": e.auth.Token,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := e.client.postWithHeaders(path, issueData, headers); err != nil {
|
if err := e.client.postWithHeaders(path, issueData, headers); err != nil {
|
||||||
|
@ -1,245 +0,0 @@
|
|||||||
package platforms
|
|
||||||
|
|
||||||
import (
|
|
||||||
"code-review/services/types"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GogsEvent Gogs 平台的 webhook 事件
|
|
||||||
type GogsEvent struct {
|
|
||||||
apiBase string
|
|
||||||
token string
|
|
||||||
Event string // 事件类型
|
|
||||||
client *httpClient
|
|
||||||
Ref string `json:"ref"`
|
|
||||||
Before string `json:"before"`
|
|
||||||
After string `json:"after"`
|
|
||||||
CompareURL string `json:"compare_url"`
|
|
||||||
Commits []struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Message string `json:"message"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
Author Author `json:"author"`
|
|
||||||
Committer Author `json:"committer"`
|
|
||||||
Timestamp string `json:"timestamp"`
|
|
||||||
} `json:"commits"`
|
|
||||||
CommitDetail struct {
|
|
||||||
Files []struct {
|
|
||||||
Filename string `json:"filename"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
Additions int `json:"additions"`
|
|
||||||
Deletions int `json:"deletions"`
|
|
||||||
Patch string `json:"patch"`
|
|
||||||
} `json:"files"`
|
|
||||||
}
|
|
||||||
Repository struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
Owner Author `json:"owner"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
FullName string `json:"full_name"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Private bool `json:"private"`
|
|
||||||
Fork bool `json:"fork"`
|
|
||||||
HTMLURL string `json:"html_url"`
|
|
||||||
SSHURL string `json:"ssh_url"`
|
|
||||||
CloneURL string `json:"clone_url"`
|
|
||||||
Website string `json:"website"`
|
|
||||||
StarsCount int `json:"stars_count"`
|
|
||||||
ForksCount int `json:"forks_count"`
|
|
||||||
WatchersCount int `json:"watchers_count"`
|
|
||||||
OpenIssuesCount int `json:"open_issues_count"`
|
|
||||||
DefaultBranch string `json:"default_branch"`
|
|
||||||
CreatedAt string `json:"created_at"`
|
|
||||||
UpdatedAt string `json:"updated_at"`
|
|
||||||
} `json:"repository"`
|
|
||||||
Pusher Author `json:"pusher"`
|
|
||||||
Sender Author `json:"sender"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Author struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
Login string `json:"login"`
|
|
||||||
FullName string `json:"full_name"`
|
|
||||||
Email string `json:"email"`
|
|
||||||
AvatarURL string `json:"avatar_url"`
|
|
||||||
Username string `json:"username"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGogsEvent 创建 Gogs 事件
|
|
||||||
func NewGogsEvent(apiBase, token string, event string) *GogsEvent {
|
|
||||||
return &GogsEvent{
|
|
||||||
apiBase: apiBase,
|
|
||||||
token: token,
|
|
||||||
Event: event,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *GogsEvent) ExtractChanges() (*types.CodeChanges, error) {
|
|
||||||
// 检查是否有提交记录
|
|
||||||
if len(e.Commits) == 0 {
|
|
||||||
log.Printf("没有提交记录,跳过代码审查")
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否跳过代码审查
|
|
||||||
for _, commit := range e.Commits {
|
|
||||||
if strings.Contains(commit.Message, "[skip codereview]") {
|
|
||||||
log.Printf("跳过代码审查: commit=%s", commit.ID)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if e.client == nil {
|
|
||||||
e.client = newHTTPClient(e.apiBase, e.token)
|
|
||||||
log.Printf("初始化 HTTP 客户端: url=%s", e.apiBase)
|
|
||||||
}
|
|
||||||
|
|
||||||
changes := &types.CodeChanges{
|
|
||||||
Repository: e.Repository.FullName,
|
|
||||||
Branch: e.Ref,
|
|
||||||
CommitID: e.After,
|
|
||||||
Files: make([]types.FileChange, 0),
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, commit := range e.Commits {
|
|
||||||
// 直接获取 diff 内容
|
|
||||||
apiPath := fmt.Sprintf("/api/v1/repos/%s/git/commits/%s.diff?access_token=%s", e.Repository.FullName, commit.ID, e.token)
|
|
||||||
var diffContent string
|
|
||||||
|
|
||||||
if err := e.client.get(apiPath, &diffContent); err != nil {
|
|
||||||
log.Printf("获取提交详情失败: commit=%s, error=%v", commit.ID, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 去除首尾空白
|
|
||||||
diffContent = strings.TrimSpace(diffContent)
|
|
||||||
if diffContent == "" {
|
|
||||||
log.Printf("提交没有变更内容: commit=%s", commit.ID)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析 diff 内容
|
|
||||||
diffBlocks := strings.Split(diffContent, "diff --git ")
|
|
||||||
// 去除空块
|
|
||||||
for _, block := range diffBlocks {
|
|
||||||
if strings.TrimSpace(block) == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 移除 'diff --git ' 前缀
|
|
||||||
block = strings.TrimPrefix(block, "diff --git ")
|
|
||||||
|
|
||||||
// 解析文件名和变更类型
|
|
||||||
lines := strings.Split(block, "\n")
|
|
||||||
if len(lines) < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取文件名
|
|
||||||
filename := ""
|
|
||||||
status := "modified"
|
|
||||||
for _, line := range lines {
|
|
||||||
if strings.HasPrefix(line, "--- a/") {
|
|
||||||
filename = strings.TrimPrefix(line, "--- a/")
|
|
||||||
break
|
|
||||||
} else if strings.HasPrefix(line, "+++ b/") {
|
|
||||||
filename = strings.TrimPrefix(line, "+++ b/")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果没有找到文件名,跳过
|
|
||||||
if filename == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确定变更类型
|
|
||||||
if strings.Contains(block, "new file mode") {
|
|
||||||
status = "added"
|
|
||||||
} else if strings.Contains(block, "deleted file mode") {
|
|
||||||
status = "deleted"
|
|
||||||
} else if strings.Contains(block, "rename from") {
|
|
||||||
status = "renamed"
|
|
||||||
}
|
|
||||||
|
|
||||||
var content strings.Builder
|
|
||||||
content.WriteString(fmt.Sprintf("### 变更说明\n"))
|
|
||||||
content.WriteString(fmt.Sprintf("提交信息: %s\n\n", commit.Message))
|
|
||||||
|
|
||||||
switch status {
|
|
||||||
case "added":
|
|
||||||
content.WriteString(fmt.Sprintf("新增文件: %s\n\n", filename))
|
|
||||||
case "modified":
|
|
||||||
content.WriteString(fmt.Sprintf("修改文件: %s\n\n", filename))
|
|
||||||
case "deleted":
|
|
||||||
content.WriteString(fmt.Sprintf("删除文件: %s\n\n", filename))
|
|
||||||
case "renamed":
|
|
||||||
content.WriteString(fmt.Sprintf("重命名文件: %s\n\n", filename))
|
|
||||||
}
|
|
||||||
|
|
||||||
content.WriteString("### 变更内容\n")
|
|
||||||
content.WriteString("```diff\n")
|
|
||||||
content.WriteString(block)
|
|
||||||
content.WriteString("\n```\n")
|
|
||||||
|
|
||||||
changes.Files = append(changes.Files, types.FileChange{
|
|
||||||
Path: filename,
|
|
||||||
Content: content.String(),
|
|
||||||
Type: parseFileType(status),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return changes, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *GogsEvent) PostComments(result *types.ReviewResult) error {
|
|
||||||
if e.client == nil {
|
|
||||||
e.client = newHTTPClient(e.apiBase, e.token)
|
|
||||||
log.Printf("初始化 HTTP 客户端: url=%s", e.apiBase)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建 issue 评论
|
|
||||||
issueBody := fmt.Sprintf("**代码审查报告**\n\n提交: %s\n\n", e.After)
|
|
||||||
for _, comment := range result.Comments {
|
|
||||||
issueBody += fmt.Sprintf("### 文件: %s\n\n%s\n\n", comment.Path, comment.Content)
|
|
||||||
}
|
|
||||||
if result.Summary != "" {
|
|
||||||
issueBody += fmt.Sprintf("\n### 总结\n\n%s", result.Summary)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建 issue
|
|
||||||
createIssuePath := fmt.Sprintf("/api/v1/repos/%s/issues", e.Repository.FullName)
|
|
||||||
issueData := map[string]interface{}{
|
|
||||||
"title": fmt.Sprintf("代码审查: %s", e.After[:7]),
|
|
||||||
"body": issueBody,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := e.client.post(createIssuePath, issueData); err != nil {
|
|
||||||
log.Printf("创建 issue 失败: path=%s, error=%v", createIssuePath, err)
|
|
||||||
return fmt.Errorf("创建 issue 失败: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("成功创建 issue: path=%s, commitID=%s", createIssuePath, e.After[:7])
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *GogsEvent) GetPlatform() string {
|
|
||||||
return "gogs"
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseFileType(t string) types.ChangeType {
|
|
||||||
switch t {
|
|
||||||
case "add":
|
|
||||||
return types.Added
|
|
||||||
case "modify":
|
|
||||||
return types.Modified
|
|
||||||
case "delete":
|
|
||||||
return types.Deleted
|
|
||||||
default:
|
|
||||||
return types.Modified
|
|
||||||
}
|
|
||||||
}
|
|
@ -399,7 +399,7 @@
|
|||||||
<select class="form-control" name="git[${index}].type" required
|
<select class="form-control" name="git[${index}].type" required
|
||||||
title="请选择 Git 平台类型">
|
title="请选择 Git 平台类型">
|
||||||
<option value="gitlab" ${platform.type === 'gitlab' ? 'selected' : ''}>GitLab</option>
|
<option value="gitlab" ${platform.type === 'gitlab' ? 'selected' : ''}>GitLab</option>
|
||||||
<option value="gitee" ${platform.type === 'gitee' ? 'selected' : ''}>Gitee</option>
|
<option value="gitea" ${platform.type === 'gitea' ? 'selected' : ''}>Gitea</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
${createPasswordField(`git[${index}].token`, platform.token, 'Token', '请输入平台访问令牌')}
|
${createPasswordField(`git[${index}].token`, platform.token, 'Token', '请输入平台访问令牌')}
|
||||||
@ -510,8 +510,8 @@
|
|||||||
token: platform.token,
|
token: platform.token,
|
||||||
webhook_secret: platform.webhook_secret,
|
webhook_secret: platform.webhook_secret,
|
||||||
api_base: platform.api_base,
|
api_base: platform.api_base,
|
||||||
signature_header: platform.type === 'gitlab' ? 'X-Gitlab-Token' : 'X-Gitee-Token',
|
signature_header: platform.type === 'gitlab' ? 'X-Gitlab-Token' : 'X-Gitea-Signature',
|
||||||
event_header: platform.type === 'gitlab' ? 'X-Gitlab-Event' : 'X-Gitee-Event'
|
event_header: platform.type === 'gitlab' ? 'X-Gitlab-Event' : 'X-Gitea-Event'
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -87,3 +87,19 @@ func FormatReviewResult(result *types.ReviewResult) string {
|
|||||||
|
|
||||||
return body.String()
|
return body.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseFileType 将文件变更类型字符串转换为 ChangeType
|
||||||
|
func ParseFileType(t string) types.ChangeType {
|
||||||
|
switch t {
|
||||||
|
case "add", "added":
|
||||||
|
return types.Added
|
||||||
|
case "modify", "modified":
|
||||||
|
return types.Modified
|
||||||
|
case "delete", "deleted":
|
||||||
|
return types.Deleted
|
||||||
|
case "renamed":
|
||||||
|
return types.Renamed
|
||||||
|
default:
|
||||||
|
return types.Modified
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user