diff --git a/cmd/pj-rehearse/main.go b/cmd/pj-rehearse/main.go index 9ee2f4c2..4ac22b82 100644 --- a/cmd/pj-rehearse/main.go +++ b/cmd/pj-rehearse/main.go @@ -11,6 +11,8 @@ import ( "k8s.io/apimachinery/pkg/util/sets" pjapi "k8s.io/test-infra/prow/apis/prowjobs/v1" + "k8s.io/test-infra/prow/config/secret" + prowflagutil "k8s.io/test-infra/prow/flagutil" prowgithub "k8s.io/test-infra/prow/github" pjdwapi "k8s.io/test-infra/prow/pod-utils/downwardapi" @@ -47,6 +49,7 @@ type options struct { allowVolumes bool debugLogPath string metricsPath string + github prowflagutil.GitHubOptions releaseRepoPath string rehearsalLimit int @@ -67,6 +70,7 @@ func gatherOptions() options { fs.IntVar(&o.rehearsalLimit, "rehearsal-limit", 15, "Upper limit of jobs attempted to rehearse (if more jobs would be rehearsed, none will)") + o.github.AddFlags(fs) fs.Parse(os.Args[1:]) return o } @@ -279,6 +283,22 @@ func rehearseMain() int { return 0 } + secretAgent := &secret.Agent{} + if !o.dryRun { + if err := secretAgent.Start([]string{o.github.TokenPath}); err != nil { + logrus.WithError(err).Fatal("Error starting secrets agent.") + } + } + + githubClient, err := o.github.GitHubClient(secretAgent, o.dryRun) + if err != nil { + logrus.WithError(err).Fatal("Error getting GitHub client.") + } + + if err := rehearse.RetireStallStatuses(githubClient, jobSpec.Refs.Org, jobSpec.Refs.Repo, jobSpec.Refs.Pulls[0].SHA, rehearsals); err != nil { + logrus.WithError(err).Warn("couldn't retire stall statuses") + } + executor := rehearse.NewExecutor(rehearsals, prNumber, o.releaseRepoPath, jobSpec.Refs, o.dryRun, loggers, pjclient) success, err := executor.ExecuteJobs() metrics.Execution = executor.Metrics diff --git a/pkg/rehearse/jobs.go b/pkg/rehearse/jobs.go index 5849630d..f1c3e0d6 100644 --- a/pkg/rehearse/jobs.go +++ b/pkg/rehearse/jobs.go @@ -27,6 +27,7 @@ import ( pjclientsetfake "k8s.io/test-infra/prow/client/clientset/versioned/fake" pj "k8s.io/test-infra/prow/client/clientset/versioned/typed/prowjobs/v1" prowconfig "k8s.io/test-infra/prow/config" + "k8s.io/test-infra/prow/github" "k8s.io/test-infra/prow/pjutil" "github.com/openshift/ci-operator-prowgen/pkg/config" @@ -485,3 +486,48 @@ func (e *Executor) submitRehearsal(job *prowconfig.Presubmit) (*pjapi.ProwJob, e return e.pjclient.Create(&prowJob) } + +func getPRStatuses(statuses []github.Status) sets.String { + ret := sets.NewString() + for _, status := range statuses { + if strings.HasPrefix(status.Context, "ci/rehearse/") { + ret.Insert(status.Context) + } + } + return ret +} + +func getRehearsalContexts(rehearsals []*prowconfig.Presubmit) sets.String { + ret := sets.NewString() + for _, job := range rehearsals { + ret.Insert(job.Context) + } + return ret +} + +// RetireStallStatuses retires all job statuses that exist in the PR from previous runs that currently doesn't +// affect the present state of the changes. +func RetireStallStatuses(ghClient *github.Client, org, repo, SHA string, rehearsals []*prowconfig.Presubmit) error { + combined, err := ghClient.GetCombinedStatus(org, repo, SHA) + if err != nil { + return err + } + + prStatuses := getPRStatuses(combined.Statuses) + rehearsalContexts := getRehearsalContexts(rehearsals) + + for context := range prStatuses { + if !rehearsalContexts.Has(context) { + status := github.Status{ + Context: context, + State: "success", + Description: "Doesn't affect this PR", + } + + if err := ghClient.CreateStatus(org, repo, SHA, status); err != nil { + return err + } + } + } + return nil +}