Skip to content

Commit fe9bf6d

Browse files
committed
chore(STONEINTG-1189): annotate PLR when component missing
This fixes a silent failure where the Build PipelineRun would stall if the appstudio.openshift.io/component label was incorrect, not found, or missing entirely. Changes: * Added logic to catch 'Component Not Found' errors during loader. * Added logic to catch cases where the component label is nil. * In both cases, the PipelineRun is now annotated with test.appstudio.openshift.io/create-snapshot-status='failed'. * Ensured Finalizer is removed if component is not found, allowing resource deletion. Testing: * Added unit tests in buildpipeline_controller_test.go covering both scenarios. Generated-by: Cursor Signed-off-by: jcullina <[email protected]>
1 parent 0076e2d commit fe9bf6d

File tree

2 files changed

+42
-2
lines changed

2 files changed

+42
-2
lines changed

internal/controller/buildpipeline/buildpipeline_controller.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package buildpipeline
1818

1919
import (
2020
"context"
21+
"fmt"
2122

2223
"github.com/konflux-ci/integration-service/cache"
2324
"k8s.io/client-go/util/retry"
@@ -86,6 +87,11 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
8687
return err
8788
})
8889
if err != nil {
90+
// Annotate the PipelineRun with the error before handling it
91+
tknErr := tekton.AnnotateBuildPipelineRunWithCreateSnapshotAnnotation(ctx, pipelineRun, r.Client, err)
92+
if tknErr != nil {
93+
return ctrl.Result{}, tknErr
94+
}
8995
if errors.IsNotFound(err) {
9096
// Use retry logic to handle etcd timeouts when removing finalizer
9197
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
@@ -105,6 +111,11 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
105111
// if both component and error are nil then the component label for the pipeline did not exist
106112
// in this case we should stop reconciliation
107113
logger.Info("Failed to get component for build pipeline - component label does not exist", "name", pipelineRun.Name, "namespace", pipelineRun.Namespace)
114+
componentErr := fmt.Errorf("component label does not exist on pipelineRun %s/%s", pipelineRun.Namespace, pipelineRun.Name)
115+
tknErr := tekton.AnnotateBuildPipelineRunWithCreateSnapshotAnnotation(ctx, pipelineRun, r.Client, componentErr)
116+
if tknErr != nil {
117+
return ctrl.Result{}, tknErr
118+
}
108119
return ctrl.Result{}, nil
109120
}
110121

internal/controller/buildpipeline/buildpipeline_controller_test.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package buildpipeline
1818

1919
import (
20+
"encoding/json"
2021
"reflect"
2122
"time"
2223

@@ -297,7 +298,17 @@ var _ = Describe("PipelineController", func() {
297298
Namespace: buildPipelineRun.Namespace,
298299
Name: buildPipelineRun.Name,
299300
}, buildPipelineRun)
300-
return err == nil && !controllerutil.ContainsFinalizer(buildPipelineRun, helpers.IntegrationPipelineRunFinalizer)
301+
if err != nil {
302+
return false
303+
}
304+
// Verify the annotation is set
305+
if annotation, ok := buildPipelineRun.Annotations[helpers.CreateSnapshotAnnotationName]; ok {
306+
var info map[string]string
307+
if err := json.Unmarshal([]byte(annotation), &info); err == nil {
308+
return info["status"] == "failed" && !controllerutil.ContainsFinalizer(buildPipelineRun, helpers.IntegrationPipelineRunFinalizer)
309+
}
310+
}
311+
return false
301312
}, time.Second*20).Should(BeTrue())
302313
})
303314

@@ -371,7 +382,25 @@ var _ = Describe("PipelineController", func() {
371382
result, err := pipelineReconciler.Reconcile(ctx, reqNoComponent)
372383
Expect(reflect.TypeOf(result)).To(Equal(reflect.TypeOf(reconcile.Result{})))
373384
Expect(err).ToNot(HaveOccurred())
374-
})
375385

386+
// Verify the annotation is set when component is nil
387+
Eventually(func() bool {
388+
err := k8sClient.Get(ctx, types.NamespacedName{
389+
Namespace: buildPipelineRunNoComponent.Namespace,
390+
Name: buildPipelineRunNoComponent.Name,
391+
}, buildPipelineRunNoComponent)
392+
if err != nil {
393+
return false
394+
}
395+
if annotation, ok := buildPipelineRunNoComponent.Annotations[helpers.CreateSnapshotAnnotationName]; ok {
396+
var info map[string]string
397+
if err := json.Unmarshal([]byte(annotation), &info); err == nil {
398+
return info["status"] == "failed" &&
399+
info["message"] == "Failed to create snapshot. Error: component label does not exist on pipelineRun default/pipelinerun-sample-no-component"
400+
}
401+
}
402+
return false
403+
}, time.Second*20).Should(BeTrue())
404+
})
376405
})
377406
})

0 commit comments

Comments
 (0)