1 Star 0 Fork 0

yangx282441848/scm

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
webhook.go 29.41 KB
一键复制 编辑 原始数据 按行查看 历史
Your Name 提交于 2021-10-11 10:02 . gitee
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
// Copyright 2017 Drone.IO Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gitlab
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"strconv"
"gitee.com/yangx282441848/scm/scm"
)
type webhookService struct {
client *wrapper
}
func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhook, error) {
data, err := ioutil.ReadAll(
io.LimitReader(req.Body, 10000000),
)
if err != nil {
return nil, err
}
var hook scm.Webhook
switch req.Header.Get("X-Gitlab-Event") {
case "Push Hook", "Tag Push Hook":
hook, err = parsePushHook(data)
case "Issue Hook":
return nil, scm.ErrUnknownEvent
case "Merge Request Hook":
hook, err = parsePullRequestHook(data)
default:
return nil, scm.ErrUnknownEvent
}
if err != nil {
return nil, err
}
// get the gitlab shared token to verify the payload
// authenticity. If no key is provided, no validation
// is performed.
token, err := fn(hook)
if err != nil {
return hook, err
} else if token == "" {
return hook, nil
}
if token != req.Header.Get("X-Gitlab-Token") {
return hook, scm.ErrSignatureInvalid
}
return hook, nil
}
func parsePushHook(data []byte) (scm.Webhook, error) {
src := new(pushHook)
err := json.Unmarshal(data, src)
if err != nil {
return nil, err
}
switch {
case src.ObjectKind == "push" && src.Before == "0000000000000000000000000000000000000000":
// TODO we previously considered returning a
// branch creation hook, however, the push hook
// returns more metadata (commit details).
return convertPushHook(src), nil
case src.ObjectKind == "push" && src.After == "0000000000000000000000000000000000000000":
return converBranchHook(src), nil
case src.ObjectKind == "tag_push" && src.Before == "0000000000000000000000000000000000000000":
// TODO we previously considered returning a
// tag creation hook, however, the push hook
// returns more metadata (commit details).
return convertPushHook(src), nil
case src.ObjectKind == "tag_push" && src.After == "0000000000000000000000000000000000000000":
return convertTagHook(src), nil
default:
return convertPushHook(src), nil
}
}
func parsePullRequestHook(data []byte) (scm.Webhook, error) {
src := new(pullRequestHook)
err := json.Unmarshal(data, src)
if err != nil {
return nil, err
}
switch src.ObjectAttributes.Action {
case "open", "close", "reopen", "merge", "update":
// no-op
default:
return nil, scm.ErrUnknownEvent
}
switch {
default:
return convertPullRequestHook(src), nil
}
}
func convertPushHook(src *pushHook) *scm.PushHook {
var commits []scm.Commit
for _, c := range src.Commits {
commits = append(commits,
scm.Commit{
Sha: c.ID,
Message: c.Message,
Link: c.URL,
Author: scm.Signature{
Name: c.Author.Name,
Email: c.Author.Email,
},
Committer: scm.Signature{
Name: c.Author.Name,
Email: c.Author.Email,
},
})
}
namespace, name := scm.Split(src.Project.PathWithNamespace)
dst := &scm.PushHook{
Ref: scm.ExpandRef(src.Ref, "refs/heads/"),
Before: src.Before,
After: src.After,
Repo: scm.Repository{
ID: strconv.Itoa(src.Project.ID),
Namespace: namespace,
Name: name,
Clone: src.Project.GitHTTPURL,
CloneSSH: src.Project.GitSSHURL,
Link: src.Project.WebURL,
Branch: src.Project.DefaultBranch,
Private: false, // TODO how do we correctly set Private vs Public?
},
Commit: scm.Commit{
Sha: src.CheckoutSha,
Message: "", // NOTE this is set below
Author: scm.Signature{
Login: src.UserUsername,
Name: src.UserName,
Email: src.UserEmail,
Avatar: src.UserAvatar,
},
Committer: scm.Signature{
Login: src.UserUsername,
Name: src.UserName,
Email: src.UserEmail,
Avatar: src.UserAvatar,
},
Link: "", // NOTE this is set below
},
Sender: scm.User{
Login: src.UserUsername,
Name: src.UserName,
Email: src.UserEmail,
Avatar: src.UserAvatar,
},
Commits: commits,
}
if len(src.Commits) > 0 {
// get the last commit (most recent)
dst.Commit.Message = src.Commits[len(src.Commits)-1].Message
dst.Commit.Link = src.Commits[len(src.Commits)-1].URL
}
return dst
}
func converBranchHook(src *pushHook) *scm.BranchHook {
action := scm.ActionCreate
commit := src.After
if src.After == "0000000000000000000000000000000000000000" {
action = scm.ActionDelete
commit = src.Before
}
namespace, name := scm.Split(src.Project.PathWithNamespace)
return &scm.BranchHook{
Action: action,
Ref: scm.Reference{
Name: scm.TrimRef(src.Ref),
Sha: commit,
},
Repo: scm.Repository{
ID: strconv.Itoa(src.Project.ID),
Namespace: namespace,
Name: name,
Clone: src.Project.GitHTTPURL,
CloneSSH: src.Project.GitSSHURL,
Link: src.Project.WebURL,
Branch: src.Project.DefaultBranch,
Private: false, // TODO how do we correctly set Private vs Public?
},
Sender: scm.User{
Login: src.UserUsername,
Name: src.UserName,
Email: src.UserEmail,
Avatar: src.UserAvatar,
},
}
}
func convertTagHook(src *pushHook) *scm.TagHook {
action := scm.ActionCreate
commit := src.After
if src.After == "0000000000000000000000000000000000000000" {
action = scm.ActionDelete
commit = src.Before
}
namespace, name := scm.Split(src.Project.PathWithNamespace)
return &scm.TagHook{
Action: action,
Ref: scm.Reference{
Name: scm.TrimRef(src.Ref),
Sha: commit,
},
Repo: scm.Repository{
ID: strconv.Itoa(src.Project.ID),
Namespace: namespace,
Name: name,
Clone: src.Project.GitHTTPURL,
CloneSSH: src.Project.GitSSHURL,
Link: src.Project.WebURL,
Branch: src.Project.DefaultBranch,
Private: false, // TODO how do we correctly set Private vs Public?
},
Sender: scm.User{
Login: src.UserUsername,
Name: src.UserName,
Email: src.UserEmail,
Avatar: src.UserAvatar,
},
}
}
func convertPullRequestHook(src *pullRequestHook) *scm.PullRequestHook {
action := scm.ActionSync
switch src.ObjectAttributes.Action {
case "open":
action = scm.ActionOpen
case "close":
action = scm.ActionClose
case "reopen":
action = scm.ActionReopen
case "merge":
action = scm.ActionMerge
case "update":
action = scm.ActionSync
}
fork := scm.Join(
src.ObjectAttributes.Source.Namespace,
src.ObjectAttributes.Source.Name,
)
namespace, name := scm.Split(src.Project.PathWithNamespace)
return &scm.PullRequestHook{
Action: action,
PullRequest: scm.PullRequest{
Number: src.ObjectAttributes.Iid,
Title: src.ObjectAttributes.Title,
Body: src.ObjectAttributes.Description,
Sha: src.ObjectAttributes.LastCommit.ID,
Ref: fmt.Sprintf("refs/merge-requests/%d/head", src.ObjectAttributes.Iid),
Source: src.ObjectAttributes.SourceBranch,
Target: src.ObjectAttributes.TargetBranch,
Fork: fork,
Link: src.ObjectAttributes.URL,
Closed: src.ObjectAttributes.State != "opened",
Merged: src.ObjectAttributes.State == "merged",
// Created : src.ObjectAttributes.CreatedAt,
// Updated : src.ObjectAttributes.UpdatedAt, // 2017-12-10 17:01:11 UTC
Author: scm.User{
Login: src.User.Username,
Name: src.User.Name,
Email: "", // TODO how do we get the pull request author email?
Avatar: src.User.AvatarURL,
},
},
Repo: scm.Repository{
ID: strconv.Itoa(src.Project.ID),
Namespace: namespace,
Name: name,
Clone: src.Project.GitHTTPURL,
CloneSSH: src.Project.GitSSHURL,
Link: src.Project.WebURL,
Branch: src.Project.DefaultBranch,
Private: false, // TODO how do we correctly set Private vs Public?
},
Sender: scm.User{
Login: src.User.Username,
Name: src.User.Name,
Email: "", // TODO how do we get the pull request author email?
Avatar: src.User.AvatarURL,
},
}
}
type (
pushHook struct {
ObjectKind string `json:"object_kind"`
EventName string `json:"event_name"`
Before string `json:"before"`
After string `json:"after"`
Ref string `json:"ref"`
CheckoutSha string `json:"checkout_sha"`
Message interface{} `json:"message"`
UserID int `json:"user_id"`
UserName string `json:"user_name"`
UserUsername string `json:"user_username"`
UserEmail string `json:"user_email"`
UserAvatar string `json:"user_avatar"`
ProjectID int `json:"project_id"`
Project struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
WebURL string `json:"web_url"`
AvatarURL interface{} `json:"avatar_url"`
GitSSHURL string `json:"git_ssh_url"`
GitHTTPURL string `json:"git_http_url"`
Namespace string `json:"namespace"`
VisibilityLevel int `json:"visibility_level"`
PathWithNamespace string `json:"path_with_namespace"`
DefaultBranch string `json:"default_branch"`
CiConfigPath interface{} `json:"ci_config_path"`
Homepage string `json:"homepage"`
URL string `json:"url"`
SSHURL string `json:"ssh_url"`
HTTPURL string `json:"http_url"`
} `json:"project"`
Commits []struct {
ID string `json:"id"`
Message string `json:"message"`
Timestamp string `json:"timestamp"`
URL string `json:"url"`
Author struct {
Name string `json:"name"`
Email string `json:"email"`
} `json:"author"`
Added []string `json:"added"`
Modified []interface{} `json:"modified"`
Removed []interface{} `json:"removed"`
} `json:"commits"`
TotalCommitsCount int `json:"total_commits_count"`
Repository struct {
Name string `json:"name"`
URL string `json:"url"`
Description string `json:"description"`
Homepage string `json:"homepage"`
GitHTTPURL string `json:"git_http_url"`
GitSSHURL string `json:"git_ssh_url"`
VisibilityLevel int `json:"visibility_level"`
} `json:"repository"`
}
commentHook struct {
ObjectKind string `json:"object_kind"`
User struct {
Name string `json:"name"`
Username string `json:"username"`
AvatarURL string `json:"avatar_url"`
} `json:"user"`
ProjectID int `json:"project_id"`
Project struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
WebURL string `json:"web_url"`
AvatarURL interface{} `json:"avatar_url"`
GitSSHURL string `json:"git_ssh_url"`
GitHTTPURL string `json:"git_http_url"`
Namespace string `json:"namespace"`
VisibilityLevel int `json:"visibility_level"`
PathWithNamespace string `json:"path_with_namespace"`
DefaultBranch string `json:"default_branch"`
CiConfigPath interface{} `json:"ci_config_path"`
Homepage string `json:"homepage"`
URL string `json:"url"`
SSHURL string `json:"ssh_url"`
HTTPURL string `json:"http_url"`
} `json:"project"`
ObjectAttributes struct {
ID int `json:"id"`
Note string `json:"note"`
NoteableType string `json:"noteable_type"`
AuthorID int `json:"author_id"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
ProjectID int `json:"project_id"`
Attachment interface{} `json:"attachment"`
LineCode string `json:"line_code"`
CommitID string `json:"commit_id"`
NoteableID int `json:"noteable_id"`
StDiff interface{} `json:"st_diff"`
System bool `json:"system"`
UpdatedByID interface{} `json:"updated_by_id"`
Type string `json:"type"`
Position struct {
BaseSha string `json:"base_sha"`
StartSha string `json:"start_sha"`
HeadSha string `json:"head_sha"`
OldPath string `json:"old_path"`
NewPath string `json:"new_path"`
PositionType string `json:"position_type"`
OldLine interface{} `json:"old_line"`
NewLine int `json:"new_line"`
} `json:"position"`
OriginalPosition struct {
BaseSha string `json:"base_sha"`
StartSha string `json:"start_sha"`
HeadSha string `json:"head_sha"`
OldPath string `json:"old_path"`
NewPath string `json:"new_path"`
PositionType string `json:"position_type"`
OldLine interface{} `json:"old_line"`
NewLine int `json:"new_line"`
} `json:"original_position"`
ResolvedAt interface{} `json:"resolved_at"`
ResolvedByID interface{} `json:"resolved_by_id"`
DiscussionID string `json:"discussion_id"`
ChangePosition struct {
BaseSha interface{} `json:"base_sha"`
StartSha interface{} `json:"start_sha"`
HeadSha interface{} `json:"head_sha"`
OldPath interface{} `json:"old_path"`
NewPath interface{} `json:"new_path"`
PositionType string `json:"position_type"`
OldLine interface{} `json:"old_line"`
NewLine interface{} `json:"new_line"`
} `json:"change_position"`
ResolvedByPush interface{} `json:"resolved_by_push"`
URL string `json:"url"`
} `json:"object_attributes"`
Repository struct {
Name string `json:"name"`
URL string `json:"url"`
Description string `json:"description"`
Homepage string `json:"homepage"`
} `json:"repository"`
MergeRequest struct {
AssigneeID interface{} `json:"assignee_id"`
AuthorID int `json:"author_id"`
CreatedAt string `json:"created_at"`
DeletedAt interface{} `json:"deleted_at"`
Description string `json:"description"`
HeadPipelineID interface{} `json:"head_pipeline_id"`
ID int `json:"id"`
Iid int `json:"iid"`
LastEditedAt interface{} `json:"last_edited_at"`
LastEditedByID interface{} `json:"last_edited_by_id"`
MergeCommitSha interface{} `json:"merge_commit_sha"`
MergeError interface{} `json:"merge_error"`
MergeParams interface{} `json:"-"`
MergeStatus string `json:"merge_status"`
MergeUserID interface{} `json:"merge_user_id"`
MergeWhenPipelineSucceeds bool `json:"merge_when_pipeline_succeeds"`
MilestoneID interface{} `json:"milestone_id"`
SourceBranch string `json:"source_branch"`
SourceProjectID int `json:"source_project_id"`
State string `json:"state"`
TargetBranch string `json:"target_branch"`
TargetProjectID int `json:"target_project_id"`
TimeEstimate int `json:"time_estimate"`
Title string `json:"title"`
UpdatedAt string `json:"updated_at"`
UpdatedByID interface{} `json:"updated_by_id"`
URL string `json:"url"`
Source struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
WebURL string `json:"web_url"`
AvatarURL interface{} `json:"avatar_url"`
GitSSHURL string `json:"git_ssh_url"`
GitHTTPURL string `json:"git_http_url"`
Namespace string `json:"namespace"`
VisibilityLevel int `json:"visibility_level"`
PathWithNamespace string `json:"path_with_namespace"`
DefaultBranch string `json:"default_branch"`
CiConfigPath interface{} `json:"ci_config_path"`
Homepage string `json:"homepage"`
URL string `json:"url"`
SSHURL string `json:"ssh_url"`
HTTPURL string `json:"http_url"`
} `json:"source"`
Target struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
WebURL string `json:"web_url"`
AvatarURL interface{} `json:"avatar_url"`
GitSSHURL string `json:"git_ssh_url"`
GitHTTPURL string `json:"git_http_url"`
Namespace string `json:"namespace"`
VisibilityLevel int `json:"visibility_level"`
PathWithNamespace string `json:"path_with_namespace"`
DefaultBranch string `json:"default_branch"`
CiConfigPath interface{} `json:"ci_config_path"`
Homepage string `json:"homepage"`
URL string `json:"url"`
SSHURL string `json:"ssh_url"`
HTTPURL string `json:"http_url"`
} `json:"target"`
LastCommit struct {
ID string `json:"id"`
Message string `json:"message"`
Timestamp string `json:"timestamp"`
URL string `json:"url"`
Author struct {
Name string `json:"name"`
Email string `json:"email"`
} `json:"author"`
} `json:"last_commit"`
WorkInProgress bool `json:"work_in_progress"`
TotalTimeSpent int `json:"total_time_spent"`
HumanTotalTimeSpent interface{} `json:"human_total_time_spent"`
HumanTimeEstimate interface{} `json:"human_time_estimate"`
} `json:"merge_request"`
}
tagHook struct {
ObjectKind string `json:"object_kind"`
EventName string `json:"event_name"`
Before string `json:"before"`
After string `json:"after"`
Ref string `json:"ref"`
CheckoutSha string `json:"checkout_sha"`
Message interface{} `json:"message"`
UserID int `json:"user_id"`
UserName string `json:"user_name"`
UserUsername string `json:"user_username"`
UserEmail string `json:"user_email"`
UserAvatar string `json:"user_avatar"`
ProjectID int `json:"project_id"`
Project struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
WebURL string `json:"web_url"`
AvatarURL interface{} `json:"avatar_url"`
GitSSHURL string `json:"git_ssh_url"`
GitHTTPURL string `json:"git_http_url"`
Namespace string `json:"namespace"`
VisibilityLevel int `json:"visibility_level"`
PathWithNamespace string `json:"path_with_namespace"`
DefaultBranch string `json:"default_branch"`
CiConfigPath interface{} `json:"ci_config_path"`
Homepage string `json:"homepage"`
URL string `json:"url"`
SSHURL string `json:"ssh_url"`
HTTPURL string `json:"http_url"`
} `json:"project"`
Commits []struct {
ID string `json:"id"`
Message string `json:"message"`
Timestamp string `json:"timestamp"`
URL string `json:"url"`
Author struct {
Name string `json:"name"`
Email string `json:"email"`
} `json:"author"`
Added []string `json:"added"`
Modified []interface{} `json:"modified"`
Removed []interface{} `json:"removed"`
} `json:"commits"`
TotalCommitsCount int `json:"total_commits_count"`
Repository struct {
Name string `json:"name"`
URL string `json:"url"`
Description string `json:"description"`
Homepage string `json:"homepage"`
GitHTTPURL string `json:"git_http_url"`
GitSSHURL string `json:"git_ssh_url"`
VisibilityLevel int `json:"visibility_level"`
} `json:"repository"`
}
issueHook struct {
ObjectKind string `json:"object_kind"`
User struct {
Name string `json:"name"`
Username string `json:"username"`
AvatarURL string `json:"avatar_url"`
} `json:"user"`
Project struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
WebURL string `json:"web_url"`
AvatarURL interface{} `json:"avatar_url"`
GitSSHURL string `json:"git_ssh_url"`
GitHTTPURL string `json:"git_http_url"`
Namespace string `json:"namespace"`
VisibilityLevel int `json:"visibility_level"`
PathWithNamespace string `json:"path_with_namespace"`
DefaultBranch string `json:"default_branch"`
CiConfigPath interface{} `json:"ci_config_path"`
Homepage string `json:"homepage"`
URL string `json:"url"`
SSHURL string `json:"ssh_url"`
HTTPURL string `json:"http_url"`
} `json:"project"`
ObjectAttributes struct {
AssigneeID interface{} `json:"assignee_id"`
AuthorID int `json:"author_id"`
BranchName interface{} `json:"branch_name"`
ClosedAt interface{} `json:"closed_at"`
Confidential bool `json:"confidential"`
CreatedAt string `json:"created_at"`
DeletedAt interface{} `json:"deleted_at"`
Description string `json:"description"`
DueDate interface{} `json:"due_date"`
ID int `json:"id"`
Iid int `json:"iid"`
LastEditedAt string `json:"last_edited_at"`
LastEditedByID int `json:"last_edited_by_id"`
MilestoneID interface{} `json:"milestone_id"`
MovedToID interface{} `json:"moved_to_id"`
ProjectID int `json:"project_id"`
RelativePosition int `json:"relative_position"`
State string `json:"state"`
TimeEstimate int `json:"time_estimate"`
Title string `json:"title"`
UpdatedAt string `json:"updated_at"`
UpdatedByID int `json:"updated_by_id"`
URL string `json:"url"`
TotalTimeSpent int `json:"total_time_spent"`
HumanTotalTimeSpent interface{} `json:"human_total_time_spent"`
HumanTimeEstimate interface{} `json:"human_time_estimate"`
AssigneeIds []interface{} `json:"assignee_ids"`
Action string `json:"action"`
} `json:"object_attributes"`
Labels []struct {
ID int `json:"id"`
Title string `json:"title"`
Color string `json:"color"`
ProjectID int `json:"project_id"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
Template bool `json:"template"`
Description string `json:"description"`
Type string `json:"type"`
GroupID interface{} `json:"group_id"`
} `json:"labels"`
Changes struct {
Labels struct {
Previous []interface{} `json:"previous"`
Current []struct {
ID int `json:"id"`
Title string `json:"title"`
Color string `json:"color"`
ProjectID int `json:"project_id"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
Template bool `json:"template"`
Description string `json:"description"`
Type string `json:"type"`
GroupID interface{} `json:"group_id"`
} `json:"current"`
} `json:"labels"`
} `json:"changes"`
Repository struct {
Name string `json:"name"`
URL string `json:"url"`
Description string `json:"description"`
Homepage string `json:"homepage"`
} `json:"repository"`
}
pullRequestHook struct {
ObjectKind string `json:"object_kind"`
User struct {
Name string `json:"name"`
Username string `json:"username"`
AvatarURL string `json:"avatar_url"`
} `json:"user"`
Project struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
WebURL string `json:"web_url"`
AvatarURL interface{} `json:"avatar_url"`
GitSSHURL string `json:"git_ssh_url"`
GitHTTPURL string `json:"git_http_url"`
Namespace string `json:"namespace"`
VisibilityLevel int `json:"visibility_level"`
PathWithNamespace string `json:"path_with_namespace"`
DefaultBranch string `json:"default_branch"`
CiConfigPath interface{} `json:"ci_config_path"`
Homepage string `json:"homepage"`
URL string `json:"url"`
SSHURL string `json:"ssh_url"`
HTTPURL string `json:"http_url"`
} `json:"project"`
ObjectAttributes struct {
AssigneeID interface{} `json:"assignee_id"`
AuthorID int `json:"author_id"`
CreatedAt string `json:"created_at"`
DeletedAt interface{} `json:"deleted_at"`
Description string `json:"description"`
HeadPipelineID interface{} `json:"head_pipeline_id"`
ID int `json:"id"`
Iid int `json:"iid"`
LastEditedAt interface{} `json:"last_edited_at"`
LastEditedByID interface{} `json:"last_edited_by_id"`
MergeCommitSha interface{} `json:"merge_commit_sha"`
MergeError interface{} `json:"merge_error"`
MergeParams interface{} `json:"-"`
MergeStatus string `json:"merge_status"`
MergeUserID interface{} `json:"merge_user_id"`
MergeWhenPipelineSucceeds bool `json:"merge_when_pipeline_succeeds"`
MilestoneID interface{} `json:"milestone_id"`
SourceBranch string `json:"source_branch"`
SourceProjectID int `json:"source_project_id"`
State string `json:"state"`
TargetBranch string `json:"target_branch"`
TargetProjectID int `json:"target_project_id"`
TimeEstimate int `json:"time_estimate"`
Title string `json:"title"`
UpdatedAt string `json:"updated_at"`
UpdatedByID interface{} `json:"updated_by_id"`
URL string `json:"url"`
Source struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
WebURL string `json:"web_url"`
AvatarURL interface{} `json:"avatar_url"`
GitSSHURL string `json:"git_ssh_url"`
GitHTTPURL string `json:"git_http_url"`
Namespace string `json:"namespace"`
VisibilityLevel int `json:"visibility_level"`
PathWithNamespace string `json:"path_with_namespace"`
DefaultBranch string `json:"default_branch"`
CiConfigPath interface{} `json:"ci_config_path"`
Homepage string `json:"homepage"`
URL string `json:"url"`
SSHURL string `json:"ssh_url"`
HTTPURL string `json:"http_url"`
} `json:"source"`
Target struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
WebURL string `json:"web_url"`
AvatarURL interface{} `json:"avatar_url"`
GitSSHURL string `json:"git_ssh_url"`
GitHTTPURL string `json:"git_http_url"`
Namespace string `json:"namespace"`
VisibilityLevel int `json:"visibility_level"`
PathWithNamespace string `json:"path_with_namespace"`
DefaultBranch string `json:"default_branch"`
CiConfigPath interface{} `json:"ci_config_path"`
Homepage string `json:"homepage"`
URL string `json:"url"`
SSHURL string `json:"ssh_url"`
HTTPURL string `json:"http_url"`
} `json:"target"`
LastCommit struct {
ID string `json:"id"`
Message string `json:"message"`
Timestamp string `json:"timestamp"`
URL string `json:"url"`
Author struct {
Name string `json:"name"`
Email string `json:"email"`
} `json:"author"`
} `json:"last_commit"`
WorkInProgress bool `json:"work_in_progress"`
TotalTimeSpent int `json:"total_time_spent"`
HumanTotalTimeSpent interface{} `json:"human_total_time_spent"`
HumanTimeEstimate interface{} `json:"human_time_estimate"`
Action string `json:"action"`
} `json:"object_attributes"`
Labels []interface{} `json:"labels"`
Changes struct {
} `json:"changes"`
Repository struct {
Name string `json:"name"`
URL string `json:"url"`
Description string `json:"description"`
Homepage string `json:"homepage"`
} `json:"repository"`
}
)
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/yangx282441848/scm.git
git@gitee.com:yangx282441848/scm.git
yangx282441848
scm
scm
v1.16.6

搜索帮助