@@ -12,6 +12,8 @@ import (
1212 "strconv"
1313 "strings"
1414
15+ "github.com/openshift-pipelines/pipelines-as-code/pkg/action"
16+ "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/keys"
1517 "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
1618 "github.com/openshift-pipelines/pipelines-as-code/pkg/changedfiles"
1719 "github.com/openshift-pipelines/pipelines-as-code/pkg/events"
@@ -69,6 +71,7 @@ type Provider struct {
6971 memberCache map [int64 ]bool
7072 cachedChangedFiles * changedfiles.ChangedFiles
7173 pacUserID int64 // user login used by PAC
74+ pipelineID int64
7275}
7376
7477var defaultGitlabListOptions = gitlab.ListOptions {
@@ -354,22 +357,39 @@ func (v *Provider) CreateStatus(ctx context.Context, event *info.Event, statusOp
354357 Context : gitlab .Ptr (contextName ),
355358 }
356359
360+ // Reuse a previously discovered pipeline ID so that all commit statuses
361+ // for the same SHA land in the same GitLab pipeline.
362+ if statusOpts .PipelineRun != nil {
363+ if id , ok := statusOpts .PipelineRun .GetAnnotations ()[keys .GitLabPipelineID ]; ok {
364+ pid , err := strconv .ParseInt (id , 10 , 64 )
365+ if err == nil {
366+ opt .PipelineID = gitlab .Ptr (pid )
367+ v .pipelineID = pid
368+ }
369+ }
370+ }
371+ if opt .PipelineID == nil && v .pipelineID != 0 {
372+ opt .PipelineID = gitlab .Ptr (v .pipelineID )
373+ }
374+
357375 // In case we have access, set the status. Typically, on a Merge Request (MR)
358376 // from a fork in an upstream repository, the token needs to have write access
359377 // to the fork repository in order to create a status. However, the token set on the
360378 // Repository CR usually doesn't have such broad access, preventing from creating
361379 // a status comment on it.
362380 // This would work on a push or an MR from a branch within the same repo.
363381 // Ignoring errors because of the write access issues,
364- _ , _ , err := v .Client ().Commits .SetCommitStatus (event .SourceProjectID , event .SHA , opt )
382+ commitStatus , _ , err := v .Client ().Commits .SetCommitStatus (event .SourceProjectID , event .SHA , opt )
365383 if err != nil {
366384 v .Logger .Debugf ("cannot set status with the GitLab token on the source project: %v" , err )
367385 } else {
386+ v .storePipelineID (ctx , statusOpts , commitStatus .PipelineID )
368387 // we managed to set the status on the source repo, all good we are done
369388 v .Logger .Debugf ("created commit status on source project ID %d" , event .TargetProjectID )
370389 return nil
371390 }
372- if _ , _ , err = v .Client ().Commits .SetCommitStatus (event .TargetProjectID , event .SHA , opt ); err == nil {
391+ if commitStatus , _ , err = v .Client ().Commits .SetCommitStatus (event .TargetProjectID , event .SHA , opt ); err == nil {
392+ v .storePipelineID (ctx , statusOpts , commitStatus .PipelineID )
373393 v .Logger .Debugf ("created commit status on target project ID %d" , event .TargetProjectID )
374394 // we managed to set the status on the target repo, all good we are done
375395 return nil
@@ -860,3 +880,35 @@ func (v *Provider) formatPipelineComment(sha string, status providerstatus.Statu
860880 return fmt .Sprintf ("%s **%s: %s/%s for %s**\n \n %s\n \n <small>Full log available [here](%s)</small>" ,
861881 emoji , status .Title , v .pacInfo .ApplicationName , status .OriginalPipelineRunName , sha , status .Text , status .DetailsURL )
862882}
883+
884+ // storePipelineID caches the pipeline ID from a successful SetCommitStatus
885+ // response and patches it onto the PipelineRun annotation for the reconciler.
886+ func (v * Provider ) storePipelineID (ctx context.Context , statusOpts providerstatus.StatusOpts , pipelineID int64 ) {
887+ if pipelineID == 0 {
888+ return
889+ }
890+ v .pipelineID = pipelineID
891+ v .patchPipelineIDAnnotation (ctx , statusOpts , pipelineID )
892+ }
893+
894+ // patchPipelineIDAnnotation stores the GitLab pipeline ID as a PipelineRun
895+ // annotation so the reconciler can read it back across Provider instances.
896+ func (v * Provider ) patchPipelineIDAnnotation (ctx context.Context , statusOpts providerstatus.StatusOpts , pipelineID int64 ) {
897+ pr := statusOpts .PipelineRun
898+ if pr == nil || (pr .GetName () == "" && pr .GetGenerateName () == "" ) {
899+ return
900+ }
901+ if _ , ok := pr .GetAnnotations ()[keys .GitLabPipelineID ]; ok {
902+ return
903+ }
904+ mergePatch := map [string ]any {
905+ "metadata" : map [string ]any {
906+ "annotations" : map [string ]string {
907+ keys .GitLabPipelineID : strconv .FormatInt (pipelineID , 10 ),
908+ },
909+ },
910+ }
911+ if _ , err := action .PatchPipelineRun (ctx , v .Logger , "gitlabPipelineID" , v .run .Clients .Tekton , pr , mergePatch ); err != nil {
912+ v .Logger .Debugf ("failed to patch pipelinerun with gitlab pipeline ID: %v" , err )
913+ }
914+ }
0 commit comments