This is an automated email from the ASF dual-hosted git repository.
squakez pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git
The following commit(s) were added to refs/heads/main by this push:
new 1c71a4c9a fix(ctrl): ignore NotFound when a Build is deleted
mid-reconcile
1c71a4c9a is described below
commit 1c71a4c9a31068468cde0c1a4f183a6beb7a30ee
Author: Ravi <[email protected]>
AuthorDate: Sun Jun 7 02:42:57 2026 +0530
fix(ctrl): ignore NotFound when a Build is deleted mid-reconcile
Signed-off-by: Ravi <[email protected]>
---
pkg/controller/build/build_controller.go | 9 ++++
pkg/controller/build/build_controller_test.go | 65 +++++++++++++++++++++++++++
2 files changed, 74 insertions(+)
diff --git a/pkg/controller/build/build_controller.go
b/pkg/controller/build/build_controller.go
index bc93643ad..998f7164e 100644
--- a/pkg/controller/build/build_controller.go
+++ b/pkg/controller/build/build_controller.go
@@ -196,6 +196,11 @@ func (r *reconcileBuild) Reconcile(ctx context.Context,
request reconcile.Reques
newTarget, err := a.Handle(ctx, target)
if err != nil {
+ // NotFound means the Build was deleted mid-reconcile
(stale cache); benign, not an error.
+ if k8serrors.IsNotFound(err) {
+ return reconcile.Result{}, nil
+ }
+
camelevent.NotifyError(r.recorder, &instance, target,
instance.Name, instance.Kind, err)
return reconcile.Result{}, err
@@ -204,6 +209,10 @@ func (r *reconcileBuild) Reconcile(ctx context.Context,
request reconcile.Reques
if newTarget != nil {
err := r.update(ctx, targetLog, &instance, newTarget)
if err != nil {
+ if k8serrors.IsNotFound(err) {
+ return reconcile.Result{}, nil
+ }
+
return reconcile.Result{}, err
}
diff --git a/pkg/controller/build/build_controller_test.go
b/pkg/controller/build/build_controller_test.go
index c77f92bc1..46ff33319 100644
--- a/pkg/controller/build/build_controller_test.go
+++ b/pkg/controller/build/build_controller_test.go
@@ -25,8 +25,11 @@ import (
"github.com/apache/camel-k/v2/pkg/internal"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
+ ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/client/interceptor"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)
@@ -82,3 +85,65 @@ func TestReconcileBuild(t *testing.T) {
assert.NotNil(t, updated.Status, "status should not be nil")
assert.NotEmpty(t, updated.Status.Phase, "phase should be set")
}
+
+// TestReconcileBuildDeletedDuringReconcile verifies that a Build deleted
mid-reconcile does not
+// surface as a reconcile error: a NotFound from the status write is benign
(#6620).
+func TestReconcileBuildDeletedDuringReconcile(t *testing.T) {
+ ctx := context.TODO()
+
+ build := &v1.Build{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-build",
+ Namespace: "default",
+ },
+ Spec: v1.BuildSpec{
+ Tasks: []v1.Task{
+ {
+ Builder: &v1.BuilderTask{
+ BaseTask: v1.BaseTask{
+ Name: "builder",
+ Configuration:
v1.BuildConfiguration{
+ Strategy:
v1.BuildStrategyRoutine,
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+
+ c, err := internal.NewFakeClient(build)
+ require.NoError(t, err)
+
+ // Simulate the Build being deleted concurrently. The fake client
routes a status patch
+ // through Update, so the NotFound is injected there.
+ fakeClient := c.(*internal.FakeClient)
+ fakeClient.Intercept(&interceptor.Funcs{
+ Update: func(ctx context.Context, cl ctrl.WithWatch, obj
ctrl.Object, opts ...ctrl.UpdateOption) error {
+ if _, ok := obj.(*v1.Build); ok {
+ return
k8serrors.NewNotFound(v1.Resource("builds"), obj.GetName())
+ }
+
+ return cl.Update(ctx, obj, opts...)
+ },
+ })
+
+ r := &reconcileBuild{
+ client: c,
+ reader: c,
+ recorder: &internal.FakeRecorder{},
+ }
+
+ req := reconcile.Request{
+ NamespacedName: types.NamespacedName{
+ Name: "test-build",
+ Namespace: "default",
+ },
+ }
+
+ result, err := r.Reconcile(ctx, req)
+
+ // The NotFound must be swallowed: no error, and no requeue since the
Build is gone.
+ require.NoError(t, err)
+ assert.Equal(t, reconcile.Result{}, result)
+}