Skip to content

Commit

Permalink
[GH-262] Merge request approval subscription (#307)
Browse files Browse the repository at this point in the history
Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com>
  • Loading branch information
MatthewDorner and mickmister authored Mar 22, 2023
1 parent 21beec5 commit ad1d267
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 7 deletions.
2 changes: 1 addition & 1 deletion server/subscription/subscription.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ var allFeatures = map[string]bool{
"pipeline": true,
"tag": true,
"pull_reviews": true,
// "label:": true,//particular case for label:XXX
// "label:": true,//particular case for label:XXX
}

type Subscription struct {
Expand Down
12 changes: 7 additions & 5 deletions server/webhook/constants.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package webhook

const (
actionOpen = "open"
actionClose = "close"
actionMerge = "merge"
actionReopen = "reopen"
actionUpdate = "update"
actionOpen = "open"
actionClose = "close"
actionMerge = "merge"
actionReopen = "reopen"
actionUpdate = "update"
actionApproved = "approved"
actionUnapproved = "unapproved"

stateOpened = "opened"
stateClosed = "closed"
Expand Down
8 changes: 8 additions & 0 deletions server/webhook/merge_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ func (w *webhook) handleDMMergeRequest(event *gitlab.MergeEvent) ([]*HandleWebho
case actionUpdate:
// TODO not enough check (opened/update) to say assigned to you...
message = fmt.Sprintf("[%s](%s) assigned you to merge request [%s!%v](%s)", senderGitlabUsername, w.gitlabRetreiver.GetUserURL(senderGitlabUsername), event.ObjectAttributes.Target.PathWithNamespace, event.ObjectAttributes.IID, event.ObjectAttributes.URL)
case actionApproved:
message = fmt.Sprintf("[%s](%s) approved your merge request [%s!%v](%s)", senderGitlabUsername, w.gitlabRetreiver.GetUserURL(senderGitlabUsername), event.ObjectAttributes.Target.PathWithNamespace, event.ObjectAttributes.IID, event.ObjectAttributes.URL)
case actionUnapproved:
message = fmt.Sprintf("[%s](%s) requested changes to your merge request [%s!%v](%s)", senderGitlabUsername, w.gitlabRetreiver.GetUserURL(senderGitlabUsername), event.ObjectAttributes.Target.PathWithNamespace, event.ObjectAttributes.IID, event.ObjectAttributes.URL)
}
case stateClosed:
message = fmt.Sprintf("[%s](%s) closed your merge request [%s!%v](%s)", senderGitlabUsername, w.gitlabRetreiver.GetUserURL(senderGitlabUsername), event.ObjectAttributes.Target.PathWithNamespace, event.ObjectAttributes.IID, event.ObjectAttributes.URL)
Expand Down Expand Up @@ -83,6 +87,10 @@ func (w *webhook) handleChannelMergeRequest(ctx context.Context, event *gitlab.M
message = fmt.Sprintf("[%s](%s) Merge request [!%v %s](%s) was closed by [%s](%s)", repo.PathWithNamespace, repo.WebURL, pr.IID, pr.Title, pr.URL, senderGitlabUsername, w.gitlabRetreiver.GetUserURL(senderGitlabUsername))
case actionReopen:
message = fmt.Sprintf("[%s](%s) Merge request [!%v %s](%s) was reopened by [%s](%s)", repo.PathWithNamespace, repo.WebURL, pr.IID, pr.Title, pr.URL, senderGitlabUsername, w.gitlabRetreiver.GetUserURL(senderGitlabUsername))
case actionApproved:
message = fmt.Sprintf("[%s](%s) Merge request [!%v %s](%s) was approved by [%s](%s)", repo.PathWithNamespace, repo.WebURL, pr.IID, pr.Title, pr.URL, senderGitlabUsername, w.gitlabRetreiver.GetUserURL(senderGitlabUsername))
case actionUnapproved:
message = fmt.Sprintf("[%s](%s) Merge request [!%v %s](%s) changes were requested by [%s](%s)", repo.PathWithNamespace, repo.WebURL, pr.IID, pr.Title, pr.URL, senderGitlabUsername, w.gitlabRetreiver.GetUserURL(senderGitlabUsername))
}

if len(message) > 0 {
Expand Down
127 changes: 127 additions & 0 deletions server/webhook/merge_request_fixture_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -833,3 +833,130 @@ const MergeRequestMerged = `{
"avatar_url":"https://www.gravatar.com/avatar/c6b552a4cd47f7cf1701ea5b650cd2e3?s=80\\u0026d=identicon"
}
}`

const ApproveMergeRequest = `{
"object_kind":"merge_request",
"event_type":"merge_request",
"user":{
"name":"manland",
"username":"manland",
"avatar_url":"https://www.gravatar.com/avatar/c6b552a4cd47f7cf1701ea5b650cd2e3?s=80\\u0026d=identicon"
},
"project":{
"id":24,
"name":"webhook",
"description":"",
"web_url":"http://localhost:3000/manland/webhook",
"avatar_url":null,
"git_ssh_url":"ssh://rmaneschi@localhost:2222/manland/webhook.git",
"git_http_url":"http://localhost:3000/manland/webhook.git",
"namespace":"manland",
"visibility_level":20,
"path_with_namespace":"manland/webhook",
"default_branch":"master",
"ci_config_path":null,
"homepage":"http://localhost:3000/manland/webhook",
"url":"ssh://rmaneschi@localhost:2222/manland/webhook.git",
"ssh_url":"ssh://rmaneschi@localhost:2222/manland/webhook.git",
"http_url":"http://localhost:3000/manland/webhook.git"
},
"object_attributes":{
"assignee_id":50,
"author_id":1,
"created_at":"2019-04-03 21:07:32 UTC",
"description":"test open merge request",
"head_pipeline_id":57,
"id":35,
"iid":4,
"last_edited_at":null,
"last_edited_by_id":null,
"merge_commit_sha":null,
"merge_error":null,
"merge_params":{
"force_remove_source_branch":null
},
"merge_status":"can_be_merged",
"merge_user_id":null,
"merge_when_pipeline_succeeds":false,
"milestone_id":null,
"source_branch":"master",
"source_project_id":25,
"state":"opened",
"target_branch":"master",
"target_project_id":24,
"time_estimate":0,
"title":"Master",
"updated_at":"2019-04-03 21:29:41 UTC",
"updated_by_id":null,
"url":"http://localhost:3000/manland/webhook/merge_requests/4",
"source":{
"id":25,
"name":"webhook",
"description":"",
"web_url":"http://localhost:3000/root/webhook",
"avatar_url":null,
"git_ssh_url":"ssh://rmaneschi@localhost:2222/root/webhook.git",
"git_http_url":"http://localhost:3000/root/webhook.git",
"namespace":"root",
"visibility_level":20,
"path_with_namespace":"root/webhook",
"default_branch":"master",
"ci_config_path":null,
"homepage":"http://localhost:3000/root/webhook",
"url":"ssh://rmaneschi@localhost:2222/root/webhook.git",
"ssh_url":"ssh://rmaneschi@localhost:2222/root/webhook.git",
"http_url":"http://localhost:3000/root/webhook.git"
},
"target":{
"id":24,
"name":"webhook",
"description":"",
"web_url":"http://localhost:3000/manland/webhook",
"avatar_url":null,
"git_ssh_url":"ssh://rmaneschi@localhost:2222/manland/webhook.git",
"git_http_url":"http://localhost:3000/manland/webhook.git",
"namespace":"manland",
"visibility_level":20,
"path_with_namespace":"manland/webhook",
"default_branch":"master",
"ci_config_path":null,
"homepage":"http://localhost:3000/manland/webhook",
"url":"ssh://rmaneschi@localhost:2222/manland/webhook.git",
"ssh_url":"ssh://rmaneschi@localhost:2222/manland/webhook.git",
"http_url":"http://localhost:3000/manland/webhook.git"
},
"last_commit":{
"id":"1fd967c14f8265a6056525c343d984ce56472d5c",
"message":"Update README.md",
"timestamp":"2019-04-03T21:04:58Z",
"url":"http://localhost:3000/manland/webhook/commit/1fd967c14f8265a6056525c343d984ce56472d5c",
"author":{
"name":"Administrator",
"email":"admin@example.com"
}
},
"work_in_progress":false,
"total_time_spent":0,
"human_total_time_spent":null,
"human_time_estimate":null,
"action":"approved"
},
"labels":[],
"changes":{
"updated_at":{
"previous":"2019-04-03 21:07:32 UTC",
"current":"2019-04-03 21:29:41 UTC"
}
},
"repository":{
"name":"webhook",
"url":"ssh://rmaneschi@localhost:2222/manland/webhook.git",
"description":"",
"homepage":"http://localhost:3000/manland/webhook"
},
"assignee":{
"name":"manland",
"username":"manland",
"avatar_url":"https://www.gravatar.com/avatar/c6b552a4cd47f7cf1701ea5b650cd2e3?s=80\\u0026d=identicon"
}
}`
34 changes: 34 additions & 0 deletions server/webhook/merge_request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,40 @@ var testDataMergeRequest = []testDataMergeRequestStr{
ToChannels: []string{"channel1"},
From: "manland",
}},
}, {
testTitle: "manland approve root merge-request and display in channel1",
fixture: ApproveMergeRequest,
gitlabRetreiver: newFakeWebhook([]*subscription.Subscription{
{ChannelID: "channel1", CreatorID: "1", Features: "merges", Repository: "manland/webhook"},
}),
res: []*HandleWebhook{{
Message: "[manland](http://my.gitlab.com/manland) approved your merge request [manland/webhook!4](http://localhost:3000/manland/webhook/merge_requests/4)",
ToUsers: []string{"root"},
ToChannels: []string{},
From: "manland",
}, {
Message: "[manland/webhook](http://localhost:3000/manland/webhook) Merge request [!4 Master](http://localhost:3000/manland/webhook/merge_requests/4) was approved by [manland](http://my.gitlab.com/manland)",
ToUsers: []string{},
ToChannels: []string{"channel1"},
From: "manland",
}},
}, {
testTitle: "manland unapprove root merge-request and display in channel1",
fixture: strings.ReplaceAll(ApproveMergeRequest, "approved", "unapproved"),
gitlabRetreiver: newFakeWebhook([]*subscription.Subscription{
{ChannelID: "channel1", CreatorID: "1", Features: "merges", Repository: "manland/webhook"},
}),
res: []*HandleWebhook{{
Message: "[manland](http://my.gitlab.com/manland) requested changes to your merge request [manland/webhook!4](http://localhost:3000/manland/webhook/merge_requests/4)",
ToUsers: []string{"root"},
ToChannels: []string{},
From: "manland",
}, {
Message: "[manland/webhook](http://localhost:3000/manland/webhook) Merge request [!4 Master](http://localhost:3000/manland/webhook/merge_requests/4) changes were requested by [manland](http://my.gitlab.com/manland)",
ToUsers: []string{},
ToChannels: []string{"channel1"},
From: "manland",
}},
}, {
testTitle: "root close its own MR without assignee and display in channel1",
fixture: CloseMergeRequestByCreator,
Expand Down
2 changes: 1 addition & 1 deletion server/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func cleanWebhookHandlers(handlers []*HandleWebhook) []*HandleWebhook {
func cleanWebhookHandlerTo(handler *HandleWebhook) *HandleWebhook {
users := map[string]bool{}
for _, v := range handler.ToUsers {
if handler.From != v && v != "" { // don't send message to author or unknown user
if handler.From != v && v != "" { // don't send message to webhook sender or unknown user
users[v] = true
}
}
Expand Down

0 comments on commit ad1d267

Please sign in to comment.