Skip to content

Commit 81c9dbc

Browse files
committed
feat: support PipelineRun running status reporting on Github with Kueue
this adds support running status of the PipelineRun when PipelineRuns are managed by Kueue. https://issues.redhat.com/browse/SRVKP-7738 Signed-off-by: Zaki Shaikh <[email protected]>
1 parent 313ace7 commit 81c9dbc

File tree

8 files changed

+138
-29
lines changed

8 files changed

+138
-29
lines changed

pkg/provider/bitbucketcloud/bitbucket.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,3 +323,7 @@ func (v *Provider) CreateToken(_ context.Context, _ []string, _ *info.Event) (st
323323
func (v *Provider) GetTemplate(commentType provider.CommentType) string {
324324
return provider.GetMarkdownTemplate(commentType)
325325
}
326+
327+
func (v *Provider) GetStatus(_ context.Context, _ *info.Event, _ string) (string, error) {
328+
return "", nil
329+
}

pkg/provider/bitbucketdatacenter/bitbucketdatacenter.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,3 +431,7 @@ func (v *Provider) CreateToken(_ context.Context, _ []string, _ *info.Event) (st
431431
func (v *Provider) GetTemplate(commentType provider.CommentType) string {
432432
return provider.GetMarkdownTemplate(commentType)
433433
}
434+
435+
func (v *Provider) GetStatus(_ context.Context, _ *info.Event, _ string) (string, error) {
436+
return "", nil
437+
}

pkg/provider/gitea/gitea.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,3 +466,7 @@ func (v *Provider) CreateToken(_ context.Context, _ []string, _ *info.Event) (st
466466
func (v *Provider) GetTemplate(commentType provider.CommentType) string {
467467
return provider.GetHTMLTemplate(commentType)
468468
}
469+
470+
func (v *Provider) GetStatus(_ context.Context, _ *info.Event, _ string) (string, error) {
471+
return "", nil
472+
}

pkg/provider/github/github.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"net/http"
88
"net/url"
99
"regexp"
10+
"strconv"
1011
"strings"
1112
"sync"
1213
"time"
@@ -664,3 +665,25 @@ func (v *Provider) CreateComment(ctx context.Context, event *info.Event, commit,
664665
})
665666
return err
666667
}
668+
669+
// GetStatus returns the status of PipelineRun from check-run API.
670+
// possible value from API response: queued, in_progress, completed, waiting, requested, pending.
671+
func (v *Provider) GetStatus(ctx context.Context, event *info.Event, statusID string) (string, error) {
672+
if v.ghClient == nil {
673+
return "", fmt.Errorf("no github client has been initialized")
674+
}
675+
676+
checkRunID, err := strconv.ParseInt(statusID, 10, 64)
677+
if err != nil {
678+
return "", fmt.Errorf("invalid check-run ID: %w", err)
679+
}
680+
cr, _, err := v.ghClient.Checks.GetCheckRun(ctx, event.Organization, event.Repository, checkRunID)
681+
if err != nil {
682+
return "", err
683+
}
684+
685+
// we have status terms we use across PaC and map those terms with git provider specific status terms returned by API
686+
// response. here we only want to check that the status is queue or not. if it is queued and PipelineRun is running
687+
// in cluster then we're supposed to update status to running via CreateStatus func.
688+
return cr.GetStatus(), nil
689+
}

pkg/provider/gitlab/gitlab.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,3 +540,7 @@ func (v *Provider) isHeadCommitOfBranch(runevent *info.Event, branchName string)
540540
func (v *Provider) GetTemplate(commentType provider.CommentType) string {
541541
return provider.GetHTMLTemplate(commentType)
542542
}
543+
544+
func (v *Provider) GetStatus(_ context.Context, _ *info.Event, _ string) (string, error) {
545+
return "", nil
546+
}

pkg/provider/interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ type Interface interface {
4747
CheckPolicyAllowing(context.Context, *info.Event, []string) (bool, string)
4848
GetTemplate(CommentType) string
4949
CreateComment(ctx context.Context, event *info.Event, comment, updateMarker string) error
50+
GetStatus(ctx context.Context, event *info.Event, statusID string) (string, error)
5051
}
5152

5253
const DefaultProviderAPIUser = "git"

pkg/reconciler/reconciler.go

Lines changed: 94 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ type Reconciler struct {
4343
eventEmitter *events.EventEmitter
4444
globalRepo *v1alpha1.Repository
4545
secretNS string
46+
event *info.Event
47+
repo *v1alpha1.Repository
4648
}
4749

4850
var (
@@ -54,6 +56,51 @@ var (
5456
func (r *Reconciler) ReconcileKind(ctx context.Context, pr *tektonv1.PipelineRun) pkgreconciler.Event {
5557
ctx = info.StoreNS(ctx, system.Namespace())
5658
logger := logging.FromContext(ctx).With("namespace", pr.GetNamespace())
59+
vcx, err := r.getProvider(ctx, pr, logger)
60+
if err != nil {
61+
return err
62+
}
63+
reason := ""
64+
if len(pr.Status.GetConditions()) > 0 {
65+
reason = pr.Status.Status.GetConditions()[0].GetReason()
66+
}
67+
if reason != "" && reason == string(tektonv1.PipelineRunReasonRunning) {
68+
checkRunID := pr.GetAnnotations()[keys.CheckRunID]
69+
status, err := vcx.GetStatus(ctx, r.event, checkRunID)
70+
if err != nil {
71+
return fmt.Errorf("failed to get status of PipelineRun %s: %w", pr.GetName(), err)
72+
}
73+
74+
if status == "queued" {
75+
consoleURL := r.run.Clients.ConsoleUI().DetailURL(pr)
76+
mt := formatting.MessageTemplate{
77+
PipelineRunName: pr.GetName(),
78+
Namespace: r.repo.GetNamespace(),
79+
ConsoleName: r.run.Clients.ConsoleUI().GetName(),
80+
ConsoleURL: consoleURL,
81+
TknBinary: settings.TknBinaryName,
82+
TknBinaryURL: settings.TknBinaryURL,
83+
}
84+
85+
msg, err := mt.MakeTemplate(vcx.GetTemplate(provider.StartingPipelineType))
86+
if err != nil {
87+
return fmt.Errorf("cannot create message template: %w", err)
88+
}
89+
status := provider.StatusOpts{
90+
Status: "in_progress",
91+
Conclusion: "pending",
92+
Text: msg,
93+
DetailsURL: consoleURL,
94+
PipelineRunName: pr.GetName(),
95+
PipelineRun: pr,
96+
OriginalPipelineRunName: pr.GetAnnotations()[keys.OriginalPRName],
97+
}
98+
99+
if err := vcx.CreateStatus(ctx, r.event, status); err != nil {
100+
return fmt.Errorf("cannot use the API on the provider platform to create a in_progress status: %w", err)
101+
}
102+
}
103+
}
57104
// if pipelineRun is in completed or failed state then return
58105
state, exist := pr.GetAnnotations()[keys.State]
59106
if exist && (state == kubeinteraction.StateCompleted || state == kubeinteraction.StateFailed) {
@@ -117,20 +164,60 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, pr *tektonv1.PipelineRun
117164
// use same pac opts across the reconciliation
118165
pacInfo := r.run.Info.GetPacOpts()
119166

167+
if repo, err := r.reportFinalStatus(ctx, logger, &pacInfo, r.event, pr, vcx); err != nil {
168+
msg := fmt.Sprintf("report status: %v", err)
169+
r.eventEmitter.EmitMessage(repo, zap.ErrorLevel, "RepositoryReportFinalStatus", msg)
170+
return err
171+
}
172+
return nil
173+
}
174+
175+
func (r *Reconciler) getProvider(ctx context.Context, pr *tektonv1.PipelineRun, logger *zap.SugaredLogger) (provider.Interface, error) {
176+
pacInfo := r.run.Info.GetPacOpts()
120177
detectedProvider, event, err := r.detectProvider(ctx, logger, pr)
121178
if err != nil {
122-
msg := fmt.Sprintf("detectProvider: %v", err)
179+
msg := fmt.Sprintf("det}ectProvider: %v", err)
123180
r.eventEmitter.EmitMessage(nil, zap.ErrorLevel, "RepositoryDetectProvider", msg)
124-
return nil
181+
return nil, err
125182
}
126183
detectedProvider.SetPacInfo(&pacInfo)
127184

128-
if repo, err := r.reportFinalStatus(ctx, logger, &pacInfo, event, pr, detectedProvider); err != nil {
129-
msg := fmt.Sprintf("report status: %v", err)
130-
r.eventEmitter.EmitMessage(repo, zap.ErrorLevel, "RepositoryReportFinalStatus", msg)
131-
return err
185+
repoName := pr.GetAnnotations()[keys.Repository]
186+
repo, err := r.repoLister.Repositories(pr.Namespace).Get(repoName)
187+
if err != nil {
188+
return nil, fmt.Errorf("reportFinalStatus: %w", err)
132189
}
133-
return nil
190+
191+
if event.InstallationID > 0 {
192+
event.Provider.WebhookSecret, _ = pac.GetCurrentNSWebhookSecret(ctx, r.kinteract, r.run)
193+
} else {
194+
secretNS := repo.GetNamespace()
195+
if repo.Spec.GitProvider != nil && repo.Spec.GitProvider.Secret == nil && r.globalRepo != nil && r.globalRepo.Spec.GitProvider != nil && r.globalRepo.Spec.GitProvider.Secret != nil {
196+
secretNS = r.globalRepo.GetNamespace()
197+
}
198+
secretFromRepo := pac.SecretFromRepository{
199+
K8int: r.kinteract,
200+
Config: detectedProvider.GetConfig(),
201+
Event: event,
202+
Repo: repo,
203+
WebhookType: pacInfo.WebhookType,
204+
Logger: logger,
205+
Namespace: secretNS,
206+
}
207+
if err := secretFromRepo.Get(ctx); err != nil {
208+
return nil, fmt.Errorf("cannot get secret from repository: %w", err)
209+
}
210+
}
211+
212+
err = detectedProvider.SetClient(ctx, r.run, event, repo, r.eventEmitter)
213+
if err != nil {
214+
return nil, fmt.Errorf("cannot set client: %w", err)
215+
}
216+
217+
r.event = event
218+
r.repo = repo
219+
220+
return detectedProvider, nil
134221
}
135222

136223
func (r *Reconciler) reportFinalStatus(ctx context.Context, logger *zap.SugaredLogger, pacInfo *info.PacOpts, event *info.Event, pr *tektonv1.PipelineRun, provider provider.Interface) (*v1alpha1.Repository, error) {
@@ -156,28 +243,6 @@ func (r *Reconciler) reportFinalStatus(ctx context.Context, logger *zap.SugaredL
156243
}
157244
r.run.Clients.ConsoleUI().SetParams(maptemplate)
158245

159-
if event.InstallationID > 0 {
160-
event.Provider.WebhookSecret, _ = pac.GetCurrentNSWebhookSecret(ctx, r.kinteract, r.run)
161-
} else {
162-
secretFromRepo := pac.SecretFromRepository{
163-
K8int: r.kinteract,
164-
Config: provider.GetConfig(),
165-
Event: event,
166-
Repo: repo,
167-
WebhookType: pacInfo.WebhookType,
168-
Logger: logger,
169-
Namespace: r.secretNS,
170-
}
171-
if err := secretFromRepo.Get(ctx); err != nil {
172-
return repo, fmt.Errorf("cannot get secret from repository: %w", err)
173-
}
174-
}
175-
176-
err = provider.SetClient(ctx, r.run, event, repo, r.eventEmitter)
177-
if err != nil {
178-
return repo, fmt.Errorf("cannot set client: %w", err)
179-
}
180-
181246
finalState := kubeinteraction.StateCompleted
182247
newPr, err := r.postFinalStatus(ctx, logger, pacInfo, provider, event, pr)
183248
if err != nil {

pkg/test/provider/testwebvcs.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,7 @@ func (v *TestProviderImp) CreateToken(_ context.Context, _ []string, _ *info.Eve
128128
func (v *TestProviderImp) GetTemplate(commentType provider.CommentType) string {
129129
return provider.GetHTMLTemplate(commentType)
130130
}
131+
132+
func (v *TestProviderImp) GetStatus(_ context.Context, _ *info.Event, _ string) (string, error) {
133+
return "", nil
134+
}

0 commit comments

Comments
 (0)