diff --git a/test/bitbucket_cloud_pullrequest_test.go b/test/bitbucket_cloud_pullrequest_test.go index 98bbc2a7bf..79eecd1362 100644 --- a/test/bitbucket_cloud_pullrequest_test.go +++ b/test/bitbucket_cloud_pullrequest_test.go @@ -87,9 +87,9 @@ func TestBitbucketCloudPullRequestCancelInProgressMerged(t *testing.T) { Namespace: targetNS, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: sha, + TargetSHA: []string{sha}, } - err = twait.UntilPipelineRunCreated(ctx, runcnx.Clients, waitOpts) + _, err = twait.UntilPipelineRunCreated(ctx, runcnx.Clients, waitOpts) assert.NilError(t, err) po := &bitbucket.PullRequestsOptions{ diff --git a/test/gitea_access_control_test.go b/test/gitea_access_control_test.go index b6ac68f222..296e48e16a 100644 --- a/test/gitea_access_control_test.go +++ b/test/gitea_access_control_test.go @@ -20,6 +20,7 @@ import ( "github.com/openshift-pipelines/pipelines-as-code/test/pkg/payload" "github.com/openshift-pipelines/pipelines-as-code/test/pkg/scm" twait "github.com/openshift-pipelines/pipelines-as-code/test/pkg/wait" + tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" "gotest.tools/v3/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -472,9 +473,9 @@ func TestGiteaPolicyAllowedOwnerFiles(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: npr.Head.Sha, + TargetSHA: []string{npr.Head.Sha}, } - _, err = twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + _, err = twait.UntilPipelineRunHasReason(context.Background(), topts.ParamsRun.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) time.Sleep(5 * time.Second) // “Evil does not sleep. It waits.” - Galadriel diff --git a/test/gitea_gitops_commands_test.go b/test/gitea_gitops_commands_test.go index c86132c94f..583bfe9d5f 100644 --- a/test/gitea_gitops_commands_test.go +++ b/test/gitea_gitops_commands_test.go @@ -11,6 +11,7 @@ import ( "time" forgejo "codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v3" + "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/keys" "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1" "github.com/openshift-pipelines/pipelines-as-code/pkg/opscomments" "github.com/openshift-pipelines/pipelines-as-code/pkg/params/triggertype" @@ -20,6 +21,7 @@ import ( pacrepo "github.com/openshift-pipelines/pipelines-as-code/test/pkg/repository" "github.com/openshift-pipelines/pipelines-as-code/test/pkg/secret" twait "github.com/openshift-pipelines/pipelines-as-code/test/pkg/wait" + tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" "github.com/tektoncd/pipeline/pkg/names" "gotest.tools/v3/assert" ) @@ -44,10 +46,10 @@ func TestGiteaCancelRun(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: topts.PullRequest.Head.Sha, + TargetSHA: []string{topts.PullRequest.Head.Sha}, } - _, err := twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) - assert.Error(t, err, "pipelinerun has failed") + _, err := twait.UntilPipelineRunHasReason(context.Background(), topts.ParamsRun.Clients, tektonv1.PipelineRunReasonCancelled, waitOpts) + assert.NilError(t, err) tgitea.CheckIfPipelineRunsCancelled(t, topts) } @@ -100,33 +102,33 @@ func TestGiteaOnCommentAnnotation(t *testing.T) { MinNumberStatus: 2, PollTimeout: twait.DefaultTimeout, } - _, err = twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + _, err = twait.UntilPipelineRunCreated(context.Background(), topts.ParamsRun.Clients, waitOpts) assert.NilError(t, err) tgitea.PostCommentOnPullRequest(t, topts, triggerComment) waitOpts.MinNumberStatus = 3 // now we should have only 3 status, the last one is the on comment match from the comment sent // but should not have matched the pull request ones - repo, err := twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + prs, err := twait.UntilPipelineRunCreated(context.Background(), topts.ParamsRun.Clients, waitOpts) assert.NilError(t, err) - assert.Equal(t, len(repo.Status), waitOpts.MinNumberStatus, fmt.Sprintf("should have only %d status", waitOpts.MinNumberStatus)) - assert.Equal(t, *repo.Status[len(repo.Status)-1].EventType, opscomments.OnCommentEventType.String(), "should have a on comment event type") + assert.Equal(t, len(prs), waitOpts.MinNumberStatus, fmt.Sprintf("should have only %d status", waitOpts.MinNumberStatus)) + assert.Equal(t, prs[len(prs)-1].Annotations[keys.EventType], opscomments.OnCommentEventType.String(), "should have a on comment event type") - last := repo.Status[len(repo.Status)-1] + last := prs[len(prs)-1] twait.GoldenPodLog(context.Background(), t, topts.ParamsRun, topts.TargetNS, - fmt.Sprintf("tekton.dev/pipelineRun=%s", last.PipelineRunName), + fmt.Sprintf("tekton.dev/pipelineRun=%s", last.Name), "step-task", strings.ReplaceAll(fmt.Sprintf("%s-pipelinerun-on-comment-annotation.golden", t.Name()), "/", "-"), 2, nil) tgitea.PostCommentOnPullRequest(t, topts, fmt.Sprintf(`%s revision=main custom1=thisone custom2="another one" custom_no_initial_value="a \"quote\""`, triggerComment)) waitOpts.MinNumberStatus = 4 - repo, err = twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + prs, err = twait.UntilPipelineRunsFinished(context.Background(), topts.ParamsRun.Clients, waitOpts) assert.NilError(t, err) - assert.Equal(t, len(repo.Status), waitOpts.MinNumberStatus, fmt.Sprintf("should have only %d status", waitOpts.MinNumberStatus)) - assert.Equal(t, *repo.Status[len(repo.Status)-1].EventType, opscomments.OnCommentEventType.String(), "should have a on comment event type") + assert.Equal(t, len(prs), waitOpts.MinNumberStatus, fmt.Sprintf("should have only %d status", waitOpts.MinNumberStatus)) + assert.Equal(t, prs[len(prs)-1].Annotations[keys.EventType], opscomments.OnCommentEventType.String(), "should have a on comment event type") // now we should have only 3 status, the last one is the on comment match with an argument redefining the revision which is a standard parameter - last = repo.Status[len(repo.Status)-1] - err = twait.RegexpMatchingInPodLog(context.Background(), topts.ParamsRun, topts.TargetNS, fmt.Sprintf("tekton.dev/pipelineRun=%s", last.PipelineRunName), "step-task", regexp.Regexp{}, t.Name(), 2, nil) + last = prs[len(prs)-1] + err = twait.RegexpMatchingInPodLog(context.Background(), topts.ParamsRun, topts.TargetNS, fmt.Sprintf("tekton.dev/pipelineRun=%s", last.Name), "step-task", regexp.Regexp{}, t.Name(), 2, nil) assert.NilError(t, err) } @@ -168,15 +170,15 @@ func TestGiteaOnCommentTestOverride(t *testing.T) { MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, } - repo, err := twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + prs, err := twait.UntilPipelineRunsFinished(context.Background(), topts.ParamsRun.Clients, waitOpts) assert.NilError(t, err) - assert.Equal(t, len(repo.Status), 1, "should have exactly 1 status") - assert.Equal(t, *repo.Status[0].EventType, opscomments.OnCommentEventType.String(), + assert.Equal(t, len(prs), 1, "should have exactly 1 status") + assert.Equal(t, prs[0].Annotations[keys.EventType], opscomments.OnCommentEventType.String(), "should have matched via on-comment annotation, not built-in /test handler") - last := repo.Status[0] + last := prs[0] err = twait.RegexpMatchingInPodLog(context.Background(), topts.ParamsRun, topts.TargetNS, - fmt.Sprintf("tekton.dev/pipelineRun=%s", last.PipelineRunName), "step-task", + fmt.Sprintf("tekton.dev/pipelineRun=%s", last.Name), "step-task", *regexp.MustCompile("custom1 is overridden"), "", 2, nil) assert.NilError(t, err) } @@ -219,15 +221,15 @@ func TestGiteaTestPipelineRunExplicitlyWithTestComment(t *testing.T) { PollTimeout: twait.DefaultTimeout, } - repo, err := twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + prs, err := twait.UntilPipelineRunCreated(context.Background(), topts.ParamsRun.Clients, waitOpts) assert.NilError(t, err) - assert.Equal(t, len(repo.Status), 1, "should have only 1 status") - assert.Equal(t, *repo.Status[0].EventType, opscomments.TestSingleCommentEventType.String(), "should have a test comment event in status") - assert.Assert(t, strings.HasPrefix(repo.Status[0].PipelineRunName, targetPrName+"-"), - "we didn't target the proper pipelinerun, we tested: %s", repo.Status[0].PipelineRunName) + assert.Equal(t, len(prs), 1, "should have only 1 status") + assert.Equal(t, prs[0].Annotations[keys.EventType], opscomments.TestSingleCommentEventType.String(), "should have a test comment event in status") + assert.Assert(t, strings.HasPrefix(prs[0].Name, targetPrName+"-"), + "we didn't target the proper pipelinerun, we tested: %s", prs[0].Name) - last := repo.Status[len(repo.Status)-1] - err = twait.RegexpMatchingInPodLog(context.Background(), topts.ParamsRun, topts.TargetNS, fmt.Sprintf("tekton.dev/pipelineRun=%s", last.PipelineRunName), "step-task", *regexp.MustCompile("custom is awesome"), "", 2, nil) + last := prs[len(prs)-1] + err = twait.RegexpMatchingInPodLog(context.Background(), topts.ParamsRun, topts.TargetNS, fmt.Sprintf("tekton.dev/pipelineRun=%s", last.Name), "step-task", *regexp.MustCompile("custom is awesome"), "", 2, nil) assert.NilError(t, err) } @@ -266,21 +268,21 @@ func TestGiteaTestAll(t *testing.T) { PollTimeout: twait.DefaultTimeout, } - repo, err := twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + prs, err := twait.UntilPipelineRunCreated(context.Background(), topts.ParamsRun.Clients, waitOpts) assert.NilError(t, err) var hasPullRequest bool var hasTestAll bool - for _, status := range repo.Status { - if *status.EventType == triggertype.PullRequest.String() { + for _, pr := range prs { + if pr.Annotations[keys.EventType] == triggertype.PullRequest.String() { hasPullRequest = true } - if *status.EventType == opscomments.TestAllCommentEventType.String() { + if pr.Annotations[keys.EventType] == opscomments.TestAllCommentEventType.String() { hasTestAll = true } } assert.Assert(t, hasPullRequest, "should have the initial pull request event in status") assert.Assert(t, hasTestAll, "should have a test all comment event in status") - assert.Equal(t, len(repo.Status), 2, "should have only 2 status") + assert.Equal(t, len(prs), 2, "should have only 2 status") } func TestGiteaRetestCommentUpdate(t *testing.T) { @@ -334,16 +336,16 @@ func TestGiteaRetestCommentUpdate(t *testing.T) { PollTimeout: twait.DefaultTimeout, } - repo, err := twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + prs, err := twait.UntilPipelineRunCreated(context.Background(), topts.ParamsRun.Clients, waitOpts) assert.NilError(t, err) var rt bool - for _, status := range repo.Status { - if *status.EventType == triggertype.PullRequest.String() { + for _, pr := range prs { + if pr.Annotations[keys.EventType] == triggertype.PullRequest.String() { rt = true } } assert.Assert(t, rt, "should have a retest all comment event in status") - assert.Equal(t, len(repo.Status), 2, "should have only 2 status") + assert.Equal(t, len(prs), 2, "should have only 2 status") // Verify comment strategy: count pac-status comments. comments, _, err := topts.GiteaCNX.Client().ListRepoIssueComments( diff --git a/test/gitea_params_test.go b/test/gitea_params_test.go index 7d0f6b910f..2f95c3c84a 100644 --- a/test/gitea_params_test.go +++ b/test/gitea_params_test.go @@ -128,9 +128,9 @@ func TestGiteaRetestPreservesSourceURL(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: 2, PollTimeout: twait.DefaultTimeout, - TargetSHA: topts.PullRequest.Head.Sha, + TargetSHA: []string{topts.PullRequest.Head.Sha}, } - _, err = twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + _, err = twait.UntilPipelineRunHasReason(context.Background(), topts.ParamsRun.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) assert.NilError(t, twait.UntilMinPRAppeared(context.Background(), topts.ParamsRun.Clients, waitOpts, 2)) @@ -311,14 +311,14 @@ func TestGiteaGlobalRepoParams(t *testing.T) { MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, } - repo, err := twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + prs, err := twait.UntilPipelineRunHasReason(context.Background(), topts.ParamsRun.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) - last := repo.Status[len(repo.Status)-1] + last := prs[len(prs)-1] err = twait.RegexpMatchingInPodLog( context.Background(), topts.ParamsRun, topts.TargetNS, - fmt.Sprintf("tekton.dev/pipelineRun=%s", last.PipelineRunName), + fmt.Sprintf("tekton.dev/pipelineRun=%s", last.Name), "step-test-params-value", regexp.Regexp{}, t.Name(), @@ -390,14 +390,14 @@ func TestGiteaGlobalRepoUseLocalDef(t *testing.T) { MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, } - repo, err := twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + prs, err := twait.UntilPipelineRunHasReason(context.Background(), topts.ParamsRun.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) - last := repo.Status[len(repo.Status)-1] + last := prs[len(prs)-1] err = twait.RegexpMatchingInPodLog( context.Background(), topts.ParamsRun, topts.TargetNS, - fmt.Sprintf("tekton.dev/pipelineRun=%s", last.PipelineRunName), + fmt.Sprintf("tekton.dev/pipelineRun=%s", last.Name), "step-test-params-value", regexp.Regexp{}, t.Name(), @@ -480,14 +480,13 @@ func TestGiteaParamsOnRepoCR(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: "", } - repo, err := twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + prs, err := twait.UntilPipelineRunHasReason(context.Background(), topts.ParamsRun.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) - assert.Assert(t, len(repo.Status) != 0) + assert.Assert(t, len(prs) != 0) assert.NilError(t, twait.RegexpMatchingInPodLog(context.Background(), topts.ParamsRun, topts.TargetNS, fmt.Sprintf("tekton.dev/pipelineRun=%s,tekton.dev/pipelineTask=params", - repo.Status[0].PipelineRunName), "step-test-params-value", *regexp.MustCompile( + prs[0].Name), "step-test-params-value", *regexp.MustCompile( "I am the most Kawaī params\nSHHHHHHH\nFollow me on my ig #nofilter\n{{ no_match }}\nHey I show up from a payload match\n{{ secret_nothere }}\n{{ no_initial_value }}"), "", 2, nil)) } @@ -538,9 +537,8 @@ my email is a true beauty and like groot, I AM pac` Namespace: topts.TargetNS, MinNumberStatus: 2, // 1 means 2 🙃 PollTimeout: twait.DefaultTimeout, - TargetSHA: topts.PullRequest.Head.Sha, } - _, err = twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + _, err = twait.UntilPipelineRunHasReason(context.Background(), topts.ParamsRun.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) time.Sleep(5 * time.Second) @@ -622,9 +620,8 @@ func TestGiteaParamsChangedFilesCEL(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: 2, // 1 means 2 🙃 PollTimeout: twait.DefaultTimeout, - TargetSHA: topts.PullRequest.Head.Sha, } - _, err = twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + _, err = twait.UntilPipelineRunHasReason(context.Background(), topts.ParamsRun.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) time.Sleep(5 * time.Second) @@ -669,9 +666,8 @@ func TestGiteaParamsChangedFilesCEL(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: 4, // 1 means 2 🙃 PollTimeout: twait.DefaultTimeout, - TargetSHA: topts.PullRequest.Head.Sha, } - _, err = twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + _, err = twait.UntilPipelineRunHasReason(context.Background(), topts.ParamsRun.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) time.Sleep(5 * time.Second) diff --git a/test/gitea_retest_pruned_test.go b/test/gitea_retest_pruned_test.go index b056a0f343..cc3847e14c 100644 --- a/test/gitea_retest_pruned_test.go +++ b/test/gitea_retest_pruned_test.go @@ -53,19 +53,18 @@ func TestGiteaRetestAfterPipelineRunPruning(t *testing.T) { RepoName: topts.TargetNS, Namespace: topts.TargetNS, PollTimeout: twait.DefaultTimeout, - TargetSHA: formatting.CleanValueKubernetes(sha), + TargetSHA: []string{formatting.CleanValueKubernetes(sha)}, }, 2) assert.NilError(t, err) - // Wait for repository to have at least 2 status entries - topts.ParamsRun.Clients.Log.Infof("Waiting for Repository status to have 2 entries") - _, err = twait.UntilRepositoryUpdated(ctx, topts.ParamsRun.Clients, twait.Opts{ - RepoName: topts.TargetNS, - Namespace: topts.TargetNS, - MinNumberStatus: 2, - PollTimeout: twait.DefaultTimeout, - TargetSHA: sha, - FailOnRepoCondition: "no-match", + // Wait for both PipelineRuns to finish (1 success + 1 failure) + topts.ParamsRun.Clients.Log.Infof("Waiting for 2 PipelineRuns to finish") + _, err = twait.UntilPipelineRunsFinished(ctx, topts.ParamsRun.Clients, twait.Opts{ + RepoName: topts.TargetNS, + Namespace: topts.TargetNS, + MinNumberStatus: 2, + PollTimeout: twait.DefaultTimeout, + TargetSHA: []string{sha}, }) assert.NilError(t, err) diff --git a/test/gitea_test.go b/test/gitea_test.go index 271dc1ce45..b1cc6cf5af 100644 --- a/test/gitea_test.go +++ b/test/gitea_test.go @@ -44,6 +44,7 @@ import ( "github.com/openshift-pipelines/pipelines-as-code/test/pkg/scm" "github.com/openshift-pipelines/pipelines-as-code/test/pkg/secret" twait "github.com/openshift-pipelines/pipelines-as-code/test/pkg/wait" + tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" rtesting "knative.dev/pkg/reconciler/testing" ) @@ -547,9 +548,9 @@ func TestGiteaConfigMaxKeepRun(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: 1, // 1 means 2 🙃 PollTimeout: twait.DefaultTimeout, - TargetSHA: topts.PullRequest.Head.Sha, + TargetSHA: []string{topts.PullRequest.Head.Sha}, } - _, err := twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + _, err := twait.UntilPipelineRunHasReason(context.Background(), topts.ParamsRun.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) time.Sleep(15 * time.Second) // “Evil does not sleep. It waits.” - Galadriel @@ -657,9 +658,9 @@ func TestGiteaConfigCancelInProgressAfterPRClosed(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: topts.SHA, + TargetSHA: []string{topts.SHA}, } - err := twait.UntilPipelineRunCreated(context.Background(), topts.ParamsRun.Clients, waitOpts) + _, err := twait.UntilPipelineRunCreated(context.Background(), topts.ParamsRun.Clients, waitOpts) assert.NilError(t, err) closed := forgejo.StateClosed @@ -878,14 +879,14 @@ func TestGiteaConcurrencyOrderedExecution(t *testing.T) { _, f := tgitea.TestPR(t, topts) defer f() - repo, err := topts.ParamsRun.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(topts.TargetNS).Get(context.Background(), topts.TargetNS, metav1.GetOptions{}) + prs, err := topts.ParamsRun.Clients.Tekton.TektonV1().PipelineRuns(topts.TargetNS).List(context.Background(), metav1.ListOptions{}) assert.NilError(t, err) - // check the last 3 update in RepositoryRunStatus are in order - statusLen := len(repo.Status) - assert.Assert(t, strings.HasPrefix(repo.Status[statusLen-3].PipelineRunName, "abc")) - assert.Assert(t, strings.HasPrefix(repo.Status[statusLen-2].PipelineRunName, "pqr")) - assert.Assert(t, strings.HasPrefix(repo.Status[statusLen-1].PipelineRunName, "xyz")) - time.Sleep(time.Second * 10) + assert.Assert(t, len(prs.Items) >= 3, "should have 3 pipelineruns") + + sort.PipelineRunSortByCompletionTime(prs.Items) + assert.Assert(t, strings.HasPrefix(prs.Items[len(prs.Items)-1].Name, "abc")) + assert.Assert(t, strings.HasPrefix(prs.Items[len(prs.Items)-2].Name, "pqr")) + assert.Assert(t, strings.HasPrefix(prs.Items[len(prs.Items)-3].Name, "xyz")) } func TestGiteaOnPathChange(t *testing.T) { @@ -1044,9 +1045,9 @@ func TestGiteaOnPullRequestLabels(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: 1, // 1 means 2 🙃 PollTimeout: twait.DefaultTimeout, - TargetSHA: topts.PullRequest.Head.Sha, + TargetSHA: []string{topts.PullRequest.Head.Sha}, } - _, err := twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + _, err := twait.UntilPipelineRunHasReason(context.Background(), topts.ParamsRun.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) topts.CheckForStatus = "success" @@ -1350,7 +1351,7 @@ func TestGiteaPushToTagGreedy(t *testing.T) { MinNumberStatus: 0, PollTimeout: twait.DefaultTimeout, } - _, err = twait.UntilRepositoryUpdated(context.Background(), topts.ParamsRun.Clients, waitOpts) + _, err = twait.UntilPipelineRunHasReason(context.Background(), topts.ParamsRun.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) } diff --git a/test/github_comment_strategy_update_test.go b/test/github_comment_strategy_update_test.go index 258119bdad..fe6e45859c 100644 --- a/test/github_comment_strategy_update_test.go +++ b/test/github_comment_strategy_update_test.go @@ -165,7 +165,6 @@ func TestGithubGHEWebhookCommentStrategyUpdateMultiplePLRs(t *testing.T) { Title: g.CommitTitle, TargetNS: g.TargetNamespace, NumberofPRMatch: 2, - SHA: g.SHA, OnEvent: "pull_request", } twait.Succeeded(ctx, t, g.Cnx, g.Options, sopt) @@ -210,7 +209,9 @@ func TestGithubGHEWebhookCommentStrategyUpdateMultiplePLRs(t *testing.T) { g.Cnx.Clients.Log.Infof("Pushed trigger commit: %s", sha) sopt.NumberofPRMatch = 4 - sopt.SHA = sha + // if there are multiple pipelineruns, we don't need to SHA because after a new commit is pushed, + // we cannot poll for the two SHA in Succeeded polling function. + // sopt.SHA = sha sopt.Title = "test: trigger re-run" twait.Succeeded(ctx, t, g.Cnx, g.Options, sopt) @@ -255,8 +256,9 @@ func TestGithubGHEWebhookCommentStrategyUpdateMarkerMatchingWithRegexChars(t *te "testdata/pipelinerun-regex-name.yaml", "testdata/pipelinerun2-regex-name.yaml", }, - GHE: true, - Webhook: true, + GHE: true, + Webhook: true, + NoStatusCheck: true, // Succeeded is called so it will check the status of the pipelineruns. } commentStrategy := &v1alpha1.Settings{ diff --git a/test/github_config_maxkeepruns_test.go b/test/github_config_maxkeepruns_test.go index b883bd785f..0df8c2011e 100644 --- a/test/github_config_maxkeepruns_test.go +++ b/test/github_config_maxkeepruns_test.go @@ -38,9 +38,9 @@ func TestGithubGHEMaxKeepRuns(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 2, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } - _, err = twait.UntilRepositoryUpdated(ctx, g.Cnx.Clients, waitOpts) + _, err = twait.UntilPipelineRunsFinished(ctx, g.Cnx.Clients, waitOpts) assert.NilError(t, err) count := 0 diff --git a/test/github_gitops_commands_prefix_test.go b/test/github_gitops_commands_prefix_test.go index ae00da7a6b..47ae551e7b 100644 --- a/test/github_gitops_commands_prefix_test.go +++ b/test/github_gitops_commands_prefix_test.go @@ -16,6 +16,7 @@ import ( tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" "gotest.tools/v3/assert" corev1 "k8s.io/api/core/v1" + "knative.dev/pkg/apis" ) func TestGithubPullRequestCustomGitOpsCommandPrefix(t *testing.T) { @@ -49,13 +50,14 @@ func TestGithubPullRequestCustomGitOpsCommandPrefix(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 2, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, } - repo, err := twait.UntilRepositoryUpdated(ctx, g.Cnx.Clients, waitOpts) + prs, err := twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) - g.Cnx.Clients.Log.Infof("Check if repository status shows succeeded") - assert.Equal(t, corev1.ConditionTrue, repo.Status[len(repo.Status)-1].Conditions[0].Status) + g.Cnx.Clients.Log.Infof("Check if pipelinerun status shows succeeded") + cond := prs[len(prs)-1].Status.GetCondition(apis.ConditionSucceeded) + assert.Assert(t, cond != nil) + assert.Equal(t, corev1.ConditionTrue, cond.Status) customTestComment = fmt.Sprintf("/%s test pr-gitops-comment", customPrefix) g.Cnx.Clients.Log.Infof("Creating %s comment on PullRequest", customTestComment) @@ -70,7 +72,6 @@ func TestGithubPullRequestCustomGitOpsCommandPrefix(t *testing.T) { OnEvent: opscomments.TestSingleCommentEventType.String(), NumberofPRMatch: 3, MinNumberStatus: 3, - SHA: g.SHA, }) } @@ -97,9 +98,9 @@ func TestGithubPullRequestCustomPrefixCancel(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } - err := twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) + _, err := twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) assert.NilError(t, err) // Cancel with custom prefix customCancelComment := fmt.Sprintf("/%s cancel", customPrefix) @@ -110,6 +111,6 @@ func TestGithubPullRequestCustomPrefixCancel(t *testing.T) { &github.IssueComment{Body: github.Ptr(customCancelComment)}) assert.NilError(t, err) - err = twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonCancelled, waitOpts) + _, err = twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonCancelled, waitOpts) assert.NilError(t, err) } diff --git a/test/github_pullrequest_concurrency_test.go b/test/github_pullrequest_concurrency_test.go index 4e1c1bdcf9..0d77973456 100644 --- a/test/github_pullrequest_concurrency_test.go +++ b/test/github_pullrequest_concurrency_test.go @@ -210,7 +210,7 @@ func testGithubConcurrency(ctx context.Context, t *testing.T, g tgithub.PRTest, Namespace: g.TargetNamespace, MinNumberStatus: 1, PollTimeout: wait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } assert.NilError(t, wait.UntilMinPRAppeared(ctx, g.Cnx.Clients, waitOpts, numberOfPipelineRuns)) diff --git a/test/github_pullrequest_oktotest_test.go b/test/github_pullrequest_oktotest_test.go index a26ed02366..7986e9d7eb 100644 --- a/test/github_pullrequest_oktotest_test.go +++ b/test/github_pullrequest_oktotest_test.go @@ -46,10 +46,6 @@ func TestGithubGHEPullRequestOkToTest(t *testing.T) { URL: repoinfo.GetHTMLURL(), } - repo, err := g.Cnx.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(g.TargetNamespace).Get(ctx, g.TargetNamespace, metav1.GetOptions{}) - assert.NilError(t, err) - initialStatusCount := len(repo.Status) - pruns, err := g.Cnx.Clients.Tekton.TektonV1().PipelineRuns(g.TargetNamespace).List(ctx, metav1.ListOptions{ LabelSelector: fmt.Sprintf("%s=%s", keys.SHA, g.SHA), }) @@ -111,10 +107,6 @@ func TestGithubGHEPullRequestOkToTest(t *testing.T) { assert.NilError(t, err) assert.Equal(t, initialPipelineRunCount, len(pruns.Items), "untrusted issue_comment must not create a new PipelineRun") - repo, err = g.Cnx.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(g.TargetNamespace).Get(ctx, g.TargetNamespace, metav1.GetOptions{}) - assert.NilError(t, err) - assert.Equal(t, initialStatusCount, len(repo.Status), "untrusted issue_comment must not add a new Repository status") - ctx, err = cctx.GetControllerCtxInfo(ctx, g.Cnx) assert.NilError(t, err) numLines := int64(1000) diff --git a/test/github_pullrequest_rerequest_test.go b/test/github_pullrequest_rerequest_test.go index bd3ea6ec4e..f754725707 100644 --- a/test/github_pullrequest_rerequest_test.go +++ b/test/github_pullrequest_rerequest_test.go @@ -16,7 +16,6 @@ import ( twait "github.com/openshift-pipelines/pipelines-as-code/test/pkg/wait" "gotest.tools/v3/assert" corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // TestGithubPullRerequest is a test that will create a pull request and check @@ -88,19 +87,17 @@ func TestGithubGHEPullRerequest(t *testing.T) { assert.NilError(t, err) g.Cnx.Clients.Log.Infof("Wait for the second repository update to be updated") - _, err = twait.UntilRepositoryUpdated(ctx, g.Cnx.Clients, twait.Opts{ + prs, err := twait.UntilPipelineRunsFinished(ctx, g.Cnx.Clients, twait.Opts{ RepoName: g.TargetNamespace, Namespace: g.TargetNamespace, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, }) assert.NilError(t, err) + assert.Assert(t, len(prs) >= 1, "no successful pipelineruns found") + assert.Assert(t, prs[len(prs)-1].Status.Conditions[0].Status == corev1.ConditionTrue) - g.Cnx.Clients.Log.Infof("Check if we have the repository set as succeeded") - repo, err := g.Cnx.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(g.TargetNamespace).Get(ctx, g.TargetNamespace, metav1.GetOptions{}) - assert.NilError(t, err) - assert.Assert(t, repo.Status[len(repo.Status)-1].Conditions[0].Status == corev1.ConditionTrue) csEvent := github.CheckSuiteEvent{ Action: github.Ptr("rerequested"), Installation: &github.Installation{ @@ -138,12 +135,12 @@ func TestGithubGHEPullRerequest(t *testing.T) { assert.NilError(t, err) g.Cnx.Clients.Log.Infof("Wait for the second repository update to be updated") - _, err = twait.UntilRepositoryUpdated(ctx, g.Cnx.Clients, twait.Opts{ + _, err = twait.UntilPipelineRunsFinished(ctx, g.Cnx.Clients, twait.Opts{ RepoName: g.TargetNamespace, Namespace: g.TargetNamespace, MinNumberStatus: 2, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, }) assert.NilError(t, err) @@ -183,17 +180,16 @@ func TestGithubGHEPullRerequest(t *testing.T) { assert.NilError(t, err) g.Cnx.Clients.Log.Infof("Wait for the third repository update (null head_branch resolved from SHA)") - _, err = twait.UntilRepositoryUpdated(ctx, g.Cnx.Clients, twait.Opts{ + prs, err = twait.UntilPipelineRunsFinished(ctx, g.Cnx.Clients, twait.Opts{ RepoName: g.TargetNamespace, Namespace: g.TargetNamespace, MinNumberStatus: 3, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, }) assert.NilError(t, err) + assert.Assert(t, len(prs) >= 3, "no successful pipelineruns found") g.Cnx.Clients.Log.Infof("Check if the third run succeeded (null head_branch case)") - repo, err = g.Cnx.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(g.TargetNamespace).Get(ctx, g.TargetNamespace, metav1.GetOptions{}) - assert.NilError(t, err) - assert.Assert(t, repo.Status[len(repo.Status)-1].Conditions[0].Status == corev1.ConditionTrue) + assert.Assert(t, prs[len(prs)-1].Status.Conditions[0].Status == corev1.ConditionTrue) } diff --git a/test/github_pullrequest_retest_test.go b/test/github_pullrequest_retest_test.go index daf8a406a6..bc6d4cbcda 100644 --- a/test/github_pullrequest_retest_test.go +++ b/test/github_pullrequest_retest_test.go @@ -45,15 +45,10 @@ func TestGithubGHEPullRequestGitopsCommentRetest(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } - _, err = twait.UntilRepositoryUpdated(ctx, g.Cnx.Clients, waitOpts) + _, err = twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) - - g.Cnx.Clients.Log.Infof("Check if we have the repository set as succeeded") - repo, err := g.Cnx.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(g.TargetNamespace).Get(ctx, g.TargetNamespace, metav1.GetOptions{}) - assert.NilError(t, err) - assert.Equal(t, repo.Status[len(repo.Status)-1].Conditions[0].Status, corev1.ConditionTrue) } // TestGithubGHEPullRequestRetest tests the retest functionality of a GitHub pull request. @@ -87,10 +82,10 @@ func TestGithubGHEPullRequestGitopsCommentCancel(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 3, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } assert.NilError(t, err) - err = twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) + _, err = twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) assert.NilError(t, err) g.Cnx.Clients.Log.Infof("/cancel pr-gitops-comment on Pull Request") @@ -105,15 +100,11 @@ func TestGithubGHEPullRequestGitopsCommentCancel(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 1, PollTimeout: 90 * time.Second, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } g.Cnx.Clients.Log.Info("Waiting for PipelineRun to be cancelled") - err = twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonCancelled, cancelWaitOpts) - assert.NilError(t, err) - - g.Cnx.Clients.Log.Info("Waiting for Repository status to reflect cancellation") - _, err = twait.UntilRepositoryHasStatusReason(ctx, g.Cnx.Clients, cancelWaitOpts, tektonv1.PipelineRunReasonCancelled.String()) + _, err = twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonCancelled, cancelWaitOpts) assert.NilError(t, err) pruns, err = g.Cnx.Clients.Tekton.TektonV1().PipelineRuns(g.TargetNamespace).List(ctx, metav1.ListOptions{ @@ -159,11 +150,11 @@ func TestGithubGHERetestWithMultipleFailedPipelineRuns(t *testing.T) { g.RunPullRequest(ctx, t) defer g.TearDown(ctx, t) - err := twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, twait.Opts{ + _, err := twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, twait.Opts{ RepoName: g.TargetNamespace, Namespace: g.TargetNamespace, MinNumberStatus: 1, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, PollTimeout: twait.DefaultTimeout, }) assert.NilError(t, err) diff --git a/test/github_pullrequest_test.go b/test/github_pullrequest_test.go index 73fd8c95e6..e1dcb1b132 100644 --- a/test/github_pullrequest_test.go +++ b/test/github_pullrequest_test.go @@ -279,9 +279,9 @@ func TestGithubGHECancelInProgress(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } - err := twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) + _, err := twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) assert.NilError(t, err) time.Sleep(10 * time.Second) @@ -296,9 +296,9 @@ func TestGithubGHECancelInProgress(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 2, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } - err = twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) + _, err = twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) assert.NilError(t, err) g.Cnx.Clients.Log.Infof("Sleeping for 10 seconds to let the pipelinerun to be cancelled") @@ -351,9 +351,9 @@ func TestGithubGHECancelInProgressPRClosed(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } - err := twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) + _, err := twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) assert.NilError(t, err) g.Cnx.Clients.Log.Infof("Closing the PullRequest") @@ -494,9 +494,9 @@ func TestGithubGHEPullRequestNoPipelineRunCancelledOnPRClosed(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } - err := twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) + _, err := twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) assert.NilError(t, err) g.Cnx.Clients.Log.Infof("Closing the PullRequest") @@ -572,16 +572,16 @@ func TestGithubGHECancelInProgressSettingFromConfigMapOnPR(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 2, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } - err = twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) + _, err = twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) assert.NilError(t, err) // we want one PipelineRun to be cancelled waitOpts.MinNumberStatus = 1 - err = twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonCancelled, waitOpts) + _, err = twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonCancelled, waitOpts) assert.NilError(t, err) } @@ -619,16 +619,16 @@ func TestGithubGHECancelInProgressSettingFromConfigMapOnPush(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 2, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } - err = twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) + _, err = twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) assert.NilError(t, err) // we want one PipelineRun to be cancelled waitOpts.MinNumberStatus = 1 - err = twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonCancelled, waitOpts) + _, err = twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonCancelled, waitOpts) assert.NilError(t, err) } @@ -733,9 +733,9 @@ func TestGithubGHEPullRequestCelPrefix(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } - _, err := twait.UntilRepositoryUpdated(ctx, g.Cnx.Clients, waitOpts) + _, err := twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) prs, err := g.Cnx.Clients.Tekton.TektonV1().PipelineRuns(g.TargetNamespace).List(ctx, metav1.ListOptions{}) diff --git a/test/github_pullrequest_test_comment_test.go b/test/github_pullrequest_test_comment_test.go index 976197f416..1a3b4de7f9 100644 --- a/test/github_pullrequest_test_comment_test.go +++ b/test/github_pullrequest_test_comment_test.go @@ -9,11 +9,14 @@ import ( "testing" "github.com/google/go-github/v85/github" + "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/keys" "github.com/openshift-pipelines/pipelines-as-code/pkg/opscomments" tgithub "github.com/openshift-pipelines/pipelines-as-code/test/pkg/github" twait "github.com/openshift-pipelines/pipelines-as-code/test/pkg/wait" + tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" "gotest.tools/v3/assert" corev1 "k8s.io/api/core/v1" + "knative.dev/pkg/apis" ) func TestGithubGHEPullRequestTest(t *testing.T) { @@ -39,12 +42,14 @@ func TestGithubGHEPullRequestTest(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } - repo, err := twait.UntilRepositoryUpdated(ctx, g.Cnx.Clients, waitOpts) + prs, err := twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) - g.Cnx.Clients.Log.Infof("Check if we have the repository set as succeeded") - assert.Assert(t, repo.Status[len(repo.Status)-1].Conditions[0].Status == corev1.ConditionTrue) + g.Cnx.Clients.Log.Infof("Check if we have the pipelinerun set as succeeded") + cond := prs[len(prs)-1].Status.GetCondition(apis.ConditionSucceeded) + assert.Assert(t, cond != nil) + assert.Equal(t, corev1.ConditionTrue, cond.Status) } func TestGithubGHEOnCommentAnnotation(t *testing.T) { @@ -77,19 +82,21 @@ func TestGithubGHEOnCommentAnnotation(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } - repo, err := twait.UntilRepositoryUpdated(ctx, g.Cnx.Clients, waitOpts) + prs, err := twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) - g.Cnx.Clients.Log.Infof("Check if we have the repository set as succeeded") - assert.Equal(t, repo.Status[len(repo.Status)-1].Conditions[0].Status, corev1.ConditionTrue) - assert.Equal(t, *repo.Status[len(repo.Status)-1].EventType, opscomments.OnCommentEventType.String()) - lastPrName := repo.Status[len(repo.Status)-1].PipelineRunName + g.Cnx.Clients.Log.Infof("Check if we have the pipelinerun set as succeeded") + lastPR := prs[len(prs)-1] + cond := lastPR.Status.GetCondition(apis.ConditionSucceeded) + assert.Assert(t, cond != nil) + assert.Equal(t, corev1.ConditionTrue, cond.Status) + assert.Equal(t, lastPR.Annotations[keys.EventType], opscomments.OnCommentEventType.String()) - err = twait.RegexpMatchingInPodLog(context.Background(), g.Cnx, g.TargetNamespace, fmt.Sprintf("tekton.dev/pipelineRun=%s", lastPrName), "step-task", *regexp.MustCompile(triggerComment), "", 2, nil) + err = twait.RegexpMatchingInPodLog(context.Background(), g.Cnx, g.TargetNamespace, fmt.Sprintf("tekton.dev/pipelineRun=%s", lastPR.Name), "step-task", *regexp.MustCompile(triggerComment), "", 2, nil) assert.NilError(t, err) - err = twait.RegexpMatchingInPodLog(context.Background(), g.Cnx, g.TargetNamespace, fmt.Sprintf("tekton.dev/pipelineRun=%s", lastPrName), "step-task", *regexp.MustCompile(fmt.Sprintf( + err = twait.RegexpMatchingInPodLog(context.Background(), g.Cnx, g.TargetNamespace, fmt.Sprintf("tekton.dev/pipelineRun=%s", lastPR.Name), "step-task", *regexp.MustCompile(fmt.Sprintf( "The event is %s", opscomments.OnCommentEventType.String())), "", 2, nil) assert.NilError(t, err) } diff --git a/test/github_push_retest_test.go b/test/github_push_retest_test.go index a17d46ee66..33e42350a2 100644 --- a/test/github_push_retest_test.go +++ b/test/github_push_retest_test.go @@ -59,17 +59,12 @@ func TestGithubGHEPushRequestGitOpsCommentOnComment(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: len(g.YamlFiles), PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } g.Cnx.Clients.Log.Info("Waiting for Repository to be updated") - _, err = twait.UntilRepositoryUpdated(ctx, g.Cnx.Clients, waitOpts) + _, err = twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) - g.Cnx.Clients.Log.Infof("Check if we have the repository set as succeeded") - repo, err := g.Cnx.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(g.TargetNamespace).Get(ctx, g.TargetNamespace, metav1.GetOptions{}) - assert.NilError(t, err) - assert.Equal(t, repo.Status[len(repo.Status)-1].Conditions[0].Status, corev1.ConditionTrue) - pruns, err = g.Cnx.Clients.Tekton.TektonV1().PipelineRuns(g.TargetNamespace).List(ctx, metav1.ListOptions{ LabelSelector: fmt.Sprintf("%s=%s", keys.SHA, g.SHA), }) @@ -121,10 +116,10 @@ func TestGithubGHEPushRequestGitOpsCommentRetest(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 4, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } g.Cnx.Clients.Log.Info("Waiting for Repository to be updated") - _, err = twait.UntilRepositoryUpdated(ctx, g.Cnx.Clients, waitOpts) + _, err = twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) g.Cnx.Clients.Log.Infof("Check if we have the repository set as succeeded") @@ -178,9 +173,9 @@ func TestGithubGHEPushRequestGitOpsCommentCancel(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: numberOfStatus, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } - err = twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) + _, err = twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) assert.NilError(t, err) comment := "/cancel pipelinerun-on-push branch:" + g.TargetNamespace @@ -195,17 +190,14 @@ func TestGithubGHEPushRequestGitOpsCommentCancel(t *testing.T) { cancelWaitOpts.MinNumberStatus = 1 cancelWaitOpts.PollTimeout = 90 * time.Second - // wait for the cancellation to propagate through PipelineRun status and repository status - err = twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonCancelled, cancelWaitOpts) - if err == nil { - _, err = twait.UntilRepositoryHasStatusReason(ctx, g.Cnx.Clients, cancelWaitOpts, tektonv1.PipelineRunReasonCancelled.String()) - } + // wait for the cancellation to propagate through PipelineRun status + _, err = twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonCancelled, cancelWaitOpts) if err != nil { numLines := int64(1000) reg := regexp.MustCompile(".*cancel-in-progress:.*pipelinerun.*on-push.*") logErr := twait.RegexpMatchingInControllerLog(ctx, g.Cnx, *reg, 10, "ghe-controller", &numLines, nil) if logErr != nil { - t.Errorf("neither a cancelled pipelinerun in repo status or a cancellation request in the controller log was found: status wait error: %s, log wait error: %s", err.Error(), logErr.Error()) + t.Errorf("neither a cancelled pipelinerun or a cancellation request in the controller log was found: status wait error: %s, log wait error: %s", err.Error(), logErr.Error()) } return } @@ -318,10 +310,10 @@ func TestGithubGHEPullRequestRetestPullRequestNumberSubstitution(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 2, PollTimeout: twait.DefaultTimeout, - TargetSHA: mergedSHA, + TargetSHA: []string{mergedSHA}, } - err = twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) + _, err = twait.UntilPipelineRunHasReason(ctx, g.Cnx.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) regex := regexp.MustCompile(fmt.Sprintf("I don't know my PR number is %d", g.PRNumber)) diff --git a/test/github_scope_token_to_list_of_private_public_repos_test.go b/test/github_scope_token_to_list_of_private_public_repos_test.go index b44a3721de..1ae5ec1336 100644 --- a/test/github_scope_token_to_list_of_private_public_repos_test.go +++ b/test/github_scope_token_to_list_of_private_public_repos_test.go @@ -21,6 +21,7 @@ import ( "github.com/openshift-pipelines/pipelines-as-code/test/pkg/payload" trepo "github.com/openshift-pipelines/pipelines-as-code/test/pkg/repository" twait "github.com/openshift-pipelines/pipelines-as-code/test/pkg/wait" + tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" "github.com/tektoncd/pipeline/pkg/names" "gotest.tools/v3/assert" corev1 "k8s.io/api/core/v1" @@ -170,9 +171,9 @@ func verifyGHTokenScope(t *testing.T, remoteTaskURL, remoteTaskName string, data Namespace: targetNS, MinNumberStatus: 0, PollTimeout: twait.DefaultTimeout, - TargetSHA: sha, + TargetSHA: []string{sha}, } - _, err = twait.UntilRepositoryUpdated(ctx, runcnx.Clients, waitOpts) + _, err = twait.UntilPipelineRunHasReason(ctx, runcnx.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) runcnx.Clients.Log.Infof("Check if we have the repository set as succeeded") diff --git a/test/github_skip_ci_test.go b/test/github_skip_ci_test.go index 21a0aa510a..3a79ae3295 100644 --- a/test/github_skip_ci_test.go +++ b/test/github_skip_ci_test.go @@ -135,9 +135,9 @@ func TestGithubGHESkipCITestCommand(t *testing.T) { Namespace: g.TargetNamespace, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: g.SHA, + TargetSHA: []string{g.SHA}, } - err = twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) + _, err = twait.UntilPipelineRunCreated(ctx, g.Cnx.Clients, waitOpts) assert.NilError(t, err) // Verify PipelineRun was created diff --git a/test/github_tag_gitops_test.go b/test/github_tag_gitops_test.go index 1a0df101b6..eca02d9aa7 100644 --- a/test/github_tag_gitops_test.go +++ b/test/github_tag_gitops_test.go @@ -116,10 +116,10 @@ func TestGithubGHEGitOpsCommentOnTag(t *testing.T) { Namespace: targetNS, MinNumberStatus: numberOfPRs, PollTimeout: twait.DefaultTimeout, - TargetSHA: sha, // this is the commit sha of the tag v1.0.0 + TargetSHA: []string{sha}, // this is the commit sha of the tag v1.0.0 } runcnx.Clients.Log.Info("Waiting for PipelineRun to be created") - err = twait.UntilPipelineRunCreated(ctx, runcnx.Clients, waitOpts) + _, err = twait.UntilPipelineRunCreated(ctx, runcnx.Clients, waitOpts) assert.NilError(t, err) } } diff --git a/test/github_tkn_pac_cli_test.go b/test/github_tkn_pac_cli_test.go index fbdca488bc..68ef0813ee 100644 --- a/test/github_tkn_pac_cli_test.go +++ b/test/github_tkn_pac_cli_test.go @@ -19,6 +19,7 @@ import ( "github.com/openshift-pipelines/pipelines-as-code/test/pkg/options" trepo "github.com/openshift-pipelines/pipelines-as-code/test/pkg/repository" twait "github.com/openshift-pipelines/pipelines-as-code/test/pkg/wait" + tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" "github.com/tektoncd/pipeline/pkg/names" "gotest.tools/v3/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -110,9 +111,9 @@ spec: Namespace: targetNS, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: sha, + TargetSHA: []string{sha}, } - _, err = twait.UntilRepositoryUpdated(ctx, runcnx.Clients, waitOpts) + _, err = twait.UntilPipelineRunHasReason(ctx, runcnx.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) runcnx.Clients.Log.Infof("Check if we have the repository set as succeeded") diff --git a/test/gitlab_merge_request_retest_pruned_test.go b/test/gitlab_merge_request_retest_pruned_test.go index 2c1ac5e407..ea59590b9a 100644 --- a/test/gitlab_merge_request_retest_pruned_test.go +++ b/test/gitlab_merge_request_retest_pruned_test.go @@ -16,6 +16,7 @@ import ( "github.com/openshift-pipelines/pipelines-as-code/test/pkg/payload" "github.com/openshift-pipelines/pipelines-as-code/test/pkg/scm" twait "github.com/openshift-pipelines/pipelines-as-code/test/pkg/wait" + tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" "github.com/tektoncd/pipeline/pkg/names" clientGitlab "gitlab.com/gitlab-org/api/client-go" "gotest.tools/v3/assert" @@ -57,18 +58,18 @@ func TestGitlabRetestAfterPipelineRunPruning(t *testing.T) { RepoName: topts.TargetNS, Namespace: topts.TargetNS, PollTimeout: twait.DefaultTimeout, - TargetSHA: formatting.CleanValueKubernetes(mr.SHA), + TargetSHA: []string{formatting.CleanValueKubernetes(mr.SHA)}, }, 2) assert.NilError(t, err) - // Wait for repository to have at least 2 status entries (both pipelines reported) - topts.ParamsRun.Clients.Log.Infof("Waiting for Repository status to have 2 entries") - _, err = twait.UntilRepositoryUpdated(ctx, topts.ParamsRun.Clients, twait.Opts{ + // Wait for both PipelineRuns to finish (1 success + 1 failure) + topts.ParamsRun.Clients.Log.Infof("Waiting for 2 PipelineRuns to finish") + _, err = twait.UntilPipelineRunsFinished(ctx, topts.ParamsRun.Clients, twait.Opts{ RepoName: topts.TargetNS, Namespace: topts.TargetNS, MinNumberStatus: 2, PollTimeout: twait.DefaultTimeout, - TargetSHA: mr.SHA, + TargetSHA: []string{mr.SHA}, }) assert.NilError(t, err) @@ -85,21 +86,29 @@ func TestGitlabRetestAfterPipelineRunPruning(t *testing.T) { initialPRNames[pr.Name] = true } - // Verify GitLab commit statuses: 1 success + 1 failure - commitStatuses, _, err := topts.GLProvider.Client().Commits.GetCommitStatuses(topts.ProjectID, mr.SHA, &clientGitlab.GetCommitStatusesOptions{}) - assert.NilError(t, err) - assert.Assert(t, len(commitStatuses) >= 2, "expected at least 2 commit statuses, got %d", len(commitStatuses)) - successCount := 0 failureCount := 0 - for _, cs := range commitStatuses { - switch cs.Status { - case "success": - successCount++ - case "failed": - failureCount++ + + // Verify GitLab commit statuses: 1 success + 1 failure + for i := 0; i < 5; i++ { + successCount = 0 + failureCount = 0 + commitStatuses, _, err := topts.GLProvider.Client().Commits.GetCommitStatuses(topts.ProjectID, mr.SHA, &clientGitlab.GetCommitStatusesOptions{}) + assert.NilError(t, err) + assert.Assert(t, len(commitStatuses) >= 2, "expected at least 2 commit statuses, got %d", len(commitStatuses)) + + for _, cs := range commitStatuses { + switch cs.Status { + case "success": + successCount++ + case "failed": + failureCount++ + } } + topts.ParamsRun.Clients.Log.Infof("waiting for commit statuses to be updated: %d success, %d failure", successCount, failureCount) + time.Sleep(1 * time.Second) } + assert.Assert(t, successCount >= 1, "expected at least 1 successful commit status") assert.Assert(t, failureCount >= 1, "expected at least 1 failed commit status") @@ -139,20 +148,17 @@ func TestGitlabRetestAfterPipelineRunPruning(t *testing.T) { RepoName: topts.TargetNS, Namespace: topts.TargetNS, PollTimeout: twait.DefaultTimeout, - TargetSHA: formatting.CleanValueKubernetes(mr.SHA), + TargetSHA: []string{formatting.CleanValueKubernetes(mr.SHA)}, }, 1) assert.NilError(t, err) - // Wait for repository status to be updated with the retest result - // We expect the re-run pipeline to fail (it's pipelinerun-exit-1), so disable - // the default FailOnRepoCondition=False check by setting it to a no-match value. - _, err = twait.UntilRepositoryUpdated(ctx, topts.ParamsRun.Clients, twait.Opts{ - RepoName: topts.TargetNS, - Namespace: topts.TargetNS, - MinNumberStatus: 3, - PollTimeout: twait.DefaultTimeout, - TargetSHA: mr.SHA, - FailOnRepoCondition: "no-match", + // Wait for the re-run pipeline to finish (it's pipelinerun-exit-1 so it will fail) + _, err = twait.UntilPipelineRunHasReason(ctx, topts.ParamsRun.Clients, tektonv1.PipelineRunReasonFailed, twait.Opts{ + RepoName: topts.TargetNS, + Namespace: topts.TargetNS, + MinNumberStatus: 1, + PollTimeout: twait.DefaultTimeout, + TargetSHA: []string{formatting.CleanValueKubernetes(mr.SHA)}, }) assert.NilError(t, err) @@ -276,24 +282,43 @@ func TestGitlabRetestAfterPipelineRunPruningFromFork(t *testing.T) { RepoName: topts.TargetNS, Namespace: topts.TargetNS, PollTimeout: twait.DefaultTimeout, - TargetSHA: formatting.CleanValueKubernetes(mr.SHA), + TargetSHA: []string{formatting.CleanValueKubernetes(mr.SHA)}, }, 2) assert.NilError(t, err) - topts.ParamsRun.Clients.Log.Infof("Waiting for Repository status to have 2 entries for fork MR") - _, err = twait.UntilRepositoryUpdated(ctx, topts.ParamsRun.Clients, twait.Opts{ + topts.ParamsRun.Clients.Log.Infof("Waiting for 2 PipelineRuns to finish for fork MR") + _, err = twait.UntilPipelineRunsFinished(ctx, topts.ParamsRun.Clients, twait.Opts{ RepoName: topts.TargetNS, Namespace: topts.TargetNS, MinNumberStatus: 2, PollTimeout: twait.DefaultTimeout, - TargetSHA: mr.SHA, + TargetSHA: []string{mr.SHA}, }) assert.NilError(t, err) topts.ParamsRun.Clients.Log.Infof("Verifying commit statuses on fork (source) project for fork MR") - sourceStatusCount, err := tgitlab.WaitForGitLabCommitStatusCount(ctx, topts.SecondGLProvider.Client(), topts.ParamsRun.Clients.Log, int(forkProject.ID), mr.SHA, "", 2) + sourceSuccessCount, err := tgitlab.WaitForGitLabCommitStatusCount( + ctx, + topts.SecondGLProvider.Client(), + topts.ParamsRun.Clients.Log, + int(forkProject.ID), + mr.SHA, + "success", + 1, + ) + assert.NilError(t, err) + assert.Assert(t, sourceSuccessCount >= 1, "expected at least 1 successful commit status on fork (source) project, got %d", sourceSuccessCount) + sourceFailureCount, err := tgitlab.WaitForGitLabCommitStatusCount( + ctx, + topts.SecondGLProvider.Client(), + topts.ParamsRun.Clients.Log, + int(forkProject.ID), + mr.SHA, + "failed", + 1, + ) assert.NilError(t, err) - assert.Assert(t, sourceStatusCount >= 2, "expected at least 2 commit statuses on fork (source) project, got %d", sourceStatusCount) + assert.Assert(t, sourceFailureCount >= 1, "expected at least 1 failed commit status on fork (source) project, got %d", sourceFailureCount) topts.ParamsRun.Clients.Log.Infof("Verifying no commit statuses on target project for fork MR") targetStatuses, _, err := topts.GLProvider.Client().Commits.GetCommitStatuses(topts.ProjectID, mr.SHA, &clientGitlab.GetCommitStatusesOptions{}) @@ -332,7 +357,7 @@ func TestGitlabRetestAfterPipelineRunPruningFromFork(t *testing.T) { topts.ParamsRun.Clients.Log.Infof("Warning: PipelineRuns not fully deleted after polling: %v (proceeding anyway)", pollErr) } - topts.ParamsRun.Clients.Log.Infof("Posting /retest comment on fork MR %d", topts.MRNumber) + topts.ParamsRun.Clients.Log.Infof("Posting /retest comment on fork MR %d", mr.IID) _, _, err = topts.GLProvider.Client().Notes.CreateMergeRequestNote(topts.ProjectID, mr.IID, &clientGitlab.CreateMergeRequestNoteOptions{Body: clientGitlab.Ptr("/retest")}) assert.NilError(t, err) @@ -342,18 +367,17 @@ func TestGitlabRetestAfterPipelineRunPruningFromFork(t *testing.T) { RepoName: topts.TargetNS, Namespace: topts.TargetNS, PollTimeout: twait.DefaultTimeout, - TargetSHA: formatting.CleanValueKubernetes(mr.SHA), + TargetSHA: []string{formatting.CleanValueKubernetes(mr.SHA)}, }, 1) assert.NilError(t, err) - topts.ParamsRun.Clients.Log.Infof("Waiting for Repository status to be updated with retest result for fork MR") - _, err = twait.UntilRepositoryUpdated(ctx, topts.ParamsRun.Clients, twait.Opts{ - RepoName: topts.TargetNS, - Namespace: topts.TargetNS, - MinNumberStatus: 3, - PollTimeout: twait.DefaultTimeout, - TargetSHA: mr.SHA, - FailOnRepoCondition: "no-match", + topts.ParamsRun.Clients.Log.Infof("Waiting for re-run PipelineRun to complete for fork MR") + _, err = twait.UntilPipelineRunsFinished(ctx, topts.ParamsRun.Clients, twait.Opts{ + RepoName: topts.TargetNS, + Namespace: topts.TargetNS, + MinNumberStatus: 1, + PollTimeout: twait.DefaultTimeout, + TargetSHA: []string{formatting.CleanValueKubernetes(mr.SHA)}, }) assert.NilError(t, err) diff --git a/test/gitlab_merge_request_test.go b/test/gitlab_merge_request_test.go index 7bdebdad7e..7f99f48106 100644 --- a/test/gitlab_merge_request_test.go +++ b/test/gitlab_merge_request_test.go @@ -100,7 +100,6 @@ func TestGitlabMergeRequest(t *testing.T) { OnEvent: opscomments.TestAllCommentEventType.String(), TargetNS: topts.TargetNS, NumberofPRMatch: 5, // this is the max we get in repos status - SHA: mr.SHA, } twait.Succeeded(ctx, t, topts.ParamsRun, topts.Opts, sopt) } @@ -133,12 +132,12 @@ func TestGitlabOnLabel(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: mr.SHA, + TargetSHA: []string{mr.SHA}, } - repo, err := twait.UntilRepositoryUpdated(ctx, topts.ParamsRun.Clients, waitOpts) + prs, err := twait.UntilPipelineRunHasReason(ctx, topts.ParamsRun.Clients, v1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) - assert.Assert(t, len(repo.Status) > 0) - assert.Equal(t, *repo.Status[0].EventType, triggertype.PullRequestLabeled.String()) + assert.Assert(t, len(prs) > 0) + assert.Equal(t, prs[0].Annotations[keys.EventType], triggertype.PullRequestLabeled.String()) } func TestGitlabOnComment(t *testing.T) { @@ -175,15 +174,17 @@ func TestGitlabOnComment(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: mr.SHA, + TargetSHA: []string{mr.SHA}, } - repo, err := twait.UntilRepositoryUpdated(ctx, topts.ParamsRun.Clients, waitOpts) + prs, err := twait.UntilPipelineRunHasReason(ctx, topts.ParamsRun.Clients, v1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) - topts.ParamsRun.Clients.Log.Infof("Check if we have the repository set as succeeded") - assert.Assert(t, repo.Status[len(repo.Status)-1].Conditions[0].Status == corev1.ConditionTrue) - lastPrName := repo.Status[len(repo.Status)-1].PipelineRunName + topts.ParamsRun.Clients.Log.Infof("Check if we have the pipelinerun set as succeeded") + lastPR := prs[len(prs)-1] + cond := lastPR.Status.GetCondition(apis.ConditionSucceeded) + assert.Assert(t, cond != nil) + assert.Equal(t, corev1.ConditionTrue, cond.Status) - err = twait.RegexpMatchingInPodLog(context.Background(), topts.ParamsRun, topts.TargetNS, fmt.Sprintf("tekton.dev/pipelineRun=%s", lastPrName), "step-task", *regexp.MustCompile(triggerComment), "", 2, nil) + err = twait.RegexpMatchingInPodLog(context.Background(), topts.ParamsRun, topts.TargetNS, fmt.Sprintf("tekton.dev/pipelineRun=%s", lastPR.Name), "step-task", *regexp.MustCompile(triggerComment), "", 2, nil) assert.NilError(t, err) } @@ -203,9 +204,9 @@ func TestGitlabCancelInProgressOnChange(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: topts.SHA, + TargetSHA: []string{topts.SHA}, } - err := twait.UntilPipelineRunCreated(ctx, topts.ParamsRun.Clients, originalPipelineWaitOpts) + _, err := twait.UntilPipelineRunCreated(ctx, topts.ParamsRun.Clients, originalPipelineWaitOpts) assert.NilError(t, err) newEntries := map[string]string{ @@ -229,13 +230,13 @@ func TestGitlabCancelInProgressOnChange(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: newSha, + TargetSHA: []string{newSha}, } - err = twait.UntilPipelineRunCreated(ctx, topts.ParamsRun.Clients, newPipelineWaitOpts) + _, err = twait.UntilPipelineRunCreated(ctx, topts.ParamsRun.Clients, newPipelineWaitOpts) assert.NilError(t, err) topts.ParamsRun.Clients.Log.Infof("Waiting for old pipelinerun to be cancelled") - cancelledErr := twait.UntilPipelineRunHasReason(ctx, topts.ParamsRun.Clients, v1.PipelineRunReasonCancelled, originalPipelineWaitOpts) + _, cancelledErr := twait.UntilPipelineRunHasReason(ctx, topts.ParamsRun.Clients, v1.PipelineRunReasonCancelled, originalPipelineWaitOpts) assert.NilError(t, cancelledErr) } @@ -255,30 +256,22 @@ func TestGitlabCancelInProgressOnPRClose(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: topts.SHA, + TargetSHA: []string{topts.SHA}, } - err := twait.UntilPipelineRunCreated(ctx, topts.ParamsRun.Clients, waitOpts) + _, err := twait.UntilPipelineRunCreated(ctx, topts.ParamsRun.Clients, waitOpts) assert.NilError(t, err) _, _, err = topts.GLProvider.Client().MergeRequests.UpdateMergeRequest(topts.ProjectID, int64(topts.MRNumber), &clientGitlab.UpdateMergeRequestOptions{ StateEvent: clientGitlab.Ptr("close"), }) assert.NilError(t, err) - err = twait.UntilPipelineRunHasReason(ctx, topts.ParamsRun.Clients, v1.PipelineRunReasonCancelled, waitOpts) + _, err = twait.UntilPipelineRunHasReason(ctx, topts.ParamsRun.Clients, v1.PipelineRunReasonCancelled, waitOpts) assert.NilError(t, err) prs, err := topts.ParamsRun.Clients.Tekton.TektonV1().PipelineRuns(topts.TargetNS).List(context.Background(), metav1.ListOptions{}) assert.NilError(t, err) assert.Equal(t, len(prs.Items), 1, "should have only one pipelinerun, but we have: %d", len(prs.Items)) assert.Equal(t, prs.Items[0].GetStatusCondition().GetCondition(apis.ConditionSucceeded).GetReason(), "Cancelled", "should have been cancelled") - - // failing on `true` condition because for cancelled PipelineRun we want `false` condition. - waitOpts.FailOnRepoCondition = corev1.ConditionTrue - repo, err := twait.UntilRepositoryUpdated(ctx, topts.ParamsRun.Clients, waitOpts) - assert.NilError(t, err) - - laststatus := repo.Status[len(repo.Status)-1] - assert.Equal(t, "Cancelled", laststatus.Conditions[0].Reason) } func TestGitlabIssueGitopsComment(t *testing.T) { @@ -596,21 +589,34 @@ func TestGitlabConsistentCommitStatusOnMR(t *testing.T) { assert.NilError(t, err) assert.Assert(t, len(prsNew.Items) == 1) - commitStatuses, _, err := topts.GLProvider.Client().Commits.GetCommitStatuses(topts.ProjectID, mr.SHA, &clientGitlab.GetCommitStatusesOptions{}) - assert.NilError(t, err) - assert.Assert(t, len(commitStatuses) == 2) - - for _, cs := range commitStatuses { - switch cs.Name { - case "Pipelines as Code CI / bad-converts-good-pipelinerun": - assert.Assert(t, cs.Status == "failed") - case "Pipelines as Code CI / always-good-pipelinerun": - assert.Assert(t, cs.Status == "success") - default: - t.Fatalf("unexpected commit status name: %s", cs.Name) + gotSuccess := false + gotFailure := false + for i := 0; i < 5; i++ { + commitStatuses, _, err := topts.GLProvider.Client().Commits.GetCommitStatuses(topts.ProjectID, mr.SHA, &clientGitlab.GetCommitStatusesOptions{}) + assert.NilError(t, err) + assert.Assert(t, len(commitStatuses) == 2) + + for _, cs := range commitStatuses { + switch cs.Name { + case "Pipelines as Code CI / bad-converts-good-pipelinerun": + gotFailure = cs.Status == "failed" + case "Pipelines as Code CI / always-good-pipelinerun": + gotSuccess = cs.Status == "success" + default: + t.Fatalf("unexpected commit status name: %s", cs.Name) + } } + t.Logf("Waiting for commit statuses to be updated") + if gotSuccess && gotFailure { + break + } + + time.Sleep(1 * time.Second) } + assert.Assert(t, gotFailure, "Commit status for bad-converts-good-pipelinerun should be failure") + assert.Assert(t, gotSuccess, "Commit status for always-good-pipelinerun should be success") + entries, err := payload.GetEntries(map[string]string{ ".tekton/bad-pipelinerun.yaml": "testdata/bad-converts-good-pipelinerun.yaml", ".tekton/always-good-pipelinerun.yaml": "testdata/always-good-pipelinerun.yaml", @@ -647,18 +653,32 @@ func TestGitlabConsistentCommitStatusOnMR(t *testing.T) { assert.NilError(t, err) assert.Assert(t, len(prsNew.Items) == 2) - commitStatuses, _, err = topts.GLProvider.Client().Commits.GetCommitStatuses(topts.ProjectID, newSHA, &clientGitlab.GetCommitStatusesOptions{}) - assert.NilError(t, err) - assert.Assert(t, len(commitStatuses) == 2) - - for _, cs := range commitStatuses { - switch cs.Name { - case "Pipelines as Code CI / bad-converts-good-pipelinerun", "Pipelines as Code CI / always-good-pipelinerun": - assert.Assert(t, cs.Status == "success") - default: - t.Fatalf("unexpected commit status name: %s", cs.Name) + gotSuccess1 := false + gotSuccess2 := false + for i := 0; i < 5; i++ { + commitStatuses, _, err := topts.GLProvider.Client().Commits.GetCommitStatuses(topts.ProjectID, newSHA, &clientGitlab.GetCommitStatusesOptions{}) + assert.NilError(t, err) + assert.Assert(t, len(commitStatuses) == 2) + + for _, cs := range commitStatuses { + switch cs.Name { + case "Pipelines as Code CI / bad-converts-good-pipelinerun": + gotSuccess1 = cs.Status == "success" + case "Pipelines as Code CI / always-good-pipelinerun": + gotSuccess2 = cs.Status == "success" + default: + t.Fatalf("unexpected commit status name: %s", cs.Name) + } + } + if gotSuccess1 && gotSuccess2 { + break } + + time.Sleep(1 * time.Second) } + + assert.Assert(t, gotSuccess1, "Commit status for bad-converts-good-pipelinerun should be success") + assert.Assert(t, gotSuccess2, "Commit status for always-good-pipelinerun should be success") } // TestGitlabMergeRequestCelPrefix tests the cel: prefix for arbitrary CEL expressions. @@ -744,9 +764,9 @@ func TestGitlabMergeRequestVariableSubs(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: 2, PollTimeout: twait.DefaultTimeout, - TargetSHA: sha, + TargetSHA: []string{sha}, } - err = twait.UntilPipelineRunHasReason(ctx, topts.ParamsRun.Clients, v1.PipelineRunReasonSuccessful, waitOpts) + _, err = twait.UntilPipelineRunHasReason(ctx, topts.ParamsRun.Clients, v1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) // Get the PipelineRun @@ -850,14 +870,25 @@ func TestGitlabMergeRequestCommentStrategyUpdateCELErrorReplacement(t *testing.T twait.Succeeded(ctx, t, topts.ParamsRun, topts.Opts, sopt) // Verify commit status is success - commitStatuses, _, err := topts.GLProvider.Client().Commits.GetCommitStatuses(topts.ProjectID, sha, &clientGitlab.GetCommitStatusesOptions{}) - assert.NilError(t, err) - assert.Assert(t, len(commitStatuses) > 0, "Expected at least one commit status") - for _, cs := range commitStatuses { - assert.Equal(t, "success", cs.Status, - "Commit status %s should be success, got %s", cs.Name, cs.Status) + foundSuccess := false + for i := 0; i < 5; i++ { + commitStatuses, _, err := topts.GLProvider.Client().Commits.GetCommitStatuses(topts.ProjectID, sha, &clientGitlab.GetCommitStatusesOptions{}) + assert.NilError(t, err) + assert.Assert(t, len(commitStatuses) > 0, "Expected at least one commit status") + for _, cs := range commitStatuses { + if cs.Status == "success" { + foundSuccess = true + break + } + } + if foundSuccess { + break + } + time.Sleep(1 * time.Second) } + assert.Assert(t, foundSuccess, "Commit status success not found") + // Verify the same comment was updated (not recreated) notes, _, err := topts.GLProvider.Client().Notes.ListMergeRequestNotes(topts.ProjectID, int64(topts.MRNumber), nil) assert.NilError(t, err) diff --git a/test/gitlab_oktotest_thread_reply_test.go b/test/gitlab_oktotest_thread_reply_test.go index 643b09a0e2..89eee277c8 100644 --- a/test/gitlab_oktotest_thread_reply_test.go +++ b/test/gitlab_oktotest_thread_reply_test.go @@ -8,6 +8,7 @@ import ( "github.com/openshift-pipelines/pipelines-as-code/pkg/params/triggertype" tgitlab "github.com/openshift-pipelines/pipelines-as-code/test/pkg/gitlab" twait "github.com/openshift-pipelines/pipelines-as-code/test/pkg/wait" + tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" clientGitlab "gitlab.com/gitlab-org/api/client-go" "gotest.tools/v3/assert" ) @@ -36,9 +37,8 @@ func TestGitlabOpsCommentInThreadReply(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: 1, PollTimeout: twait.DefaultTimeout, - TargetSHA: "", } - _, err = twait.UntilRepositoryUpdated(ctx, topts.ParamsRun.Clients, waitOpts) + _, err = twait.UntilPipelineRunHasReason(ctx, topts.ParamsRun.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) topts.ParamsRun.Clients.Log.Info("Updating discussion with /test comment in a reply thread") @@ -48,7 +48,7 @@ func TestGitlabOpsCommentInThreadReply(t *testing.T) { }) assert.NilError(t, err) waitOpts.MinNumberStatus = 2 - _, err = twait.UntilRepositoryUpdated(ctx, topts.ParamsRun.Clients, waitOpts) + _, err = twait.UntilPipelineRunHasReason(ctx, topts.ParamsRun.Clients, tektonv1.PipelineRunReasonSuccessful, waitOpts) assert.NilError(t, err) topts.ParamsRun.Clients.Log.Info("Repository status updated after /test comment") diff --git a/test/gitlab_push_gitops_command_test.go b/test/gitlab_push_gitops_command_test.go index 6607770e33..743bd79c82 100644 --- a/test/gitlab_push_gitops_command_test.go +++ b/test/gitlab_push_gitops_command_test.go @@ -49,10 +49,10 @@ func TestGitlabGitOpsCommandTestOnPush(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: 1, PollTimeout: wait.DefaultTimeout, - TargetSHA: branch.Commit.ID, + TargetSHA: []string{branch.Commit.ID}, } - err = wait.UntilPipelineRunCreated(ctx, topts.ParamsRun.Clients, waitOpts) + _, err = wait.UntilPipelineRunCreated(ctx, topts.ParamsRun.Clients, waitOpts) assert.NilError(t, err) commentOpts := &gitlab.PostCommitCommentOptions{ @@ -114,10 +114,10 @@ func TestGitlabGitOpsCommandCancelOnPush(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: numberOfStatus, PollTimeout: wait.DefaultTimeout, - TargetSHA: branch.Commit.ID, + TargetSHA: []string{branch.Commit.ID}, } - err = wait.UntilPipelineRunCreated(ctx, topts.ParamsRun.Clients, waitOpts) + _, err = wait.UntilPipelineRunCreated(ctx, topts.ParamsRun.Clients, waitOpts) assert.NilError(t, err) prsNew, err := topts.ParamsRun.Clients.Tekton.TektonV1().PipelineRuns(topts.TargetNS).List(ctx, metav1.ListOptions{}) @@ -131,7 +131,7 @@ func TestGitlabGitOpsCommandCancelOnPush(t *testing.T) { assert.NilError(t, err) topts.ParamsRun.Clients.Log.Infof("Commit comment %s has been created", cc.Note) - err = wait.UntilPipelineRunHasReason(ctx, topts.ParamsRun.Clients, v1.PipelineRunReasonCancelled, waitOpts) + _, err = wait.UntilPipelineRunHasReason(ctx, topts.ParamsRun.Clients, v1.PipelineRunReasonCancelled, waitOpts) assert.NilError(t, err) } @@ -185,10 +185,10 @@ func TestGitlabGitOpsCommandTestOnTag(t *testing.T) { Namespace: topts.TargetNS, MinNumberStatus: numberOfPRs, PollTimeout: wait.DefaultTimeout, - TargetSHA: sha, + TargetSHA: []string{sha}, } - err = wait.UntilPipelineRunCreated(ctx, topts.ParamsRun.Clients, waitOpts) + _, err = wait.UntilPipelineRunCreated(ctx, topts.ParamsRun.Clients, waitOpts) assert.NilError(t, err) prsNew, err := topts.ParamsRun.Clients.Tekton.TektonV1().PipelineRuns(topts.TargetNS).List(ctx, metav1.ListOptions{}) diff --git a/test/pkg/wait/check.go b/test/pkg/wait/check.go index fd0c86611c..ab5d6a36ac 100644 --- a/test/pkg/wait/check.go +++ b/test/pkg/wait/check.go @@ -10,9 +10,10 @@ import ( "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/keys" "github.com/openshift-pipelines/pipelines-as-code/pkg/params" "github.com/openshift-pipelines/pipelines-as-code/test/pkg/options" + tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" "gotest.tools/v3/assert" corev1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/apis" ) var DefaultTimeout = 10 * time.Minute @@ -28,66 +29,67 @@ type SuccessOpt struct { } func Succeeded(ctx context.Context, t *testing.T, runcnx *params.Run, opts options.E2E, sopt SuccessOpt) { - runcnx.Clients.Log.Infof("Waiting for Repository to be updated") + t.Helper() + runcnx.Clients.Log.Infof("Waiting for PipelineRuns to succeed") minNumberStatus := sopt.MinNumberStatus if minNumberStatus == 0 { minNumberStatus = sopt.NumberofPRMatch } + var targetSHA []string + if sopt.SHA != "" { + targetSHA = []string{sopt.SHA} + } waitOpts := Opts{ RepoName: sopt.TargetNS, Namespace: sopt.TargetNS, MinNumberStatus: minNumberStatus, PollTimeout: DefaultTimeout, - TargetSHA: sopt.SHA, + TargetSHA: targetSHA, } - _, err := UntilRepositoryUpdated(ctx, runcnx.Clients, waitOpts) + prs, err := UntilPipelineRunsFinished(ctx, runcnx.Clients, waitOpts) assert.NilError(t, err) - runcnx.Clients.Log.Infof("Check if we have the repository set as succeeded") - repo, err := runcnx.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(sopt.TargetNS).Get(ctx, sopt.TargetNS, v1.GetOptions{}) - assert.NilError(t, err) + assert.Assert(t, len(prs) > 0, "no successful pipelineruns found") - assert.Assert(t, len(repo.Status) > 0, "repository status is empty") - laststatus := repo.Status[len(repo.Status)-1] + var pr tektonv1.PipelineRun if sopt.SHA != "" { found := false - for i := len(repo.Status) - 1; i >= 0; i-- { - if repo.Status[i].SHA != nil && *repo.Status[i].SHA == sopt.SHA { - laststatus = repo.Status[i] + for i := len(prs) - 1; i >= 0; i-- { + if prs[i].Annotations[keys.SHA] == sopt.SHA { + pr = prs[i] found = true break } } if !found { - availableSHAs := make([]string, 0, len(repo.Status)) - for _, st := range repo.Status { - if st.SHA != nil { - availableSHAs = append(availableSHAs, *st.SHA) - } else { - availableSHAs = append(availableSHAs, "") - } + availableSHAs := make([]string, 0, len(prs)) + for _, p := range prs { + availableSHAs = append(availableSHAs, p.Annotations[keys.SHA]) } - assert.Assert(t, false, "no matching status found for SHA %s; available SHAs: %v", sopt.SHA, availableSHAs) + assert.Assert(t, false, "no matching pipelinerun found for SHA %s; available SHAs: %v", sopt.SHA, availableSHAs) } + } else { + pr = prs[len(prs)-1] } - assert.Equal(t, corev1.ConditionTrue, laststatus.Conditions[0].Status) + + runcnx.Clients.Log.Infof("Check if we have the pipelinerun set as succeeded") + cond := pr.Status.GetCondition(apis.ConditionSucceeded) + assert.Assert(t, cond != nil) + assert.Equal(t, corev1.ConditionTrue, cond.Status) if sopt.SHA != "" { - assert.Equal(t, sopt.SHA, *laststatus.SHA) - assert.Equal(t, sopt.SHA, filepath.Base(*laststatus.SHAURL)) + assert.Equal(t, sopt.SHA, pr.Annotations[keys.SHA]) + assert.Equal(t, sopt.SHA, filepath.Base(pr.Annotations[keys.ShaURL])) } - laststatustitle := strings.TrimSpace(*laststatus.Title) + shaTitle := strings.TrimSpace(pr.Annotations[keys.ShaTitle]) if sopt.Title != "" { - assert.Equal(t, sopt.Title, laststatustitle) + assert.Equal(t, sopt.Title, shaTitle) } else { - assert.Assert(t, *laststatus.Title != "") + assert.Assert(t, pr.Annotations[keys.ShaTitle] != "") } - assert.Assert(t, *laststatus.LogURL != "") - - pr, err := runcnx.Clients.Tekton.TektonV1().PipelineRuns(sopt.TargetNS).Get(ctx, laststatus.PipelineRunName, v1.GetOptions{}) - assert.NilError(t, err) + assert.Assert(t, pr.Annotations[keys.LogURL] != "") assert.Equal(t, sopt.OnEvent, pr.Annotations[keys.EventType]) - assert.Equal(t, repo.GetName(), pr.Annotations[keys.Repository]) + assert.Equal(t, sopt.TargetNS, pr.Annotations[keys.Repository]) if opts.Organization != "" { assert.Equal(t, opts.Organization, pr.Annotations[keys.URLOrg]) @@ -95,10 +97,6 @@ func Succeeded(ctx context.Context, t *testing.T, runcnx *params.Run, opts optio if opts.Repo != "" { assert.Equal(t, opts.Repo, pr.Annotations[keys.URLRepository]) } - if sopt.SHA != "" { - assert.Equal(t, sopt.SHA, pr.Annotations[keys.SHA]) - assert.Equal(t, sopt.SHA, filepath.Base(pr.Annotations[keys.ShaURL])) - } - assert.Equal(t, laststatustitle, strings.TrimSpace(pr.Annotations[keys.ShaTitle])) - runcnx.Clients.Log.Infof("Success, number of status %d has been matched", sopt.NumberofPRMatch) + assert.Equal(t, shaTitle, strings.TrimSpace(pr.Annotations[keys.ShaTitle])) + runcnx.Clients.Log.Infof("Success, number of pipelineruns %d has been matched", sopt.NumberofPRMatch) } diff --git a/test/pkg/wait/wait.go b/test/pkg/wait/wait.go index 83be66e33e..a7ce79cf02 100644 --- a/test/pkg/wait/wait.go +++ b/test/pkg/wait/wait.go @@ -3,26 +3,69 @@ package wait import ( "context" "fmt" + "sort" + "strings" "time" "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/keys" - pacv1alpha1 "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1" "github.com/openshift-pipelines/pipelines-as-code/pkg/kubeinteraction" "github.com/openshift-pipelines/pipelines-as-code/pkg/params/clients" v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/apis" ) +// sortPipelineRunsByCompletion sorts the pipeline runs by completion time, then by creation time. +// Note that it converts time to milliseconds to avoid precision issues. +func sortPipelineRunsByCompletionMillis(prs []v1.PipelineRun) { + sort.Slice(prs, func(i, j int) bool { + ci := time.UnixMilli(prs[i].Status.CompletionTime.UnixMilli()) + cj := time.UnixMilli(prs[j].Status.CompletionTime.UnixMilli()) + if ci.IsZero() && cj.IsZero() { + ci = time.UnixMilli(prs[i].Status.StartTime.UnixMilli()) + cj = time.UnixMilli(prs[j].Status.StartTime.UnixMilli()) + return ci.Before(cj) + } + if ci.IsZero() { + return false + } + if cj.IsZero() { + return true + } + return ci.Before(cj) + }) +} + +// sortPipelineRunsByCreationMillis sorts the pipeline runs by creation time. +// Note that it converts time to milliseconds to avoid precision issues. +func sortPipelineRunsByCreationMillis(prs []v1.PipelineRun) { + sort.Slice(prs, func(i, j int) bool { + ci := time.UnixMilli(prs[i].CreationTimestamp.UnixMilli()) + cj := time.UnixMilli(prs[j].CreationTimestamp.UnixMilli()) + return ci.Before(cj) + }) +} + type Opts struct { - RepoName string - Namespace string - MinNumberStatus int - PollTimeout time.Duration - AdminNS string - TargetSHA string - FailOnRepoCondition corev1.ConditionStatus + RepoName string + Namespace string + MinNumberStatus int + PollTimeout time.Duration + AdminNS string + TargetSHA []string +} + +func shaLabelSelector(shas []string) string { + switch len(shas) { + case 0: + return "" + case 1: + return fmt.Sprintf("%s=%s", keys.SHA, shas[0]) + default: + return fmt.Sprintf("%s in (%s)", keys.SHA, strings.Join(shas, ",")) + } } func UntilMinPRAppeared(ctx context.Context, clients clients.Clients, opts Opts, minNumber int) error { @@ -30,8 +73,8 @@ func UntilMinPRAppeared(ctx context.Context, clients clients.Clients, opts Opts, defer cancel() return kubeinteraction.PollImmediateWithContext(ctx, opts.PollTimeout, func() (bool, error) { listOpts := metav1.ListOptions{} - if opts.TargetSHA != "" { - listOpts.LabelSelector = fmt.Sprintf("%s=%s", keys.SHA, opts.TargetSHA) + if sel := shaLabelSelector(opts.TargetSHA); sel != "" { + listOpts.LabelSelector = sel } prs, err := clients.Tekton.TektonV1().PipelineRuns(opts.Namespace).List(ctx, listOpts) if err != nil { @@ -44,110 +87,76 @@ func UntilMinPRAppeared(ctx context.Context, clients clients.Clients, opts Opts, }) } -func UntilRepositoryUpdated(ctx context.Context, clients clients.Clients, opts Opts) (*pacv1alpha1.Repository, error) { +func UntilPipelineRunCreated(ctx context.Context, clients clients.Clients, opts Opts) ([]v1.PipelineRun, error) { ctx, cancel := context.WithTimeout(ctx, opts.PollTimeout) defer cancel() - var repo *pacv1alpha1.Repository - return repo, kubeinteraction.PollImmediateWithContext(ctx, opts.PollTimeout, func() (bool, error) { - clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(opts.Namespace) - var err error - if repo, err = clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(opts.Namespace).Get(ctx, opts.RepoName, metav1.GetOptions{}); err != nil { - return true, err + var matched []v1.PipelineRun + return matched, kubeinteraction.PollImmediateWithContext(ctx, opts.PollTimeout, func() (bool, error) { + listOpts := metav1.ListOptions{} + if sel := shaLabelSelector(opts.TargetSHA); sel != "" { + listOpts.LabelSelector = sel } - - prs, err := clients.Tekton.TektonV1().PipelineRuns(opts.Namespace).List(ctx, metav1.ListOptions{ - LabelSelector: fmt.Sprintf("%s=%s", keys.SHA, opts.TargetSHA), - }) + prs, err := clients.Tekton.TektonV1().PipelineRuns(opts.Namespace).List(ctx, listOpts) if err != nil { return true, err } - if len(prs.Items) > 0 { - prConditions := prs.Items[0].Status.Conditions - if opts.FailOnRepoCondition == "" { - opts.FailOnRepoCondition = corev1.ConditionFalse - } - - if len(prConditions) != 0 && prConditions[0].Status == opts.FailOnRepoCondition { - return true, fmt.Errorf("pipelinerun has failed") - } - } - clients.Log.Infof("Still waiting for repository status to be updated: %d/%d", len(repo.Status), opts.MinNumberStatus) - time.Sleep(2 * time.Second) - if opts.TargetSHA != "" { - matchingStatuses := 0 - for _, s := range repo.Status { - if s.SHA != nil && *s.SHA == opts.TargetSHA { - matchingStatuses++ - } - } - return matchingStatuses > 0 && len(repo.Status) >= opts.MinNumberStatus, nil + clients.Log.Infof("waiting for pipelinerun to be created: selector sha=%v, MinNumberStatus=%d pr.Items=%d", opts.TargetSHA, opts.MinNumberStatus, len(prs.Items)) + if len(prs.Items) == opts.MinNumberStatus { + matched = prs.Items + sortPipelineRunsByCreationMillis(matched) + return true, nil } - return len(repo.Status) >= opts.MinNumberStatus, nil + return false, nil }) } -func UntilRepositoryHasStatusReason(ctx context.Context, clients clients.Clients, opts Opts, reason string) (*pacv1alpha1.Repository, error) { +// UntilPipelineRunsFinished waits until at least MinNumberStatus PipelineRuns +// have reached a terminal state (Succeeded, Failed, or Cancelled). +// Results are sorted by completion time descending (newest first, oldest last). +func UntilPipelineRunsFinished(ctx context.Context, clients clients.Clients, opts Opts) ([]v1.PipelineRun, error) { ctx, cancel := context.WithTimeout(ctx, opts.PollTimeout) defer cancel() - var repo *pacv1alpha1.Repository - return repo, kubeinteraction.PollImmediateWithContext(ctx, opts.PollTimeout, func() (bool, error) { - var err error - if repo, err = clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(opts.Namespace).Get(ctx, opts.RepoName, metav1.GetOptions{}); err != nil { + var matched []v1.PipelineRun + return matched, kubeinteraction.PollImmediateWithContext(ctx, opts.PollTimeout, func() (bool, error) { + listOpts := metav1.ListOptions{} + if sel := shaLabelSelector(opts.TargetSHA); sel != "" { + listOpts.LabelSelector = sel + } + prs, err := clients.Tekton.TektonV1().PipelineRuns(opts.Namespace).List(ctx, listOpts) + if err != nil { return true, err } - matchingStatuses := 0 - reasons := []string{} - for _, status := range repo.Status { - if opts.TargetSHA != "" { - if status.SHA == nil || *status.SHA != opts.TargetSHA { - continue - } - } - matchingStatuses++ - if len(status.Conditions) == 0 { - continue - } - reasons = append(reasons, status.Conditions[0].Reason) - if status.Conditions[0].Reason == reason { - return true, nil + var finished []v1.PipelineRun + for _, pr := range prs.Items { + if cond := pr.Status.GetCondition(apis.ConditionSucceeded); cond != nil && cond.Status != corev1.ConditionUnknown { + finished = append(finished, pr) } } - clients.Log.Infof( - "Still waiting for repository status reason to be updated: wanted=%q matching statuses=%d reasons=%v", - reason, matchingStatuses, reasons, - ) - return false, nil - }) -} - -func UntilPipelineRunCreated(ctx context.Context, clients clients.Clients, opts Opts) error { - ctx, cancel := context.WithTimeout(ctx, opts.PollTimeout) - defer cancel() - return kubeinteraction.PollImmediateWithContext(ctx, opts.PollTimeout, func() (bool, error) { - clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(opts.Namespace) - prs, err := clients.Tekton.TektonV1().PipelineRuns(opts.Namespace).List(ctx, metav1.ListOptions{ - LabelSelector: fmt.Sprintf("%s=%s", keys.SHA, opts.TargetSHA), - }) - if err != nil { - return true, err + clients.Log.Infof("still waiting for %d pipelinerun(s) to finish in %s namespace (finished=%d, total=%d)", + opts.MinNumberStatus, opts.Namespace, len(finished), len(prs.Items)) + if len(finished) >= opts.MinNumberStatus { + sortPipelineRunsByCompletionMillis(finished) + matched = finished + return true, nil } - - clients.Log.Infof("waiting for pipelinerun to be created: selector %s=%s, MinNumberStatus=%d pr.Items=%d", keys.SHA, opts.TargetSHA, opts.MinNumberStatus, len(prs.Items)) - return len(prs.Items) == opts.MinNumberStatus, nil + return false, nil }) } // UntilPipelineRunHasReason Checks for certain reason of PipelineRuns. -func UntilPipelineRunHasReason(ctx context.Context, clients clients.Clients, desiredReason v1.PipelineRunReason, opts Opts) error { +func UntilPipelineRunHasReason(ctx context.Context, clients clients.Clients, desiredReason v1.PipelineRunReason, opts Opts) ([]v1.PipelineRun, error) { ctx, cancel := context.WithTimeout(ctx, opts.PollTimeout) defer cancel() - return kubeinteraction.PollImmediateWithContext(ctx, opts.PollTimeout, func() (bool, error) { - prs, err := clients.Tekton.TektonV1().PipelineRuns(opts.Namespace).List(ctx, metav1.ListOptions{ - LabelSelector: fmt.Sprintf("%s=%s", keys.SHA, opts.TargetSHA), - }) + var matched []v1.PipelineRun + return matched, kubeinteraction.PollImmediateWithContext(ctx, opts.PollTimeout, func() (bool, error) { + listOpts := metav1.ListOptions{} + if sel := shaLabelSelector(opts.TargetSHA); sel != "" { + listOpts.LabelSelector = sel + } + prs, err := clients.Tekton.TektonV1().PipelineRuns(opts.Namespace).List(ctx, listOpts) if err != nil { return true, err } @@ -160,6 +169,11 @@ func UntilPipelineRunHasReason(ctx context.Context, clients clients.Clients, des } clients.Log.Infof("still waiting for %d pipelinerun(s) to have reason %s in %s namespace", opts.MinNumberStatus, desiredReason.String(), opts.Namespace) - return len(prsWithReason) >= opts.MinNumberStatus, nil + if len(prsWithReason) >= opts.MinNumberStatus { + matched = prsWithReason + sortPipelineRunsByCreationMillis(matched) + return true, nil + } + return false, nil }) } diff --git a/test/pkg/wait/wait_test.go b/test/pkg/wait/wait_test.go index f2d7b5ffeb..b7ed0b8857 100644 --- a/test/pkg/wait/wait_test.go +++ b/test/pkg/wait/wait_test.go @@ -1,12 +1,14 @@ package wait import ( + "context" "testing" "time" - pacv1alpha1 "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1" + "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/keys" paramsclients "github.com/openshift-pipelines/pipelines-as-code/pkg/params/clients" testclient "github.com/openshift-pipelines/pipelines-as-code/pkg/test/clients" + pipelinev1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" "go.uber.org/zap" "gotest.tools/v3/assert" corev1 "k8s.io/api/core/v1" @@ -16,72 +18,255 @@ import ( rtesting "knative.dev/pkg/reconciler/testing" ) -func makeRepositoryRunStatus(sha *string, reason string) pacv1alpha1.RepositoryRunStatus { - status := pacv1alpha1.RepositoryRunStatus{ - SHA: sha, +func makePipelineRun(name, sha, reason string) *pipelinev1.PipelineRun { + pr := &pipelinev1.PipelineRun{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: "test-ns", + Labels: map[string]string{ + keys.SHA: sha, + }, + }, + } + if reason != "" { + pr.Status.Status = duckv1.Status{ + Conditions: []knativeapis.Condition{ + { + Type: knativeapis.ConditionSucceeded, + Reason: reason, + }, + }, + } + } + return pr +} + +func makePipelineRunWithStatus(name, sha, reason string, condStatus corev1.ConditionStatus, created, completed time.Time) *pipelinev1.PipelineRun { + pr := makePipelineRun(name, sha, reason) + pr.CreationTimestamp = metav1.NewTime(created) + if !completed.IsZero() { + pr.Status.CompletionTime = &metav1.Time{Time: completed} } if reason != "" { - status.Status = duckv1.Status{ + pr.Status.Status = duckv1.Status{ Conditions: []knativeapis.Condition{ - {Reason: reason}, + { + Type: knativeapis.ConditionSucceeded, + Status: condStatus, + Reason: reason, + }, }, } } - return status + return pr +} + +func seedAndMakeClients(ctx context.Context, t *testing.T, prs []*pipelinev1.PipelineRun) paramsclients.Clients { + t.Helper() + seeded, _ := testclient.SeedTestData(t, ctx, testclient.Data{ + Namespaces: []*corev1.Namespace{ + {ObjectMeta: metav1.ObjectMeta{Name: "test-ns"}}, + }, + PipelineRuns: prs, + }) + return paramsclients.Clients{ + Tekton: seeded.Pipeline, + Log: zap.NewNop().Sugar(), + } +} + +type waitTestCase struct { + name string + pipelineRuns []*pipelinev1.PipelineRun + targetSHA []string + minStatus int + wantErr bool + wantCount int + wantOrder []string +} + +func runWaitTests(t *testing.T, tests []waitTestCase, waitFn func(context.Context, paramsclients.Clients, Opts) ([]pipelinev1.PipelineRun, error)) { + t.Helper() + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx, _ := rtesting.SetupFakeContext(t) + clients := seedAndMakeClients(ctx, t, tt.pipelineRuns) + opts := Opts{ + Namespace: "test-ns", + MinNumberStatus: tt.minStatus, + TargetSHA: tt.targetSHA, + PollTimeout: 10 * time.Millisecond, + } + + prs, err := waitFn(ctx, clients, opts) + if tt.wantErr { + assert.Assert(t, err != nil) + assert.ErrorContains(t, err, "timed out") + return + } + + assert.NilError(t, err) + assert.Equal(t, len(prs), tt.wantCount) + if len(tt.wantOrder) > 0 { + for i, name := range tt.wantOrder { + assert.Equal(t, prs[i].Name, name, "index %d: expected %s got %s", i, name, prs[i].Name) + } + } + }) + } } -func strPtr(v string) *string { - return &v +func TestUntilPipelineRunCreated(t *testing.T) { + now := time.Now() + runWaitTests(t, []waitTestCase{ + { + name: "exact count match returns pipelineruns", + pipelineRuns: []*pipelinev1.PipelineRun{ + makePipelineRunWithStatus("pr-b", "sha-1", "", "", now.Add(2*time.Second), time.Time{}), + makePipelineRunWithStatus("pr-a", "sha-1", "", "", now, time.Time{}), + }, + targetSHA: []string{"sha-1"}, + minStatus: 2, + wantCount: 2, + wantOrder: []string{"pr-a", "pr-b"}, + }, + { + name: "sort order by creation time ascending with three pipelineruns", + pipelineRuns: []*pipelinev1.PipelineRun{ + makePipelineRunWithStatus("pr-third", "sha-1", "", "", now.Add(3*time.Second), time.Time{}), + makePipelineRunWithStatus("pr-first", "sha-1", "", "", now, time.Time{}), + makePipelineRunWithStatus("pr-second", "sha-1", "", "", now.Add(1*time.Second), time.Time{}), + }, + targetSHA: []string{"sha-1"}, + minStatus: 3, + wantCount: 3, + wantOrder: []string{"pr-first", "pr-second", "pr-third"}, + }, + { + name: "times out when count does not match exactly", + pipelineRuns: []*pipelinev1.PipelineRun{ + makePipelineRun("pr-1", "sha-1", ""), + }, + targetSHA: []string{"sha-1"}, + minStatus: 2, + wantErr: true, + }, + { + name: "no target sha matches all pipelineruns", + pipelineRuns: []*pipelinev1.PipelineRun{ + makePipelineRunWithStatus("pr-2", "sha-2", "", "", now.Add(1*time.Second), time.Time{}), + makePipelineRunWithStatus("pr-1", "sha-1", "", "", now, time.Time{}), + }, + minStatus: 2, + wantCount: 2, + wantOrder: []string{"pr-1", "pr-2"}, + }, + }, UntilPipelineRunCreated) +} + +func TestUntilPipelineRunsFinished(t *testing.T) { + now := time.Now() + runWaitTests(t, []waitTestCase{ + { + name: "mixed success and failure both returned sorted by completion", + pipelineRuns: []*pipelinev1.PipelineRun{ + makePipelineRunWithStatus("pr-late", "sha-1", "Succeeded", corev1.ConditionTrue, now, now.Add(10*time.Second)), + makePipelineRunWithStatus("pr-early", "sha-1", "Failed", corev1.ConditionFalse, now, now.Add(5*time.Second)), + }, + targetSHA: []string{"sha-1"}, + minStatus: 2, + wantCount: 2, + wantOrder: []string{"pr-early", "pr-late"}, + }, + { + name: "running pipelinerun not counted as finished", + pipelineRuns: []*pipelinev1.PipelineRun{ + makePipelineRunWithStatus("pr-done", "sha-1", "Succeeded", corev1.ConditionTrue, now, now.Add(5*time.Second)), + makePipelineRun("pr-running", "sha-1", ""), + }, + targetSHA: []string{"sha-1"}, + minStatus: 2, + wantErr: true, + }, + { + name: "no target sha returns all finished across shas", + pipelineRuns: []*pipelinev1.PipelineRun{ + makePipelineRunWithStatus("pr-b", "sha-2", "Failed", corev1.ConditionFalse, now, now.Add(8*time.Second)), + makePipelineRunWithStatus("pr-a", "sha-1", "Succeeded", corev1.ConditionTrue, now, now.Add(3*time.Second)), + }, + minStatus: 2, + wantCount: 2, + wantOrder: []string{"pr-a", "pr-b"}, + }, + { + name: "times out when not enough finished", + pipelineRuns: []*pipelinev1.PipelineRun{ + makePipelineRunWithStatus("pr-1", "sha-1", "Succeeded", corev1.ConditionTrue, now, now.Add(5*time.Second)), + }, + targetSHA: []string{"sha-1"}, + minStatus: 3, + wantErr: true, + }, + { + name: "cancelled pipelinerun counted as finished", + pipelineRuns: []*pipelinev1.PipelineRun{ + makePipelineRunWithStatus("pr-1", "sha-1", "Cancelled", corev1.ConditionFalse, now, now.Add(5*time.Second)), + }, + targetSHA: []string{"sha-1"}, + minStatus: 1, + wantCount: 1, + }, + }, UntilPipelineRunsFinished) } -func TestUntilRepositoryHasStatusReason(t *testing.T) { +func TestUntilPipelineRunHasReason(t *testing.T) { tests := []struct { - name string - statuses []pacv1alpha1.RepositoryRunStatus - targetSHA string - reason string - wantErr bool + name string + pipelineRuns []*pipelinev1.PipelineRun + targetSHA []string + reason string + wantErr bool }{ { name: "match by target sha and reason", - statuses: []pacv1alpha1.RepositoryRunStatus{ - makeRepositoryRunStatus(strPtr("sha-1"), "Succeeded"), - makeRepositoryRunStatus(strPtr("sha-2"), "Cancelled"), + pipelineRuns: []*pipelinev1.PipelineRun{ + makePipelineRun("pr-1", "sha-1", "Succeeded"), + makePipelineRun("pr-2", "sha-2", "Cancelled"), }, - targetSHA: "sha-2", + targetSHA: []string{"sha-2"}, reason: "Cancelled", }, { name: "wrong reason for matching sha", - statuses: []pacv1alpha1.RepositoryRunStatus{ - makeRepositoryRunStatus(strPtr("sha-2"), "Succeeded"), + pipelineRuns: []*pipelinev1.PipelineRun{ + makePipelineRun("pr-1", "sha-2", "Succeeded"), }, - targetSHA: "sha-2", + targetSHA: []string{"sha-2"}, reason: "Cancelled", wantErr: true, }, { name: "reason exists on a different sha only", - statuses: []pacv1alpha1.RepositoryRunStatus{ - makeRepositoryRunStatus(strPtr("sha-1"), "Cancelled"), + pipelineRuns: []*pipelinev1.PipelineRun{ + makePipelineRun("pr-1", "sha-1", "Cancelled"), }, - targetSHA: "sha-2", + targetSHA: []string{"sha-2"}, reason: "Cancelled", wantErr: true, }, { name: "match without target sha filter", - statuses: []pacv1alpha1.RepositoryRunStatus{ - makeRepositoryRunStatus(strPtr("sha-1"), "Cancelled"), + pipelineRuns: []*pipelinev1.PipelineRun{ + makePipelineRun("pr-1", "sha-1", "Cancelled"), }, reason: "Cancelled", }, { - name: "status without conditions", - statuses: []pacv1alpha1.RepositoryRunStatus{ - makeRepositoryRunStatus(strPtr("sha-2"), ""), + name: "pipelinerun without conditions", + pipelineRuns: []*pipelinev1.PipelineRun{ + makePipelineRun("pr-1", "sha-2", ""), }, - targetSHA: "sha-2", + targetSHA: []string{"sha-2"}, reason: "Cancelled", wantErr: true, }, @@ -90,40 +275,15 @@ func TestUntilRepositoryHasStatusReason(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { ctx, _ := rtesting.SetupFakeContext(t) - repositoryNS := "test-repository-ns" - repositoryName := "test-repository" - seeded, _ := testclient.SeedTestData(t, ctx, testclient.Data{ - Namespaces: []*corev1.Namespace{ - { - ObjectMeta: metav1.ObjectMeta{Name: repositoryNS}, - }, - }, - Repositories: []*pacv1alpha1.Repository{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: repositoryName, - Namespace: repositoryNS, - }, - Spec: pacv1alpha1.RepositorySpec{ - URL: "https://ghe.pipelinesascode.com/org/repo", - }, - Status: tt.statuses, - }, - }, - }) - - clients := paramsclients.Clients{ - PipelineAsCode: seeded.PipelineAsCode, - Log: zap.NewNop().Sugar(), - } + clients := seedAndMakeClients(ctx, t, tt.pipelineRuns) opts := Opts{ - RepoName: repositoryName, - Namespace: repositoryNS, - TargetSHA: tt.targetSHA, - PollTimeout: 10 * time.Millisecond, + Namespace: "test-ns", + MinNumberStatus: 1, + TargetSHA: tt.targetSHA, + PollTimeout: 10 * time.Millisecond, } - repository, err := UntilRepositoryHasStatusReason(ctx, clients, opts, tt.reason) + prs, err := UntilPipelineRunHasReason(ctx, clients, pipelinev1.PipelineRunReason(tt.reason), opts) if tt.wantErr { assert.Assert(t, err != nil) assert.ErrorContains(t, err, "timed out") @@ -131,8 +291,7 @@ func TestUntilRepositoryHasStatusReason(t *testing.T) { } assert.NilError(t, err) - assert.Assert(t, repository != nil) - assert.Equal(t, repository.GetName(), repositoryName) + assert.Assert(t, len(prs) >= 1) }) } }