Spaces:
Paused
Paused
| // Copyright 2022 Woodpecker Authors | |
| // Copyright 2018 Drone.IO Inc. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package github | |
| import ( | |
| "bytes" | |
| "net/http" | |
| "sort" | |
| "strings" | |
| "testing" | |
| "github.com/stretchr/testify/assert" | |
| "go.woodpecker-ci.org/woodpecker/v3/server/forge/github/fixtures" | |
| "go.woodpecker-ci.org/woodpecker/v3/server/forge/types" | |
| "go.woodpecker-ci.org/woodpecker/v3/server/model" | |
| ) | |
| const ( | |
| hookEvent = "X-GitHub-Event" | |
| hookDeploy = "deployment" | |
| hookPush = "push" | |
| hookPull = "pull_request" | |
| hookRelease = "release" | |
| ) | |
| func testHookRequest(payload []byte, event string) *http.Request { | |
| buf := bytes.NewBuffer(payload) | |
| req, _ := http.NewRequest(http.MethodPost, "/hook", buf) | |
| req.Header = http.Header{} | |
| req.Header.Set(hookEvent, event) | |
| return req | |
| } | |
| func Test_parseHook(t *testing.T) { | |
| t.Run("ignore unsupported hook events", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookPullRequest), "issues") | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Empty(t, pc) | |
| assert.Empty(t, cc) | |
| assert.Nil(t, r) | |
| assert.Nil(t, b) | |
| assert.Nil(t, p) | |
| assert.ErrorIs(t, err, &types.ErrIgnoreEvent{}) | |
| }) | |
| t.Run("skip skip push hook when action is deleted", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookPushDeleted), hookPush) | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Empty(t, pc) | |
| assert.Empty(t, cc) | |
| assert.Nil(t, r) | |
| assert.Nil(t, b) | |
| assert.NoError(t, err) | |
| assert.Nil(t, p) | |
| }) | |
| t.Run("push hook", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookPush), hookPush) | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Equal(t, "2f780193b136b72bfea4eeb640786a8c4450c7a2", pc) | |
| assert.Equal(t, "366701fde727cb7a9e7f21eb88264f59f6f9b89c", cc) | |
| assert.NoError(t, err) | |
| assert.Nil(t, p) | |
| assert.NotNil(t, r) | |
| assert.NotNil(t, b) | |
| assert.Equal(t, model.EventPush, b.Event) | |
| sort.Strings(b.ChangedFiles) | |
| }) | |
| t.Run("PR hook", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookPullRequest), hookPull) | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Empty(t, pc) | |
| assert.Empty(t, cc) | |
| assert.NoError(t, err) | |
| assert.NotNil(t, r) | |
| assert.NotNil(t, b) | |
| assert.NotNil(t, p) | |
| assert.Equal(t, model.EventPull, b.Event) | |
| }) | |
| t.Run("PR closed hook", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookPullRequestClosed), hookPull) | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Empty(t, pc) | |
| assert.Empty(t, cc) | |
| assert.NoError(t, err) | |
| assert.NotNil(t, r) | |
| assert.NotNil(t, b) | |
| assert.NotNil(t, p) | |
| assert.Equal(t, model.EventPullClosed, b.Event) | |
| }) | |
| t.Run("reopen a pull", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookPullRequestReopened), hookPull) | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Empty(t, pc) | |
| assert.Empty(t, cc) | |
| assert.NoError(t, err) | |
| assert.NotNil(t, r) | |
| assert.NotNil(t, b) | |
| assert.NotNil(t, p) | |
| assert.Equal(t, model.EventPull, b.Event) | |
| }) | |
| t.Run("PR merged hook", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookPullRequestMerged), hookPull) | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Empty(t, pc) | |
| assert.Empty(t, cc) | |
| assert.NoError(t, err) | |
| assert.NotNil(t, r) | |
| assert.NotNil(t, b) | |
| assert.NotNil(t, p) | |
| assert.Equal(t, model.EventPullClosed, b.Event) | |
| }) | |
| t.Run("PR edited hook", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookPullRequestEdited), hookPull) | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Empty(t, pc) | |
| assert.Empty(t, cc) | |
| assert.NoError(t, err) | |
| assert.NotNil(t, r) | |
| assert.NotNil(t, b) | |
| assert.NotNil(t, p) | |
| assert.Equal(t, model.EventPullMetadata, b.Event) | |
| assert.Equal(t, []string{"edited"}, b.EventReason) | |
| }) | |
| t.Run("deploy hook", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookDeploy), hookDeploy) | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Empty(t, pc) | |
| assert.Empty(t, cc) | |
| assert.NoError(t, err) | |
| assert.NotNil(t, r) | |
| assert.NotNil(t, b) | |
| assert.Nil(t, p) | |
| assert.Equal(t, model.EventDeploy, b.Event) | |
| assert.Equal(t, "production", b.DeployTo) | |
| assert.Equal(t, "deploy", b.DeployTask) | |
| }) | |
| t.Run("release hook", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookRelease), hookRelease) | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Empty(t, pc) | |
| assert.Empty(t, cc) | |
| assert.NoError(t, err) | |
| assert.NotNil(t, r) | |
| assert.NotNil(t, b) | |
| assert.Nil(t, p) | |
| assert.Equal(t, model.EventRelease, b.Event) | |
| assert.Len(t, strings.Split(b.Ref, "/"), 3) | |
| assert.True(t, strings.HasPrefix(b.Ref, "refs/tags/")) | |
| }) | |
| t.Run("pull review requested", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookPullRequestReviewRequested), hookPull) | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Empty(t, pc) | |
| assert.Empty(t, cc) | |
| assert.ErrorIs(t, err, &types.ErrIgnoreEvent{}) | |
| assert.Nil(t, r) | |
| assert.Nil(t, b) | |
| assert.Nil(t, p) | |
| }) | |
| t.Run("pull milestoned", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookPullRequestMilestoneAdded), hookPull) | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Empty(t, pc) | |
| assert.Empty(t, cc) | |
| assert.NoError(t, err) | |
| assert.NotNil(t, r) | |
| assert.NotNil(t, b) | |
| assert.Equal(t, model.EventPullMetadata, b.Event) | |
| assert.Equal(t, []string{"milestoned"}, b.EventReason) | |
| if assert.NotNil(t, p) { | |
| assert.Equal(t, int64(2705176047), *p.ID) | |
| assert.Equal(t, 1, *p.Number) | |
| assert.Equal(t, "open", *p.State) | |
| assert.Equal(t, "Some ned more AAAA", *p.Title) | |
| assert.Equal(t, "yeaaa", *p.Body) | |
| assert.Equal(t, false, *p.Draft) | |
| assert.Equal(t, false, *p.Merged) | |
| assert.Equal(t, true, *p.Mergeable) | |
| assert.Equal(t, "unstable", *p.MergeableState) | |
| if assert.NotNil(t, p.User) { | |
| assert.Equal(t, "6543", *p.User.Login) | |
| assert.Equal(t, int64(24977596), *p.User.ID) | |
| } | |
| if assert.NotNil(t, p.Milestone) { | |
| assert.Equal(t, int64(13392101), *p.Milestone.ID) | |
| assert.Equal(t, 2, *p.Milestone.Number) | |
| assert.Equal(t, "open mile", *p.Milestone.Title) | |
| assert.Equal(t, "ongoing", *p.Milestone.Description) | |
| assert.Equal(t, "open", *p.Milestone.State) | |
| if assert.NotNil(t, p.Milestone.Creator) { | |
| assert.Equal(t, "demoaccount2-commits", *p.Milestone.Creator.Login) | |
| assert.Equal(t, int64(223550959), *p.Milestone.Creator.ID) | |
| } | |
| } | |
| assert.Empty(t, p.RequestedReviewers) | |
| if assert.NotNil(t, p.Head) { | |
| assert.Equal(t, "6543-patch-1", *p.Head.Ref) | |
| assert.Equal(t, "36b5813240a9d2daa29b05046d56a53e18f39a3e", *p.Head.SHA) | |
| } | |
| if assert.NotNil(t, p.Base) { | |
| assert.Equal(t, "main", *p.Base.Ref) | |
| assert.Equal(t, "67012991d6c69b1c58378346fca366b864d8d1a1", *p.Base.SHA) | |
| } | |
| } | |
| }) | |
| // milestone change will result two webhooks an demilestoned and milestoned | |
| t.Run("pull request demilestoned", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookPullRequestMilestoneRemoved), hookPull) | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Empty(t, pc) | |
| assert.Empty(t, cc) | |
| assert.NoError(t, err) | |
| assert.NotNil(t, r) | |
| assert.NotNil(t, b) | |
| assert.Equal(t, model.EventPullMetadata, b.Event) | |
| assert.Equal(t, []string{"demilestoned"}, b.EventReason) | |
| if assert.NotNil(t, p) { | |
| assert.Equal(t, int64(2705176047), *p.ID) | |
| assert.Equal(t, 1, *p.Number) | |
| assert.Equal(t, "open", *p.State) | |
| assert.Equal(t, "Some ned more AAAA", *p.Title) | |
| if assert.NotNil(t, p.User) { | |
| assert.Equal(t, "6543", *p.User.Login) | |
| assert.Equal(t, int64(24977596), *p.User.ID) | |
| } | |
| if assert.Len(t, p.Labels, 1) { | |
| assert.Equal(t, int64(9024465370), *p.Labels[0].ID) | |
| assert.Equal(t, "bug", *p.Labels[0].Name) | |
| assert.Equal(t, "d73a4a", *p.Labels[0].Color) | |
| assert.Equal(t, "Something isn't working", *p.Labels[0].Description) | |
| } | |
| assert.Nil(t, p.Milestone) | |
| if assert.NotNil(t, p.Head) { | |
| assert.Equal(t, "6543-patch-1", *p.Head.Ref) | |
| assert.Equal(t, "36b5813240a9d2daa29b05046d56a53e18f39a3e", *p.Head.SHA) | |
| } | |
| if assert.NotNil(t, p.Base) { | |
| assert.Equal(t, "main", *p.Base.Ref) | |
| assert.Equal(t, "67012991d6c69b1c58378346fca366b864d8d1a1", *p.Base.SHA) | |
| } | |
| } | |
| }) | |
| t.Run("pull request labele added", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookPullRequestLabelAdded), hookPull) | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Empty(t, pc) | |
| assert.Empty(t, cc) | |
| assert.NoError(t, err) | |
| assert.NotNil(t, r) | |
| assert.NotNil(t, b) | |
| assert.Equal(t, model.EventPullMetadata, b.Event) | |
| assert.Equal(t, []string{"label_updated"}, b.EventReason) | |
| if assert.NotNil(t, p) { | |
| assert.Equal(t, int64(2705176047), *p.ID) | |
| assert.Equal(t, 1, *p.Number) | |
| assert.Equal(t, "open", *p.State) | |
| assert.Equal(t, "Some ned more AAAA", *p.Title) | |
| assert.Equal(t, "yeaaa", *p.Body) | |
| assert.Equal(t, false, *p.Draft) | |
| assert.Equal(t, false, *p.Merged) | |
| assert.Equal(t, true, *p.Mergeable) | |
| assert.Equal(t, "unstable", *p.MergeableState) | |
| if assert.NotNil(t, p.User) { | |
| assert.Equal(t, "6543", *p.User.Login) | |
| assert.Equal(t, int64(24977596), *p.User.ID) | |
| } | |
| if assert.Len(t, p.Labels, 2) { | |
| assert.Equal(t, int64(9024465376), *p.Labels[0].ID) | |
| assert.Equal(t, "documentation", *p.Labels[0].Name) | |
| assert.Equal(t, "0075ca", *p.Labels[0].Color) | |
| assert.Equal(t, "Improvements or additions to documentation", *p.Labels[0].Description) | |
| assert.Equal(t, int64(9024465382), *p.Labels[1].ID) | |
| assert.Equal(t, "enhancement", *p.Labels[1].Name) | |
| assert.Equal(t, "a2eeef", *p.Labels[1].Color) | |
| assert.Equal(t, "New feature or request", *p.Labels[1].Description) | |
| } | |
| if assert.NotNil(t, p.Milestone) { | |
| assert.Equal(t, int64(13392101), *p.Milestone.ID) | |
| assert.Equal(t, "open mile", *p.Milestone.Title) | |
| } | |
| assert.Empty(t, p.RequestedReviewers) | |
| if assert.NotNil(t, p.Head) { | |
| assert.Equal(t, "6543-patch-1", *p.Head.Ref) | |
| assert.Equal(t, "36b5813240a9d2daa29b05046d56a53e18f39a3e", *p.Head.SHA) | |
| } | |
| if assert.NotNil(t, p.Base) { | |
| assert.Equal(t, "main", *p.Base.Ref) | |
| assert.Equal(t, "67012991d6c69b1c58378346fca366b864d8d1a1", *p.Base.SHA) | |
| } | |
| } | |
| }) | |
| // lable change will result two webhooks an unlable and labeled | |
| t.Run("pull request got label removed", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookPullRequestLabelRemoved), hookPull) | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Empty(t, pc) | |
| assert.Empty(t, cc) | |
| assert.NoError(t, err) | |
| assert.NotNil(t, r) | |
| assert.NotNil(t, b) | |
| assert.Equal(t, model.EventPullMetadata, b.Event) | |
| assert.Equal(t, []string{"label_updated"}, b.EventReason) | |
| if assert.NotNil(t, p) { | |
| assert.Equal(t, int64(2705176047), *p.ID) | |
| assert.Equal(t, 1, *p.Number) | |
| assert.Equal(t, "open", *p.State) | |
| assert.Equal(t, "Some ned more AAAA", *p.Title) | |
| if assert.NotNil(t, p.User) { | |
| assert.Equal(t, "6543", *p.User.Login) | |
| assert.Equal(t, int64(24977596), *p.User.ID) | |
| } | |
| if assert.Len(t, p.Labels, 1) { | |
| assert.Equal(t, int64(9024465370), *p.Labels[0].ID) | |
| assert.Equal(t, "bug", *p.Labels[0].Name) | |
| assert.Equal(t, "d73a4a", *p.Labels[0].Color) | |
| assert.Equal(t, "Something isn't working", *p.Labels[0].Description) | |
| } | |
| if assert.NotNil(t, p.Head) { | |
| assert.Equal(t, "6543-patch-1", *p.Head.Ref) | |
| assert.Equal(t, "36b5813240a9d2daa29b05046d56a53e18f39a3e", *p.Head.SHA) | |
| } | |
| if assert.NotNil(t, p.Base) { | |
| assert.Equal(t, "main", *p.Base.Ref) | |
| assert.Equal(t, "67012991d6c69b1c58378346fca366b864d8d1a1", *p.Base.SHA) | |
| } | |
| } | |
| }) | |
| t.Run("pull request got all label removed", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookPullRequestLabelsCleared), hookPull) | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Empty(t, pc) | |
| assert.Empty(t, cc) | |
| assert.NoError(t, err) | |
| assert.NotNil(t, r) | |
| assert.NotNil(t, b) | |
| assert.Equal(t, model.EventPullMetadata, b.Event) | |
| assert.Equal(t, []string{"label_cleared"}, b.EventReason) | |
| if assert.NotNil(t, p) { | |
| assert.Equal(t, int64(2705176047), *p.ID) | |
| assert.Equal(t, 1, *p.Number) | |
| assert.Equal(t, "open", *p.State) | |
| assert.Equal(t, "Some ned more AAAA", *p.Title) | |
| assert.Empty(t, p.Labels) | |
| if assert.NotNil(t, p.User) { | |
| assert.Equal(t, "6543", *p.User.Login) | |
| assert.Equal(t, int64(24977596), *p.User.ID) | |
| } | |
| if assert.NotNil(t, p.Head) { | |
| assert.Equal(t, "6543-patch-1", *p.Head.Ref) | |
| assert.Equal(t, "36b5813240a9d2daa29b05046d56a53e18f39a3e", *p.Head.SHA) | |
| } | |
| if assert.NotNil(t, p.Base) { | |
| assert.Equal(t, "main", *p.Base.Ref) | |
| assert.Equal(t, "67012991d6c69b1c58378346fca366b864d8d1a1", *p.Base.SHA) | |
| } | |
| } | |
| }) | |
| t.Run("pull request assigned", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookPullRequestAssigneeAdded), hookPull) | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Empty(t, pc) | |
| assert.Empty(t, cc) | |
| assert.NoError(t, err) | |
| assert.NotNil(t, r) | |
| assert.NotNil(t, b) | |
| assert.Equal(t, model.EventPullMetadata, b.Event) | |
| assert.Equal(t, []string{"assigned"}, b.EventReason) | |
| if assert.NotNil(t, p) { | |
| assert.Equal(t, int64(2705176047), *p.ID) | |
| assert.Equal(t, 1, *p.Number) | |
| assert.Equal(t, "open", *p.State) | |
| assert.Equal(t, "Some ned more AAAA", *p.Title) | |
| if assert.NotNil(t, p.User) { | |
| assert.Equal(t, "6543", *p.User.Login) | |
| assert.Equal(t, int64(24977596), *p.User.ID) | |
| } | |
| if assert.NotNil(t, p.Assignee) { | |
| assert.Equal(t, "demoaccount2-commits", *p.Assignee.Login) | |
| assert.Equal(t, int64(223550959), *p.Assignee.ID) | |
| } | |
| if assert.Len(t, p.Assignees, 1) { | |
| assert.Equal(t, "demoaccount2-commits", *p.Assignees[0].Login) | |
| assert.Equal(t, int64(223550959), *p.Assignees[0].ID) | |
| } | |
| if assert.Len(t, p.Labels, 1) { | |
| assert.Equal(t, int64(9024465370), *p.Labels[0].ID) | |
| assert.Equal(t, "bug", *p.Labels[0].Name) | |
| } | |
| assert.Nil(t, p.Milestone) | |
| if assert.NotNil(t, p.Head) { | |
| assert.Equal(t, "6543-patch-1", *p.Head.Ref) | |
| assert.Equal(t, "36b5813240a9d2daa29b05046d56a53e18f39a3e", *p.Head.SHA) | |
| } | |
| if assert.NotNil(t, p.Base) { | |
| assert.Equal(t, "main", *p.Base.Ref) | |
| assert.Equal(t, "67012991d6c69b1c58378346fca366b864d8d1a1", *p.Base.SHA) | |
| } | |
| } | |
| }) | |
| // assigne change will result two webhooks an assigned and unassigned | |
| t.Run("pull request unassigned", func(t *testing.T) { | |
| req := testHookRequest([]byte(fixtures.HookPullRequestAssigneeRemoved), hookPull) | |
| p, r, b, cc, pc, err := parseHook(req, false) | |
| assert.Empty(t, pc) | |
| assert.Empty(t, cc) | |
| assert.NoError(t, err) | |
| assert.NotNil(t, r) | |
| assert.NotNil(t, b) | |
| assert.Equal(t, model.EventPullMetadata, b.Event) | |
| assert.Equal(t, []string{"unassigned"}, b.EventReason) | |
| if assert.NotNil(t, p) { | |
| assert.Equal(t, int64(2705176047), *p.ID) | |
| assert.Equal(t, 1, *p.Number) | |
| assert.Equal(t, "open", *p.State) | |
| assert.Equal(t, "Some ned more AAAA", *p.Title) | |
| if assert.NotNil(t, p.User) { | |
| assert.Equal(t, "6543", *p.User.Login) | |
| assert.Equal(t, int64(24977596), *p.User.ID) | |
| } | |
| assert.Nil(t, p.Assignee) | |
| assert.Empty(t, p.Assignees) | |
| if assert.Len(t, p.Labels, 1) { | |
| assert.Equal(t, int64(9024465370), *p.Labels[0].ID) | |
| assert.Equal(t, "bug", *p.Labels[0].Name) | |
| } | |
| assert.Nil(t, p.Milestone) | |
| if assert.NotNil(t, p.Head) { | |
| assert.Equal(t, "6543-patch-1", *p.Head.Ref) | |
| assert.Equal(t, "36b5813240a9d2daa29b05046d56a53e18f39a3e", *p.Head.SHA) | |
| } | |
| if assert.NotNil(t, p.Base) { | |
| assert.Equal(t, "main", *p.Base.Ref) | |
| assert.Equal(t, "67012991d6c69b1c58378346fca366b864d8d1a1", *p.Base.SHA) | |
| } | |
| } | |
| }) | |
| } | |