diff --git a/cmd/pipelines-as-code-watcher/main.go b/cmd/pipelines-as-code-watcher/main.go index 5257bf4bb..5bf10110b 100644 --- a/cmd/pipelines-as-code-watcher/main.go +++ b/cmd/pipelines-as-code-watcher/main.go @@ -65,6 +65,7 @@ func main() { if val, ok := os.LookupEnv("PAC_DISABLE_HA"); ok { if strings.ToLower(val) == "true" { ctx = sharedmain.WithHADisabled(ctx) + ctx = sharedmain.WithHealthProbesDisabled(ctx) } } diff --git a/pkg/params/triggertype/types.go b/pkg/params/triggertype/types.go index a36e2e4eb..9a9e61994 100644 --- a/pkg/params/triggertype/types.go +++ b/pkg/params/triggertype/types.go @@ -4,6 +4,16 @@ type ( Trigger string ) +// IsPullRequestType all Triggertype that are actually a pull request. +func IsPullRequestType(s string) Trigger { + eventType := s + switch s { + case PullRequest.String(), OkToTest.String(), Retest.String(), Cancel.String(), LabelUpdate.String(): + eventType = PullRequest.String() + } + return Trigger(eventType) +} + func (t Trigger) String() string { return string(t) } diff --git a/pkg/policy/policy.go b/pkg/policy/policy.go index 9482fbb95..77f9b5cd6 100644 --- a/pkg/policy/policy.go +++ b/pkg/policy/policy.go @@ -45,9 +45,9 @@ func (p *Policy) checkAllowed(ctx context.Context, tType triggertype.Trigger) (R sType = settings.Policy.OkToTest // apply the same policy for PullRequest and comment // we don't support comments on PRs yet but if we do on the future we will need our own policy - case triggertype.PullRequest, triggertype.Comment: + case triggertype.PullRequest, triggertype.Comment, triggertype.LabelUpdate: sType = settings.Policy.PullRequest - // NOTE: not supported yet, will imp if it gets requested and reasonable to implement + // NOTE: not supported yet, will imp if it gets requested and reasonable to implement case triggertype.Push, triggertype.Cancel, triggertype.CheckSuiteRerequested, triggertype.CheckRunRerequested, triggertype.Incoming: return ResultNotSet, "" default: diff --git a/pkg/provider/bitbucketcloud/bitbucket.go b/pkg/provider/bitbucketcloud/bitbucket.go index 65a3d28bc..48bd9a67b 100644 --- a/pkg/provider/bitbucketcloud/bitbucket.go +++ b/pkg/provider/bitbucketcloud/bitbucket.go @@ -112,8 +112,11 @@ func (v *Provider) CreateStatus(_ context.Context, event *info.Event, statusopts if err != nil { return err } + + eventType := triggertype.IsPullRequestType(event.EventType) if statusopts.Conclusion != "STOPPED" && statusopts.Status == "completed" && - statusopts.Text != "" && event.EventType == triggertype.PullRequest.String() { + statusopts.Text != "" && + (eventType == triggertype.PullRequest || event.TriggerTarget == triggertype.PullRequest) { onPr := "" if statusopts.OriginalPipelineRunName != "" { onPr = "/" + statusopts.OriginalPipelineRunName diff --git a/pkg/provider/gitea/gitea.go b/pkg/provider/gitea/gitea.go index f46f525f9..58e4adf2a 100644 --- a/pkg/provider/gitea/gitea.go +++ b/pkg/provider/gitea/gitea.go @@ -174,16 +174,12 @@ func (v *Provider) createStatusCommit(event *info.Event, pacopts *info.PacOpts, if _, _, err := v.Client.CreateStatus(event.Organization, event.Repository, event.SHA, gStatus); err != nil { return err } - eventType := event.EventType - if eventType == triggertype.OkToTest.String() || eventType == triggertype.Retest.String() || - eventType == triggertype.Cancel.String() { - eventType = triggertype.PullRequest.String() - } - if opscomments.IsAnyOpsEventType(eventType) { - eventType = triggertype.PullRequest.String() - } - if status.Text != "" && (eventType == triggertype.PullRequest.String() || event.TriggerTarget == triggertype.PullRequest) { + eventType := triggertype.IsPullRequestType(event.EventType) + if opscomments.IsAnyOpsEventType(eventType.String()) { + eventType = triggertype.PullRequest + } + if status.Text != "" && (eventType == triggertype.PullRequest || event.TriggerTarget == triggertype.PullRequest) { status.Text = strings.ReplaceAll(strings.TrimSpace(status.Text), "
", "\n") _, _, err := v.Client.CreateIssueComment(event.Organization, event.Repository, int64(event.PullRequestNumber), gitea.CreateIssueCommentOption{ diff --git a/pkg/provider/github/status.go b/pkg/provider/github/status.go index 53397dac8..429ca29db 100644 --- a/pkg/provider/github/status.go +++ b/pkg/provider/github/status.go @@ -13,6 +13,7 @@ import ( "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/keys" "github.com/openshift-pipelines/pipelines-as-code/pkg/kubeinteraction" kstatus "github.com/openshift-pipelines/pipelines-as-code/pkg/kubeinteraction/status" + "github.com/openshift-pipelines/pipelines-as-code/pkg/opscomments" "github.com/openshift-pipelines/pipelines-as-code/pkg/params/info" "github.com/openshift-pipelines/pipelines-as-code/pkg/params/triggertype" "github.com/openshift-pipelines/pipelines-as-code/pkg/provider" @@ -321,7 +322,13 @@ func (v *Provider) createStatusCommit(ctx context.Context, runevent *info.Event, runevent.Organization, runevent.Repository, runevent.SHA, ghstatus); err != nil { return err } - if (status.Status == "completed" || (status.Status == "queued" && status.Title == "Pending approval")) && status.Text != "" && runevent.EventType == triggertype.PullRequest.String() { + eventType := triggertype.IsPullRequestType(runevent.EventType) + if opscomments.IsAnyOpsEventType(eventType.String()) { + eventType = triggertype.PullRequest + } + if (status.Status == "completed" || + (status.Status == "queued" && status.Title == "Pending approval")) && + status.Text != "" && eventType == triggertype.PullRequest { _, _, err = v.Client.Issues.CreateComment(ctx, runevent.Organization, runevent.Repository, runevent.PullRequestNumber, &github.IssueComment{ diff --git a/pkg/provider/gitlab/gitlab.go b/pkg/provider/gitlab/gitlab.go index 4ca9fdf8a..2247145dd 100644 --- a/pkg/provider/gitlab/gitlab.go +++ b/pkg/provider/gitlab/gitlab.go @@ -40,6 +40,8 @@ const ( noClientErrStr = `no gitlab client has been initialized, exiting... (hint: did you forget setting a secret on your repo?)` ) +var anyMergeRequestEventType = []string{"Merge Request", "MergeRequest"} + var _ provider.Interface = (*Provider)(nil) type Provider struct { @@ -217,10 +219,12 @@ func (v *Provider) CreateStatus(_ context.Context, event *info.Event, statusOpts "cannot set status with the GitLab token because of: "+err.Error()) } + eventType := triggertype.IsPullRequestType(event.EventType) + if opscomments.IsAnyOpsEventType(eventType.String()) { + eventType = triggertype.PullRequest + } // only add a note when we are on a MR - if event.EventType == triggertype.PullRequest.String() || - event.EventType == "Merge_Request" || event.EventType == "Merge Request" || - opscomments.IsAnyOpsEventType(event.EventType) { + if eventType == triggertype.PullRequest || provider.Valid(event.EventType, anyMergeRequestEventType) { mopt := &gitlab.CreateMergeRequestNoteOptions{Body: gitlab.Ptr(body)} _, _, err := v.Client.Notes.CreateMergeRequestNote(event.TargetProjectID, event.PullRequestNumber, mopt) return err diff --git a/pkg/reconciler/emit_metrics_test.go b/pkg/reconciler/emit_metrics_test.go index 0a952738e..9b5a23259 100644 --- a/pkg/reconciler/emit_metrics_test.go +++ b/pkg/reconciler/emit_metrics_test.go @@ -132,7 +132,7 @@ func TestCalculatePipelineRunDuration(t *testing.T) { conditionType: apis.ConditionSucceeded, status: corev1.ConditionTrue, reason: tektonv1.PipelineRunReasonSuccessful.String(), - completionTime: metav1.NewTime(startTime.Time.Add(time.Minute)), + completionTime: metav1.NewTime(startTime.Add(time.Minute)), tags: map[string]string{ "namespace": "pac-ns", "reason": tektonv1.PipelineRunReasonSuccessful.String(), @@ -148,7 +148,7 @@ func TestCalculatePipelineRunDuration(t *testing.T) { conditionType: apis.ConditionSucceeded, status: corev1.ConditionTrue, reason: tektonv1.PipelineRunReasonCompleted.String(), - completionTime: metav1.NewTime(startTime.Time.Add(time.Minute)), + completionTime: metav1.NewTime(startTime.Add(time.Minute)), tags: map[string]string{ "namespace": "pac-ns", "reason": tektonv1.PipelineRunReasonCompleted.String(), @@ -164,7 +164,7 @@ func TestCalculatePipelineRunDuration(t *testing.T) { conditionType: apis.ConditionSucceeded, status: corev1.ConditionFalse, reason: tektonv1.PipelineRunReasonFailed.String(), - completionTime: metav1.NewTime(startTime.Time.Add(2 * time.Minute)), + completionTime: metav1.NewTime(startTime.Add(2 * time.Minute)), tags: map[string]string{ "namespace": "pac-ns", "reason": tektonv1.PipelineRunReasonFailed.String(), @@ -180,7 +180,7 @@ func TestCalculatePipelineRunDuration(t *testing.T) { conditionType: apis.ConditionSucceeded, status: corev1.ConditionFalse, reason: tektonv1.PipelineRunReasonCancelled.String(), - completionTime: metav1.NewTime(startTime.Time.Add(2 * time.Second)), + completionTime: metav1.NewTime(startTime.Add(2 * time.Second)), tags: map[string]string{ "namespace": "pac-ns", "reason": tektonv1.PipelineRunReasonCancelled.String(), @@ -196,7 +196,7 @@ func TestCalculatePipelineRunDuration(t *testing.T) { conditionType: apis.ConditionSucceeded, status: corev1.ConditionFalse, reason: tektonv1.PipelineRunReasonTimedOut.String(), - completionTime: metav1.NewTime(startTime.Time.Add(10 * time.Minute)), + completionTime: metav1.NewTime(startTime.Add(10 * time.Minute)), tags: map[string]string{ "namespace": "pac-ns", "reason": tektonv1.PipelineRunReasonTimedOut.String(), @@ -212,7 +212,7 @@ func TestCalculatePipelineRunDuration(t *testing.T) { conditionType: apis.ConditionSucceeded, status: corev1.ConditionFalse, reason: tektonv1.PipelineRunReasonCouldntGetPipeline.String(), - completionTime: metav1.NewTime(startTime.Time.Add(time.Second)), + completionTime: metav1.NewTime(startTime.Add(time.Second)), tags: map[string]string{ "namespace": "pac-ns", "reason": tektonv1.PipelineRunReasonCouldntGetPipeline.String(), diff --git a/test/gitea_test.go b/test/gitea_test.go index e6ca80ad6..c864578f8 100644 --- a/test/gitea_test.go +++ b/test/gitea_test.go @@ -760,10 +760,11 @@ func TestGiteaErrorSnippet(t *testing.T) { } func TestGiteaOnPullRequestLabels(t *testing.T) { + prName := "on-label" topts := &tgitea.TestOpts{ TargetEvent: triggertype.PullRequest.String(), YAMLFiles: map[string]string{ - ".tekton/pr.yaml": "testdata/pipelinerun-on-label.yaml", + fmt.Sprintf(".tekton/%s.yaml", prName): "testdata/pipelinerun-on-label.yaml", }, ExpectEvents: false, CheckForNumberStatus: 0, @@ -796,6 +797,10 @@ func TestGiteaOnPullRequestLabels(t *testing.T) { twait.GoldenPodLog(context.Background(), t, topts.ParamsRun, topts.TargetNS, fmt.Sprintf("tekton.dev/pipelineRun=%s,tekton.dev/pipelineTask=task", repo.Status[0].PipelineRunName), "step-success", strings.ReplaceAll(fmt.Sprintf("%s.golden", t.Name()), "/", "-"), 2) + + // Make sure the on-label pr has triggered and post status + topts.Regexp = regexp.MustCompile(fmt.Sprintf("Pipelines as Code CI/%s.* has successfully validated your commit", prName)) + tgitea.WaitForPullRequestCommentMatch(t, topts) } func TestGiteaErrorSnippetWithSecret(t *testing.T) { diff --git a/test/gitlab_merge_request_test.go b/test/gitlab_merge_request_test.go index a658a3729..ab1c4cdf3 100644 --- a/test/gitlab_merge_request_test.go +++ b/test/gitlab_merge_request_test.go @@ -9,6 +9,7 @@ import ( "net/http" "regexp" "testing" + "time" "github.com/google/go-github/v66/github" "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/keys" @@ -103,6 +104,7 @@ func TestGitlabMergeRequest(t *testing.T) { Body: clientGitlab.Ptr("/retest"), }) assert.NilError(t, err) + sopt = twait.SuccessOpt{ Title: commitTitle, OnEvent: opscomments.RetestAllCommentEventType.String(), @@ -123,30 +125,76 @@ func TestGitlabMergeRequest(t *testing.T) { } // we get 2 PRS initially, 2 prs from the push update and 2 prs from the /retest == 6 assert.Equal(t, 6, successCommentsPost) +} + +func TestGitlabOnLabel(t *testing.T) { + prName := "on-label" + targetNS := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-ns") + ctx := context.Background() + runcnx, opts, glprovider, err := tgitlab.Setup(ctx) + assert.NilError(t, err) + ctx, err = cctx.GetControllerCtxInfo(ctx, runcnx) + assert.NilError(t, err) + runcnx.Clients.Log.Info("Testing with Gitlab") + + projectinfo, resp, err := glprovider.Client.Projects.GetProject(opts.ProjectID, nil) + assert.NilError(t, err) + if resp != nil && resp.StatusCode == http.StatusNotFound { + t.Errorf("Repository %s not found in %s", opts.Organization, opts.Repo) + } - // Now test that we react to labels - scmEntries, err := payload.GetEntries(map[string]string{ - ".tekton/pipelinerun-label.yaml": "testdata/pipelinerun-on-label.yaml", + err = tgitlab.CreateCRD(ctx, projectinfo, runcnx, targetNS, nil) + assert.NilError(t, err) + + entries, err := payload.GetEntries(map[string]string{ + fmt.Sprintf(".tekton/%s.yaml", prName): "testdata/pipelinerun-on-label.yaml", }, targetNS, projectinfo.DefaultBranch, triggertype.PullRequest.String(), map[string]string{}) assert.NilError(t, err) + targetRefName := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-test") + gitCloneURL, err := scm.MakeGitCloneURL(projectinfo.WebURL, opts.UserName, opts.Password) + assert.NilError(t, err) + commitTitle := "Committing files from test on " + targetRefName + scmOpts := &scm.Opts{ + GitURL: gitCloneURL, + CommitTitle: commitTitle, + Log: runcnx.Clients.Log, + WebURL: projectinfo.WebURL, + TargetRefName: targetRefName, + BaseRefName: projectinfo.DefaultBranch, + } + scm.PushFilesToRefGit(t, scmOpts, entries) + runcnx.Clients.Log.Infof("Branch %s has been created and pushed with files", targetRefName) + + mrTitle := "TestMergeRequest - " + targetRefName + mrID, err := tgitlab.CreateMR(glprovider.Client, opts.ProjectID, targetRefName, projectinfo.DefaultBranch, mrTitle) + assert.NilError(t, err) + runcnx.Clients.Log.Infof("MergeRequest %s/-/merge_requests/%d has been created", projectinfo.WebURL, mrID) + defer tgitlab.TearDown(ctx, t, runcnx, glprovider, mrID, targetRefName, targetNS, opts.ProjectID) + + runcnx.Clients.Log.Infof("waiting 5 seconds until we make sure nothing happened") + time.Sleep(5 * time.Second) + prsNew, err := runcnx.Clients.Tekton.TektonV1().PipelineRuns(targetNS).List(ctx, metav1.ListOptions{}) + assert.NilError(t, err) + assert.Assert(t, len(prsNew.Items) == 0) - scm.PushFilesToRefGit(t, scmOpts, scmEntries) - _, _, err = glprovider.Client.MergeRequests.UpdateMergeRequest(opts.ProjectID, mrID, &clientGitlab.UpdateMergeRequestOptions{ + // now add a Label + mr, _, err := glprovider.Client.MergeRequests.UpdateMergeRequest(opts.ProjectID, mrID, &clientGitlab.UpdateMergeRequestOptions{ Labels: &clientGitlab.LabelOptions{"bug"}, }) assert.NilError(t, err) - notes, _, err = glprovider.Client.Notes.ListMergeRequestNotes(opts.ProjectID, mrID, nil) - assert.NilError(t, err) - successCommentsPost = 0 - for _, n := range notes { - if successRegexp.MatchString(n.Body) { - successCommentsPost++ - } + waitOpts := twait.Opts{ + RepoName: targetNS, + Namespace: targetNS, + MinNumberStatus: 1, + PollTimeout: twait.DefaultTimeout, + TargetSHA: mr.SHA, } - // we get 2 PRS initially, 2 prs from the push update and 2 prs from the /retest + 2 prs from the label == 8 - assert.Equal(t, 8, successCommentsPost) + repo, err := twait.UntilRepositoryUpdated(ctx, runcnx.Clients, waitOpts) + assert.NilError(t, err) + assert.Assert(t, len(repo.Status) > 0) + assert.Equal(t, *repo.Status[0].EventType, triggertype.LabelUpdate.String()) } func TestGitlabOnComment(t *testing.T) {