From 5cedc956e94e2d6726c4193c61f0825371390578 Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 7 Feb 2024 01:45:00 +0100 Subject: [PATCH] Ignore gitlab merge request events without code changes (#3338) Closes #3320 From the gitlab docs at: https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#merge-request-events > The field object_attributes.oldrev is only available when there are actual code changes --- server/forge/gitlab/gitlab.go | 4 + server/forge/gitlab/gitlab_test.go | 31 +++ server/forge/gitlab/testdata/hooks.go | 290 ++++++++++++++++++++++++++ 3 files changed, 325 insertions(+) diff --git a/server/forge/gitlab/gitlab.go b/server/forge/gitlab/gitlab.go index d46848487..eb13aedce 100644 --- a/server/forge/gitlab/gitlab.go +++ b/server/forge/gitlab/gitlab.go @@ -644,6 +644,10 @@ func (g *GitLab) Hook(ctx context.Context, req *http.Request) (*model.Repo, *mod switch event := parsed.(type) { case *gitlab.MergeEvent: + // https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#merge-request-events + if event.ObjectAttributes.OldRev == "" && event.ObjectAttributes.Action != "open" && event.ObjectAttributes.Action != "close" && event.ObjectAttributes.Action != "merge" { + return nil, nil, &forge_types.ErrIgnoreEvent{Event: string(eventType), Reason: "no code changes"} + } mergeIID, repo, pipeline, err := convertMergeRequestHook(event, req) if err != nil { return nil, nil, err diff --git a/server/forge/gitlab/gitlab_test.go b/server/forge/gitlab/gitlab_test.go index 88fff4f29..4b69ba716 100644 --- a/server/forge/gitlab/gitlab_test.go +++ b/server/forge/gitlab/gitlab_test.go @@ -27,6 +27,7 @@ import ( "github.com/stretchr/testify/assert" "go.woodpecker-ci.org/woodpecker/v2/server/forge/gitlab/testdata" + "go.woodpecker-ci.org/woodpecker/v2/server/forge/types" "go.woodpecker-ci.org/woodpecker/v2/server/model" ) @@ -203,6 +204,36 @@ func Test_GitLab(t *testing.T) { } }) + g.It("Should ignore merge request hook without changes", func() { + req, _ := http.NewRequest( + testdata.ServiceHookMethod, + testdata.ServiceHookURL.String(), + bytes.NewReader(testdata.HookPullRequestWithoutChanges), + ) + req.Header = testdata.ServiceHookHeaders + + // TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles + hookRepo, pipeline, err := client.Hook(ctx, req) + assert.Nil(t, hookRepo) + assert.Nil(t, pipeline) + assert.ErrorIs(t, err, &types.ErrIgnoreEvent{}) + }) + + g.It("Should ignore merge request approval", func() { + req, _ := http.NewRequest( + testdata.ServiceHookMethod, + testdata.ServiceHookURL.String(), + bytes.NewReader(testdata.HookPullRequestApproved), + ) + req.Header = testdata.ServiceHookHeaders + + // TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles + hookRepo, pipeline, err := client.Hook(ctx, req) + assert.Nil(t, hookRepo) + assert.Nil(t, pipeline) + assert.ErrorIs(t, err, &types.ErrIgnoreEvent{}) + }) + g.It("Should parse merge request hook when MR closed", func() { req, _ := http.NewRequest( testdata.ServiceHookMethod, diff --git a/server/forge/gitlab/testdata/hooks.go b/server/forge/gitlab/testdata/hooks.go index 7f5fe5569..f60df4b43 100644 --- a/server/forge/gitlab/testdata/hooks.go +++ b/server/forge/gitlab/testdata/hooks.go @@ -323,6 +323,296 @@ var HookPullRequest = []byte(` } `) +var HookPullRequestWithoutChanges = []byte(` +{ + "object_kind": "merge_request", + "event_type": "merge_request", + "user": { + "id": 2251488, + "name": "Anbraten", + "username": "anbraten", + "avatar_url": "https://secure.gravatar.com/avatar/fc9b6fe77c6b732a02925a62a81f05a0?s=80&d=identicon", + "email": "some@mail.info" + }, + "project": { + "id": 32059612, + "name": "woodpecker", + "description": "", + "web_url": "https://gitlab.com/anbraten/woodpecker", + "avatar_url": "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", + "git_ssh_url": "git@gitlab.com:anbraten/woodpecker.git", + "git_http_url": "https://gitlab.com/anbraten/woodpecker.git", + "namespace": "Anbraten", + "visibility_level": 20, + "path_with_namespace": "anbraten/woodpecker", + "default_branch": "main", + "ci_config_path": "", + "homepage": "https://gitlab.com/anbraten/woodpecker", + "url": "git@gitlab.com:anbraten/woodpecker.git", + "ssh_url": "git@gitlab.com:anbraten/woodpecker.git", + "http_url": "https://gitlab.com/anbraten/woodpecker.git" + }, + "object_attributes": { + "assignee_id": 2251488, + "author_id": 2251488, + "created_at": "2022-01-10 15:23:41 UTC", + "description": "", + "head_pipeline_id": 449733536, + "id": 134400602, + "iid": 3, + "last_edited_at": "2022-01-17 15:46:23 UTC", + "last_edited_by_id": 2251488, + "merge_commit_sha": null, + "merge_error": null, + "merge_params": { + "force_remove_source_branch": "1" + }, + "merge_status": "unchecked", + "merge_user_id": null, + "merge_when_pipeline_succeeds": false, + "milestone_id": null, + "source_branch": "anbraten-main-patch-05373", + "source_project_id": 32059612, + "state_id": 1, + "target_branch": "main", + "target_project_id": 32059612, + "time_estimate": 0, + "title": "Update client.go 🎉", + "updated_at": "2022-01-17 15:47:39 UTC", + "updated_by_id": 2251488, + "url": "https://gitlab.com/anbraten/woodpecker/-/merge_requests/3", + "source": { + "id": 32059612, + "name": "woodpecker", + "description": "", + "web_url": "https://gitlab.com/anbraten/woodpecker", + "avatar_url": null, + "git_ssh_url": "git@gitlab.com:anbraten/woodpecker.git", + "git_http_url": "https://gitlab.com/anbraten/woodpecker.git", + "namespace": "Anbraten", + "visibility_level": 20, + "path_with_namespace": "anbraten/woodpecker", + "default_branch": "main", + "ci_config_path": "", + "homepage": "https://gitlab.com/anbraten/woodpecker", + "url": "git@gitlab.com:anbraten/woodpecker.git", + "ssh_url": "git@gitlab.com:anbraten/woodpecker.git", + "http_url": "https://gitlab.com/anbraten/woodpecker.git" + }, + "target": { + "id": 32059612, + "name": "woodpecker", + "description": "", + "web_url": "https://gitlab.com/anbraten/woodpecker", + "avatar_url": "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", + "git_ssh_url": "git@gitlab.com:anbraten/woodpecker.git", + "git_http_url": "https://gitlab.com/anbraten/woodpecker.git", + "namespace": "Anbraten", + "visibility_level": 20, + "path_with_namespace": "anbraten/woodpecker", + "default_branch": "main", + "ci_config_path": "", + "homepage": "https://gitlab.com/anbraten/woodpecker", + "url": "git@gitlab.com:anbraten/woodpecker.git", + "ssh_url": "git@gitlab.com:anbraten/woodpecker.git", + "http_url": "https://gitlab.com/anbraten/woodpecker.git" + }, + "last_commit": { + "id": "c136499ec574e1034b24c5d306de9acda3005367", + "message": "Update folder/todo.txt", + "title": "Update folder/todo.txt", + "timestamp": "2022-01-17T15:47:38+00:00", + "url": "https://gitlab.com/anbraten/woodpecker/-/commit/c136499ec574e1034b24c5d306de9acda3005367", + "author": { + "name": "Anbraten", + "email": "some@mail.info" + } + }, + "work_in_progress": false, + "total_time_spent": 0, + "time_change": 0, + "human_total_time_spent": null, + "human_time_change": null, + "human_time_estimate": null, + "assignee_ids": [ + 2251488 + ], + "state": "opened", + "blocking_discussions_resolved": true, + "action": "update" + }, + "labels": [ + + ], + "changes": { + "updated_at": { + "previous": "2022-01-17 15:46:23 UTC", + "current": "2022-01-17 15:47:39 UTC" + } + }, + "repository": { + "name": "woodpecker", + "url": "git@gitlab.com:anbraten/woodpecker.git", + "description": "", + "homepage": "https://gitlab.com/anbraten/woodpecker" + }, + "assignees": [ + { + "id": 2251488, + "name": "Anbraten", + "username": "anbraten", + "avatar_url": "https://secure.gravatar.com/avatar/fc9b6fe77c6b732a02925a62a81f05a0?s=80&d=identicon", + "email": "some@mail.info" + } + ] +} +`) + +var HookPullRequestApproved = []byte(` +{ + "object_kind": "merge_request", + "event_type": "merge_request", + "user": { + "id": 2251488, + "name": "Anbraten", + "username": "anbraten", + "avatar_url": "https://secure.gravatar.com/avatar/fc9b6fe77c6b732a02925a62a81f05a0?s=80&d=identicon", + "email": "some@mail.info" + }, + "project": { + "id": 32059612, + "name": "woodpecker", + "description": "", + "web_url": "https://gitlab.com/anbraten/woodpecker", + "avatar_url": "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", + "git_ssh_url": "git@gitlab.com:anbraten/woodpecker.git", + "git_http_url": "https://gitlab.com/anbraten/woodpecker.git", + "namespace": "Anbraten", + "visibility_level": 20, + "path_with_namespace": "anbraten/woodpecker", + "default_branch": "main", + "ci_config_path": "", + "homepage": "https://gitlab.com/anbraten/woodpecker", + "url": "git@gitlab.com:anbraten/woodpecker.git", + "ssh_url": "git@gitlab.com:anbraten/woodpecker.git", + "http_url": "https://gitlab.com/anbraten/woodpecker.git" + }, + "object_attributes": { + "assignee_id": 2251488, + "author_id": 2251488, + "created_at": "2022-01-10 15:23:41 UTC", + "description": "", + "head_pipeline_id": 449733536, + "id": 134400602, + "iid": 3, + "last_edited_at": "2022-01-17 15:46:23 UTC", + "last_edited_by_id": 2251488, + "merge_commit_sha": null, + "merge_error": null, + "merge_params": { + "force_remove_source_branch": "1" + }, + "merge_status": "unchecked", + "merge_user_id": null, + "merge_when_pipeline_succeeds": false, + "milestone_id": null, + "source_branch": "anbraten-main-patch-05373", + "source_project_id": 32059612, + "state_id": 1, + "target_branch": "main", + "target_project_id": 32059612, + "time_estimate": 0, + "title": "Update client.go 🎉", + "updated_at": "2022-01-17 15:47:39 UTC", + "updated_by_id": 2251488, + "url": "https://gitlab.com/anbraten/woodpecker/-/merge_requests/3", + "source": { + "id": 32059612, + "name": "woodpecker", + "description": "", + "web_url": "https://gitlab.com/anbraten/woodpecker", + "avatar_url": null, + "git_ssh_url": "git@gitlab.com:anbraten/woodpecker.git", + "git_http_url": "https://gitlab.com/anbraten/woodpecker.git", + "namespace": "Anbraten", + "visibility_level": 20, + "path_with_namespace": "anbraten/woodpecker", + "default_branch": "main", + "ci_config_path": "", + "homepage": "https://gitlab.com/anbraten/woodpecker", + "url": "git@gitlab.com:anbraten/woodpecker.git", + "ssh_url": "git@gitlab.com:anbraten/woodpecker.git", + "http_url": "https://gitlab.com/anbraten/woodpecker.git" + }, + "target": { + "id": 32059612, + "name": "woodpecker", + "description": "", + "web_url": "https://gitlab.com/anbraten/woodpecker", + "avatar_url": "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", + "git_ssh_url": "git@gitlab.com:anbraten/woodpecker.git", + "git_http_url": "https://gitlab.com/anbraten/woodpecker.git", + "namespace": "Anbraten", + "visibility_level": 20, + "path_with_namespace": "anbraten/woodpecker", + "default_branch": "main", + "ci_config_path": "", + "homepage": "https://gitlab.com/anbraten/woodpecker", + "url": "git@gitlab.com:anbraten/woodpecker.git", + "ssh_url": "git@gitlab.com:anbraten/woodpecker.git", + "http_url": "https://gitlab.com/anbraten/woodpecker.git" + }, + "last_commit": { + "id": "c136499ec574e1034b24c5d306de9acda3005367", + "message": "Update folder/todo.txt", + "title": "Update folder/todo.txt", + "timestamp": "2022-01-17T15:47:38+00:00", + "url": "https://gitlab.com/anbraten/woodpecker/-/commit/c136499ec574e1034b24c5d306de9acda3005367", + "author": { + "name": "Anbraten", + "email": "some@mail.info" + } + }, + "work_in_progress": false, + "total_time_spent": 0, + "time_change": 0, + "human_total_time_spent": null, + "human_time_change": null, + "human_time_estimate": null, + "assignee_ids": [ + 2251488 + ], + "state": "opened", + "blocking_discussions_resolved": true, + "action": "approved" + }, + "labels": [ + + ], + "changes": { + "updated_at": { + "previous": "2022-01-17 15:46:23 UTC", + "current": "2022-01-17 15:47:39 UTC" + } + }, + "repository": { + "name": "woodpecker", + "url": "git@gitlab.com:anbraten/woodpecker.git", + "description": "", + "homepage": "https://gitlab.com/anbraten/woodpecker" + }, + "assignees": [ + { + "id": 2251488, + "name": "Anbraten", + "username": "anbraten", + "avatar_url": "https://secure.gravatar.com/avatar/fc9b6fe77c6b732a02925a62a81f05a0?s=80&d=identicon", + "email": "some@mail.info" + } + ] +} +`) + var HookPullRequestClosed = []byte(` { "object_kind": "merge_request",