Skip to content

Commit 78eed25

Browse files
PuneetPunamiyazakisk
authored andcommitted
fix(gitlab): trigger PipelineRun only on label change
Before this patch pipeline was triggered on any merge request update, regardless of what changed such as title, description or assigne changes With the current change, pipeline will be triggered only when labels are added or removed Signed-off-by: PuneetPunamiya <[email protected]>
1 parent f9fd3f3 commit 78eed25

File tree

3 files changed

+120
-0
lines changed

3 files changed

+120
-0
lines changed

pkg/provider/gitlab/detect.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ func (v *Provider) Detect(req *http.Request, payload string, logger *zap.Sugared
3838

3939
switch gitEvent := eventInt.(type) {
4040
case *gitlab.MergeEvent:
41+
// on a MR update, react only if OldRev is empty (no new commits pushed).
42+
// If OldRev is empty, it's a metadata-only update (e.g., label changes).
43+
if gitEvent.ObjectAttributes.Action == "update" && gitEvent.ObjectAttributes.OldRev == "" {
44+
if !hasOnlyLabelsChanged(gitEvent) {
45+
return setLoggerAndProceed(false, "this 'Merge Request' update event changes are not supported; cannot proceed", nil)
46+
}
47+
}
48+
4149
if provider.Valid(gitEvent.ObjectAttributes.Action, []string{"open", "reopen", "update"}) {
4250
return setLoggerAndProceed(true, "", nil)
4351
}
@@ -76,3 +84,27 @@ func (v *Provider) Detect(req *http.Request, payload string, logger *zap.Sugared
7684
return setLoggerAndProceed(false, "", fmt.Errorf("gitlab: event \"%s\" is not supported", event))
7785
}
7886
}
87+
88+
// hasOnlyLabelsChanged checks if the only change in the merge request is to its labels.
89+
// This function ensures that other fields remain unchanged.
90+
func hasOnlyLabelsChanged(gitEvent *gitlab.MergeEvent) bool {
91+
changes := gitEvent.Changes
92+
93+
labelsChanged := len(changes.Labels.Previous) > 0 || len(changes.Labels.Current) > 0
94+
95+
// Only Labels can change — everything else must be zero or nil
96+
onlyUpdatedAtOrLabels := labelsChanged &&
97+
changes.Assignees.Previous == nil && changes.Assignees.Current == nil &&
98+
changes.Reviewers.Previous == nil && changes.Reviewers.Current == nil &&
99+
changes.Description.Previous == "" && changes.Description.Current == "" &&
100+
changes.MergeStatus.Previous == "" && changes.MergeStatus.Current == "" &&
101+
changes.MilestoneID.Previous == 0 && changes.MilestoneID.Current == 0 &&
102+
changes.SourceBranch.Previous == "" && changes.SourceBranch.Current == "" &&
103+
changes.SourceProjectID.Previous == 0 && changes.SourceProjectID.Current == 0 &&
104+
changes.StateID.Previous == 0 && changes.StateID.Current == 0 &&
105+
changes.TargetBranch.Previous == "" && changes.TargetBranch.Current == "" &&
106+
changes.TargetProjectID.Previous == 0 && changes.TargetProjectID.Current == 0 &&
107+
changes.Title.Previous == "" && changes.Title.Current == ""
108+
109+
return onlyUpdatedAtOrLabels
110+
}

pkg/provider/gitlab/detect_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,20 @@ func TestProvider_Detect(t *testing.T) {
7272
isGL: true,
7373
processReq: true,
7474
},
75+
{
76+
name: "good/mergeRequest update Event with title",
77+
event: sample.MREventAsJSON("update", `"title": "test"`),
78+
eventType: gitlab.EventTypeMergeRequest,
79+
isGL: true,
80+
processReq: false,
81+
},
82+
{
83+
name: "good/mergeRequest update Event with description",
84+
event: sample.MREventAsJSON("update", `"description": "test pac"`),
85+
eventType: gitlab.EventTypeMergeRequest,
86+
isGL: true,
87+
processReq: false,
88+
},
7589
{
7690
name: "good/note event",
7791
event: sample.NoteEventAsJSON("abc"),

test/gitlab_merge_request_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,80 @@ func TestGitlabDisableCommentsOnMR(t *testing.T) {
616616
assert.Equal(t, 2, successCommentsPost)
617617
}
618618

619+
func TestGitlabMergeRequestOnUpdateAtAndLabelChange(t *testing.T) {
620+
targetNS := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-ns")
621+
ctx := context.Background()
622+
runcnx, opts, glprovider, err := tgitlab.Setup(ctx)
623+
assert.NilError(t, err)
624+
ctx, err = cctx.GetControllerCtxInfo(ctx, runcnx)
625+
assert.NilError(t, err)
626+
runcnx.Clients.Log.Info("Testing with Gitlab")
627+
628+
projectinfo, resp, err := glprovider.Client().Projects.GetProject(opts.ProjectID, nil)
629+
assert.NilError(t, err)
630+
if resp != nil && resp.StatusCode == http.StatusNotFound {
631+
t.Errorf("Repository %s not found in %s", opts.Organization, opts.Repo)
632+
}
633+
634+
err = tgitlab.CreateCRD(ctx, projectinfo, runcnx, opts, targetNS, nil)
635+
assert.NilError(t, err)
636+
637+
entries, err := payload.GetEntries(map[string]string{
638+
".tekton/pipelinerun.yaml": "testdata/pipelinerun.yaml",
639+
".tekton/pipelinerun-clone.yaml": "testdata/pipelinerun-clone.yaml",
640+
}, targetNS, projectinfo.DefaultBranch,
641+
triggertype.PullRequest.String(), map[string]string{})
642+
assert.NilError(t, err)
643+
644+
targetRefName := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-test")
645+
646+
gitCloneURL, err := scm.MakeGitCloneURL(projectinfo.WebURL, opts.UserName, opts.Password)
647+
assert.NilError(t, err)
648+
commitTitle := "Committing files from test on " + targetRefName
649+
scmOpts := &scm.Opts{
650+
GitURL: gitCloneURL,
651+
CommitTitle: commitTitle,
652+
Log: runcnx.Clients.Log,
653+
WebURL: projectinfo.WebURL,
654+
TargetRefName: targetRefName,
655+
BaseRefName: projectinfo.DefaultBranch,
656+
}
657+
_ = scm.PushFilesToRefGit(t, scmOpts, entries)
658+
659+
runcnx.Clients.Log.Infof("Branch %s has been created and pushed with files", targetRefName)
660+
mrTitle := "TestMergeRequest - " + targetRefName
661+
mrID, err := tgitlab.CreateMR(glprovider.Client(), opts.ProjectID, targetRefName, projectinfo.DefaultBranch, mrTitle)
662+
assert.NilError(t, err)
663+
runcnx.Clients.Log.Infof("MergeRequest %s/-/merge_requests/%d has been created", projectinfo.WebURL, mrID)
664+
defer tgitlab.TearDown(ctx, t, runcnx, glprovider, mrID, targetRefName, targetNS, opts.ProjectID)
665+
666+
sopt := twait.SuccessOpt{
667+
Title: commitTitle,
668+
OnEvent: "Merge Request",
669+
TargetNS: targetNS,
670+
NumberofPRMatch: 2,
671+
SHA: "",
672+
}
673+
twait.Succeeded(ctx, t, runcnx, opts, sopt)
674+
prsNew, err := runcnx.Clients.Tekton.TektonV1().PipelineRuns(targetNS).List(ctx, metav1.ListOptions{})
675+
assert.NilError(t, err)
676+
assert.Assert(t, len(prsNew.Items) == 2)
677+
678+
runcnx.Clients.Log.Infof("Changing Title on MergeRequest %s/-/merge_requests/%d", projectinfo.WebURL, mrID)
679+
_, _, err = glprovider.Client().MergeRequests.UpdateMergeRequest(opts.ProjectID, mrID, &clientGitlab.UpdateMergeRequestOptions{
680+
Title: clientGitlab.Ptr("test"),
681+
})
682+
assert.NilError(t, err)
683+
684+
// let's wait 10 secs and check every second that a PipelineRun is created or not.
685+
for i := 0; i < 10; i++ {
686+
prs, err := runcnx.Clients.Tekton.TektonV1().PipelineRuns(targetNS).List(ctx, metav1.ListOptions{})
687+
assert.NilError(t, err)
688+
assert.Assert(t, len(prs.Items) == 2)
689+
time.Sleep(1 * time.Second)
690+
}
691+
}
692+
619693
// Local Variables:
620694
// compile-command: "go test -tags=e2e -v -run ^TestGitlabMergeRequest$"
621695
// End:

0 commit comments

Comments
 (0)