Skip to content

Commit fe2b8bd

Browse files
aThorp96chmouel
authored andcommitted
fix: Cancel PipelineRuns on MR change in Gitlab
Signed-off-by: Andrew Thorp <athorp@redhat.com>
1 parent 0e10ba9 commit fe2b8bd

File tree

5 files changed

+178
-77
lines changed

5 files changed

+178
-77
lines changed

pkg/pipelineascode/cancel_pipelineruns.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/keys"
1717
"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
1818
"github.com/openshift-pipelines/pipelines-as-code/pkg/formatting"
19-
"github.com/openshift-pipelines/pipelines-as-code/pkg/opscomments"
2019
"github.com/openshift-pipelines/pipelines-as-code/pkg/params/triggertype"
2120
)
2221

@@ -87,9 +86,6 @@ func (p *PacRun) cancelInProgressMatchingPR(ctx context.Context, matchPR *tekton
8786
labelMap[keys.PullRequest] = strconv.Itoa(p.event.PullRequestNumber)
8887
}
8988
labelSelector := getLabelSelector(labelMap)
90-
if p.event.TriggerTarget == triggertype.PullRequest {
91-
labelSelector += fmt.Sprintf(",%s in (pull_request, %s)", keys.EventType, opscomments.AnyOpsKubeLabelInSelector())
92-
}
9389
p.run.Clients.Log.Infof("cancel-in-progress: selecting pipelineRuns to cancel with labels: %v", labelSelector)
9490
prs, err := p.run.Clients.Tekton.TektonV1().PipelineRuns(matchPR.GetNamespace()).List(ctx, metav1.ListOptions{
9591
LabelSelector: labelSelector,

pkg/provider/gitlab/parse_payload.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func (v *Provider) ParsePayload(_ context.Context, _ *params.Run, request *http.
9797
processedEvent.BaseBranch = gitEvent.Ref
9898
processedEvent.HeadURL = gitEvent.Project.WebURL
9999
processedEvent.BaseURL = processedEvent.HeadURL
100-
processedEvent.TriggerTarget = "push"
100+
processedEvent.TriggerTarget = triggertype.Push
101101
v.pathWithNamespace = gitEvent.Project.PathWithNamespace
102102
processedEvent.Organization, processedEvent.Repository = getOrgRepo(v.pathWithNamespace)
103103
v.targetProjectID = gitEvent.ProjectID
@@ -121,7 +121,7 @@ func (v *Provider) ParsePayload(_ context.Context, _ *params.Run, request *http.
121121
processedEvent.BaseBranch = gitEvent.Ref
122122
processedEvent.HeadURL = gitEvent.Project.WebURL
123123
processedEvent.BaseURL = processedEvent.HeadURL
124-
processedEvent.TriggerTarget = "push"
124+
processedEvent.TriggerTarget = triggertype.Push
125125
v.pathWithNamespace = gitEvent.Project.PathWithNamespace
126126
processedEvent.Organization, processedEvent.Repository = getOrgRepo(v.pathWithNamespace)
127127
v.targetProjectID = gitEvent.ProjectID

test/gitlab_merge_request_test.go

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,119 @@ func TestGitlabOnComment(t *testing.T) {
277277
assert.NilError(t, err)
278278
}
279279

280+
func TestGitlabCancelInProgressOnChange(t *testing.T) {
281+
targetNS := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-ns")
282+
ctx := context.Background()
283+
runcnx, opts, glprovider, err := tgitlab.Setup(ctx)
284+
assert.NilError(t, err)
285+
ctx, err = cctx.GetControllerCtxInfo(ctx, runcnx)
286+
assert.NilError(t, err)
287+
runcnx.Clients.Log.Info("Testing Gitlab cancel in progress on pr close")
288+
projectinfo, resp, err := glprovider.Client.Projects.GetProject(opts.ProjectID, nil)
289+
assert.NilError(t, err)
290+
if resp != nil && resp.StatusCode == http.StatusNotFound {
291+
t.Errorf("Repository %s not found in %s", opts.Organization, opts.Repo)
292+
}
293+
294+
err = tgitlab.CreateCRD(ctx, projectinfo, runcnx, targetNS, nil)
295+
assert.NilError(t, err)
296+
297+
entries, err := payload.GetEntries(map[string]string{
298+
".tekton/in-progress.yaml": "testdata/pipelinerun-cancel-in-progress.yaml",
299+
}, targetNS, projectinfo.DefaultBranch,
300+
triggertype.PullRequest.String(), map[string]string{})
301+
assert.NilError(t, err)
302+
targetRefName := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-test")
303+
304+
gitCloneURL, err := scm.MakeGitCloneURL(projectinfo.WebURL, opts.UserName, opts.Password)
305+
assert.NilError(t, err)
306+
mrTitle := "TestCancelInProgress initial commit - " + targetRefName
307+
scmOpts := &scm.Opts{
308+
GitURL: gitCloneURL,
309+
Log: runcnx.Clients.Log,
310+
WebURL: projectinfo.WebURL,
311+
TargetRefName: targetRefName,
312+
BaseRefName: projectinfo.DefaultBranch,
313+
CommitTitle: mrTitle,
314+
}
315+
316+
oldSha := scm.PushFilesToRefGit(t, scmOpts, entries)
317+
runcnx.Clients.Log.Infof("Branch %s has been created and pushed with files", targetRefName)
318+
mrID, err := tgitlab.CreateMR(glprovider.Client, opts.ProjectID, targetRefName, projectinfo.DefaultBranch, mrTitle)
319+
assert.NilError(t, err)
320+
runcnx.Clients.Log.Infof("MergeRequest %s/-/merge_requests/%d has been created", projectinfo.WebURL, mrID)
321+
defer tgitlab.TearDown(ctx, t, runcnx, glprovider, mrID, targetRefName, targetNS, opts.ProjectID)
322+
323+
runcnx.Clients.Log.Infof("Waiting for the pipelinerun to be created")
324+
waitOpts := twait.Opts{
325+
RepoName: targetNS,
326+
Namespace: targetNS,
327+
MinNumberStatus: 1,
328+
PollTimeout: twait.DefaultTimeout,
329+
TargetSHA: oldSha,
330+
}
331+
err = twait.UntilPipelineRunCreated(ctx, runcnx.Clients, waitOpts)
332+
assert.NilError(t, err)
333+
334+
newEntries := map[string]string{
335+
"new-file.txt": "plz work",
336+
}
337+
338+
changeTitle := "TestCancelInProgress second commit - " + targetRefName
339+
scmOpts = &scm.Opts{
340+
GitURL: gitCloneURL,
341+
Log: runcnx.Clients.Log,
342+
WebURL: projectinfo.WebURL,
343+
TargetRefName: targetRefName,
344+
BaseRefName: targetRefName,
345+
CommitTitle: changeTitle,
346+
}
347+
newSha := scm.PushFilesToRefGit(t, scmOpts, newEntries)
348+
349+
runcnx.Clients.Log.Infof("Waiting for new pipeline to be created")
350+
changeWaitOpts := twait.Opts{
351+
RepoName: targetNS,
352+
Namespace: targetNS,
353+
MinNumberStatus: 1,
354+
PollTimeout: twait.DefaultTimeout,
355+
TargetSHA: newSha,
356+
}
357+
err = twait.UntilPipelineRunCreated(ctx, runcnx.Clients, changeWaitOpts)
358+
assert.NilError(t, err)
359+
360+
runcnx.Clients.Log.Infof("Sleeping for 10 seconds to let the pipelinerun to be canceled")
361+
362+
i := 0
363+
foundCancelled := false
364+
for i < 10 {
365+
prs, err := runcnx.Clients.Tekton.TektonV1().PipelineRuns(targetNS).List(ctx, metav1.ListOptions{
366+
LabelSelector: fmt.Sprintf("%s=%s", keys.SHA, oldSha),
367+
})
368+
assert.NilError(t, err)
369+
370+
for _, pr := range prs.Items {
371+
if pr.GetStatusCondition() == nil {
372+
continue
373+
}
374+
if len(pr.Status.Conditions) == 0 {
375+
continue
376+
}
377+
if pr.Status.Conditions[0].Reason == "Cancelled" {
378+
runcnx.Clients.Log.Infof("PipelineRun %s has been canceled", pr.Name)
379+
foundCancelled = true
380+
break
381+
}
382+
}
383+
if foundCancelled {
384+
break
385+
}
386+
387+
time.Sleep(5 * time.Second)
388+
i++
389+
}
390+
assert.Assert(t, foundCancelled, "No Pipelines has been found cancedl in NS %s", targetNS)
391+
}
392+
280393
func TestGitlabCancelInProgressOnPRClose(t *testing.T) {
281394
targetNS := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-ns")
282395
ctx := context.Background()
@@ -303,7 +416,7 @@ func TestGitlabCancelInProgressOnPRClose(t *testing.T) {
303416

304417
gitCloneURL, err := scm.MakeGitCloneURL(projectinfo.WebURL, opts.UserName, opts.Password)
305418
assert.NilError(t, err)
306-
mrTitle := "TestCancelInProgress - " + targetRefName
419+
mrTitle := "TestCancelInProgressOnClose - " + targetRefName
307420
scmOpts := &scm.Opts{
308421
GitURL: gitCloneURL,
309422
Log: runcnx.Clients.Log,

test/pkg/scm/scm.go

Lines changed: 61 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,57 @@ type FileChange struct {
3434
NewContent string
3535
}
3636

37+
// initializeGitClone initializes git's configuration, clones a given repository, and sets up the given branch.
38+
// Returns the repository path, a cleanup function which should be deferred, and an error, if any occurred.
39+
func initializeGit(t *testing.T, opts *Opts) (string, func(), error) {
40+
tmpdir := fs.NewDir(t, t.Name())
41+
fixPwd := env.ChangeWorkingDir(t, tmpdir.Path())
42+
cleanupFunc := func() {
43+
fixPwd()
44+
if os.Getenv("TEST_NOCLEANUP") == "" {
45+
tmpdir.Remove()
46+
}
47+
}
48+
path := tmpdir.Path()
49+
50+
var err error
51+
52+
if _, err = git.RunGit(path, "init"); err != nil {
53+
return "", func() {}, err
54+
}
55+
if _, err = git.RunGit(path, "config", "user.name", "OpenShift Pipelines E2E test"); err != nil {
56+
return "", func() {}, err
57+
}
58+
if _, err = git.RunGit(path, "config", "user.email", "e2e-pipeline@redhat.com"); err != nil {
59+
return "", func() {}, err
60+
}
61+
62+
if _, err = git.RunGit(path, "remote", "add", "-f", "origin", opts.GitURL); err != nil {
63+
return "", func() {}, err
64+
}
65+
66+
if _, err = git.RunGit(path, "fetch", "-a", "origin"); err != nil {
67+
return "", func() {}, err
68+
}
69+
70+
if strings.HasPrefix(opts.TargetRefName, "refs/tags") {
71+
_, err = git.RunGit(path, "reset", "--hard", "origin/"+opts.BaseRefName)
72+
} else {
73+
if opts.NoCheckOutFromBase {
74+
// Create a new branch without the base reference,
75+
// which can be helpful for testing when you only want to add specific requested files
76+
_, err = git.RunGit(path, "checkout", "-B", opts.TargetRefName)
77+
} else {
78+
// checkout new branch from base branch
79+
_, err = git.RunGit(path, "checkout", "-B", opts.TargetRefName, "origin/"+opts.BaseRefName)
80+
}
81+
}
82+
return path, cleanupFunc, err
83+
}
84+
3785
// gitPushPullRetry tries to push the files to the repo, if it fails it will try to rebase and push again.
38-
func gitPushPullRetry(t *testing.T, opts *Opts, path string) {
86+
// Returns the sha of the commit pushed.
87+
func gitPushPullRetry(t *testing.T, opts *Opts, path string) string {
3988
// use a loop to try multiple times in case of error
4089
var err error
4190
count := 0
@@ -48,7 +97,12 @@ func gitPushPullRetry(t *testing.T, opts *Opts, path string) {
4897
opts.Log.Infof("Pushed files to repo %s branch %s", opts.WebURL, opts.TargetRefName)
4998
// trying to avoid the multiple events at the time of creation we have a sync
5099
time.Sleep(5 * time.Second)
51-
return
100+
101+
// get sha
102+
sha, err := git.RunGit(path, "rev-parse", "HEAD")
103+
assert.NilError(t, err)
104+
105+
return sha
52106
}
53107
if strings.Contains(err.Error(), "non-fast-forward") {
54108
_, err = git.RunGit(path, "fetch", "-a", "origin")
@@ -69,40 +123,8 @@ func gitPushPullRetry(t *testing.T, opts *Opts, path string) {
69123
}
70124

71125
func PushFilesToRefGit(t *testing.T, opts *Opts, entries map[string]string) string {
72-
tmpdir := fs.NewDir(t, t.Name())
73-
defer (func() {
74-
if os.Getenv("TEST_NOCLEANUP") == "" {
75-
tmpdir.Remove()
76-
}
77-
})()
78-
defer env.ChangeWorkingDir(t, tmpdir.Path())()
79-
path := tmpdir.Path()
80-
_, err := git.RunGit(path, "init")
81-
assert.NilError(t, err)
82-
83-
_, err = git.RunGit(path, "config", "user.name", "OpenShift Pipelines E2E test")
84-
assert.NilError(t, err)
85-
_, err = git.RunGit(path, "config", "user.email", "e2e-pipeline@redhat.com")
86-
assert.NilError(t, err)
87-
88-
_, err = git.RunGit(path, "remote", "add", "-f", "origin", opts.GitURL)
89-
assert.NilError(t, err)
90-
91-
_, err = git.RunGit(path, "fetch", "-a", "origin")
92-
assert.NilError(t, err)
93-
94-
if strings.HasPrefix(opts.TargetRefName, "refs/tags") {
95-
_, err = git.RunGit(path, "reset", "--hard", "origin/"+opts.BaseRefName)
96-
} else {
97-
if opts.NoCheckOutFromBase {
98-
// Create a new branch without the base reference,
99-
// which can be helpful for testing when you only want to add specific requested files
100-
_, err = git.RunGit(path, "checkout", "-B", opts.TargetRefName)
101-
} else {
102-
// checkout new branch from base branch
103-
_, err = git.RunGit(path, "checkout", "-B", opts.TargetRefName, "origin/"+opts.BaseRefName)
104-
}
105-
}
126+
path, cleanupFunc, err := initializeGit(t, opts)
127+
defer cleanupFunc()
106128
assert.NilError(t, err)
107129

108130
for filename, content := range entries {
@@ -125,42 +147,12 @@ func PushFilesToRefGit(t *testing.T, opts *Opts, entries map[string]string) stri
125147
assert.NilError(t, err)
126148
}
127149

128-
// get sha
129-
sha, err := git.RunGit(path, "rev-parse", "HEAD")
130-
assert.NilError(t, err)
131-
132-
gitPushPullRetry(t, opts, path)
133-
return sha
150+
return gitPushPullRetry(t, opts, path)
134151
}
135152

136153
func ChangeFilesRefGit(t *testing.T, opts *Opts, fileChanges []FileChange) {
137-
tmpdir := fs.NewDir(t, t.Name())
138-
defer (func() {
139-
if os.Getenv("TEST_NOCLEANUP") == "" {
140-
tmpdir.Remove()
141-
}
142-
})()
143-
defer env.ChangeWorkingDir(t, tmpdir.Path())()
144-
path := tmpdir.Path()
145-
_, err := git.RunGit(path, "init")
146-
assert.NilError(t, err)
147-
148-
_, err = git.RunGit(path, "config", "user.name", "OpenShift Pipelines E2E test")
149-
assert.NilError(t, err)
150-
_, err = git.RunGit(path, "config", "user.email", "e2e-pipeline@redhat.com")
151-
assert.NilError(t, err)
152-
153-
_, err = git.RunGit(path, "remote", "add", "-f", "origin", opts.GitURL)
154-
assert.NilError(t, err)
155-
156-
_, err = git.RunGit(path, "fetch", "-a", "origin")
157-
assert.NilError(t, err)
158-
159-
if strings.HasPrefix(opts.TargetRefName, "refs/tags") {
160-
_, err = git.RunGit(path, "reset", "--hard", "origin/"+opts.BaseRefName)
161-
} else {
162-
_, err = git.RunGit(path, "checkout", "-B", opts.TargetRefName, "origin/"+opts.BaseRefName)
163-
}
154+
path, cleanupFunc, err := initializeGit(t, opts)
155+
defer cleanupFunc()
164156
assert.NilError(t, err)
165157

166158
for _, fileChange := range fileChanges {

test/pkg/wait/wait.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func UntilPipelineRunCreated(ctx context.Context, clients clients.Clients, opts
7979
return true, err
8080
}
8181

82-
clients.Log.Info("still waiting for pipelinerun to be created")
82+
clients.Log.Infof("still waiting for pipelinerun to be created with label '%s=%s' in %s namespace", keys.SHA, opts.TargetSHA, opts.Namespace)
8383
return len(prs.Items) == opts.MinNumberStatus, nil
8484
})
8585
}

0 commit comments

Comments
 (0)