Repository: shipwright-io/build
Pull request #685 (2021-03-19 22:01:06)

Add EP for synchronous webhook validation
# Changes

Adds a proposal as `provisional` to gather feedback.

See also #596 

/kind feature

# Submitter Checklist

- [n/a] Includes tests if functionality changed/was added
- [n/a] Includes docs if changes are user-facing
- [y] [Set a kind label on this PR](https://prow.k8s.io/command-help#kind)  
- [y] Release notes block has been filled in, or marked NONE

See [the contributor guide](https://github.com/shipwright-io/build/blob/master/CONTRIBUTING.md)
for details on coding conventions, github and prow interactions, and the code review process.

# Release Notes

```release-note
NONE
```

openshift-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by:
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **qu1queee** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @qu1queee` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=shipwright-io%2Fbuild).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/shipwright-io/build/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["qu1queee"]} -->

Patch:
diff --git a/deploy/crds/shipwright.io_buildruns.yaml b/deploy/crds/shipwright.io_buildruns.yaml
index 01be3be4..0e3cb6f0 100644
--- a/deploy/crds/shipwright.io_buildruns.yaml
+++ b/deploy/crds/shipwright.io_buildruns.yaml
@@ -261,6 +261,20 @@ spec:
                               TODO: Add other useful fields. apiVersion, kind, uid?'
                             type: string
                         type: object
+                      flavor:
+                        description: Flavor of the git provider like github, gitlab,
+                          bitbucket, generic, etc. Optional.
+                        type: string
+                      httpProxy:
+                        description: HTTPProxy is optional.
+                        type: string
+                      httpsProxy:
+                        description: HTTPSProxy is optional.
+                        type: string
+                      noProxy:
+                        description: NoProxy can be used to specify domains for which
+                          no proxying should be performed. Optional.
+                        type: string
                       revision:
                         description: Ref is a git reference. Optional. If not defined,
                           it will fallback to the git repository default branch.
diff --git a/deploy/crds/shipwright.io_builds.yaml b/deploy/crds/shipwright.io_builds.yaml
index c1df11dd..5df90530 100644
--- a/deploy/crds/shipwright.io_builds.yaml
+++ b/deploy/crds/shipwright.io_builds.yaml
@@ -202,6 +202,20 @@ spec:
                           TODO: Add other useful fields. apiVersion, kind, uid?'
                         type: string
                     type: object
+                  flavor:
+                    description: Flavor of the git provider like github, gitlab, bitbucket,
+                      generic, etc. Optional.
+                    type: string
+                  httpProxy:
+                    description: HTTPProxy is optional.
+                    type: string
+                  httpsProxy:
+                    description: HTTPSProxy is optional.
+                    type: string
+                  noProxy:
+                    description: NoProxy can be used to specify domains for which
+                      no proxying should be performed. Optional.
+                    type: string
                   revision:
                     description: Ref is a git reference. Optional. If not defined,
                       it will fallback to the git repository default branch.
diff --git a/docs/build.md b/docs/build.md
index 5af473b1..65fcc29d 100644
--- a/docs/build.md
+++ b/docs/build.md
@@ -52,7 +52,7 @@ In order to prevent users from triggering `BuildRuns` (_execution of a Build_) t
 | SetOwnerReferenceFailed   | Setting ownerreferences between a Build and a BuildRun failed. This is triggered when making use of the `build.shipwright.io/build-run-deletion` annotation in a Build. |
 | SpecSourceSecretNotFound | The secret used to authenticate to git doesn´t exist. |
 | SpecOutputSecretRefNotFound | The secret used to authenticate to the container registry doesn´t exist. |
-| SpecBuilderSecretRefNotFound | The secret used to authenticate to the container registry doesn´t exist.|
+| SpecRuntimeSecretRefNotFound | The secret used to authenticate to the container registry doesn´t exist.|
 | MultipleSecretRefNotFound | More than one secret is missing. At the moment, only three paths on a Build can specify a secret. |
 | RuntimePathsCanNotBeEmpty | The Runtime feature is used, but the runtime path was not defined. This is mandatory. |
 | RemoteRepositoryUnreachable | The defined `spec.source.url` was not found. This validation only take place for http/https protocols. |
diff --git a/docs/buildrun.md b/docs/buildrun.md
index d1d8c3e1..cdcb2114 100644
--- a/docs/buildrun.md
+++ b/docs/buildrun.md
@@ -125,20 +125,11 @@ The following table illustrates the different states a BuildRun can have under i
 
 | Status | Reason | CompletionTime is set | Description |
 | --- | --- | --- | --- |
-| Unknown | Pending                       | No  | The BuildRun is waiting on a Pod in status Pending. |
-| Unknown | Running                       | No  | The BuildRun has been validate and started to perform its work. |
-| True    | Succeeded                     | Yes | The BuildRun Pod is done. |
-| False    | Failed                       | Yes | The BuildRun failed in one of the steps. |
-| False    | BuildRunTimeout              | Yes | The BuildRun timed out. |
-| False    | UnknownStrategyKind          | Yes | The Build specified strategy Kind is unknown. (_options: ClusterBuildStrategy or BuildStrategy_) |
-| False    | ClusterBuildStrategyNotFound | Yes | The referenced cluster strategy was not found in the cluster. |
-| False    | BuildStrategyNotFound        | Yes | The referenced namespaced strategy was not found in the cluster. |
-| False    | SetOwnerReferenceFailed      | Yes | Setting ownerreferences from the BuildRun to the related TaskRun failed.  |
-| False    | TaskRunIsMissing             | Yes | The BuildRun related TaskRun was not found. |
-| False    | TaskRunGenerationFailed      | Yes | The generation of a TaskRun spec failed. |
-| False    | ServiceAccountNotFound       | Yes | The referenced service account was not found in the cluster. |
-| False    | BuildRegistrationFailed      | Yes | The related Build in the BuildRun is on a Failed state. |
-| False    | BuildNotFound                | Yes | The related Build in the BuildRun was not found. |
+| Unknown | Pending   | No  | The BuildRun is waiting on a Pod in status Pending. |
+| Unknown | Running   | No  | The BuildRun has been validate and started to perform its work. |
+| True    | Succeeded | Yes | The BuildRun Pod is done. |
+| False    | Failed | Yes | The BuildRun failed in one of the steps. |
+| False    | BuildRunTimeout | Yes | The BuildRun timed out. |
 
 _Note_: We heavily rely on the Tekton TaskRun [Conditions](https://github.com/tektoncd/pipeline/blob/main/docs/taskruns.md#monitoring-execution-status) for populating the BuildRun ones, with some exceptions.
 
diff --git a/docs/proposals/webhook-validation.md b/docs/proposals/webhook-validation.md
new file mode 100644
index 00000000..0d69d3b4
--- /dev/null
+++ b/docs/proposals/webhook-validation.md
@@ -0,0 +1,130 @@
+<!--
+Copyright The Shipwright Contributors
+
+SPDX-License-Identifier: Apache-2.0
+-->
+
+---
+title: webhook-validation
+authors:
+  - "@ImJasonH"
+reviewers:
+  - "@gmontero"
+  - "@zhangtbj"
+approvers:
+  - "@qu1queee"
+  - "@adamkaplan"
+creation-date: 2020-03-19
+last-updated: 2020-03-19
+status: provisional
+---
+
+# Webhook Validation
+
+## Release Signoff Checklist
+
+- [ ] Enhancement is `implementable`
+- [ ] Design details are appropriately documented from clear requirements
+- [ ] Test plan is defined
+- [ ] Graduation criteria for dev preview, tech preview, GA
+- [ ] User-facing documentation is created in [docs](/docs/)
+
+## Open Questions [optional]
+
+Do we want to require that operators run another job to synchronously validate client requests?
+
+Do we want to rely on Knative's webhook packages, or write our own code to manage certs ourselves?
+Is there anything already out there in controller-gen we should be using?
+
+## Summary
+
+Kubernetes provides facilities to inject synchronous validation of CRUD operations from clients for specified types, such as Shipwright's CRD types.
+
+Webhooks can also mutate incoming requests, including setting default values and converting between versions of CRDs. These features should be considered later, and are not described in this proposal.
+
+We should take advantage of these features and include a webhook validation deployment in the Shipwright installation to provide this functionality.
+
+## Motivation
+
+Today, when a user creates a resource (e.g., a Build, BuildRun, etc.), they are immediately stored in the cluster's etcd storage, and the Shipwright controller begins reconciling the object.
+
+If the controller finds that the resource is invalid, it updates the resource's `.status` to indicate this state and stops reconciling it.
+
+Examples of invalid resources include:
+
+- a BuildRun referencing a Build that doesn't exist
+- a BuildRun referencing a ServiceAccount that doesn't exist
+- a Build referencing a (Cluster)BuildStrategy that doesn't exist
+- a BuildStrategy containing zero steps
+
+(This is a partial list, and new validation can be assumed to be added over time as the Shipwright API evolves.)
+
+By allowing invalid resources to be accepted and stored, we require clients to watch or poll all resources to ensure their request was valid, and we add to the API surface of resources that otherwise would not need to report a status, like a Build.
+
+Always accepting and storing resources, even invalid ones, can also lead to additional storage of known-invalid objects, which clutter the user experience and can lead to confusion, and in extreme cases, cluster resource exhaustion.
+
+Mixing reconciliation and validation code in the controller also complicates our codebase, leading to PRs like https://github.com/shipwright-io/build/pull/641 which add new validation-centric statuses that the user must watch for.
+As we add new validation scenarios, we currently add new `Reason` strings that clients must be aware of, which is cumbersome and won't scale indefinitely.
+
+### Goals
+
+Enforce synchronous validation via a new Deployment and a [ValidatingAdmissionWebhook](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#validatingadmissionwebhook), and remove validation-centric logic from the reconciler.
+
+The reconciler should be able to assume in many cases that the resource it is reconciling has already been validated.
+
+### Non-Goals
+
+- Include a mutating or defaulting or conversion webhook.
+  If we decide these are useful, we can add them in future proposals.
+
+## Proposal
+
+Rely on [kubebuilder's webhook support](https://book.kubebuilder.io/cronjob-tutorial/webhook-implementation.html) to add a new webhook validation controller, and include it in Shipwright's default installation as a K8s Deployment.
+
+
+### Implementation Details/Notes/Constraints [optional]
+
+#### Certificates 
+
+The webhook deployment will also need to manage certificates since K8s webhook requests are sent over HTTPS.
+Setting up these certificates securely can be cumbersome.
+
+The [Knative](https://knative.dev) project has [some libraries to make this management easier](https://github.com/knative/pkg/tree/main/webhook) by taking care of cert generation, registration and refreshing, but mixing Knative-style components and existing `controller-gen`/KubeBuilder-style components might make complicate development.
+
+#### Webhook Availability
+
+Once registered, if the K8s API server can't reach the defined webhook service, _all_ requests will fail for registered CRD types.
+The webhook deployment is stateless, so it can be easily replicated and scheduled across multiple nodes to ensure availability in the case of node failure.
+
+### Risks and Mitigations
+
+Clients that expect to have requests accepted and asynchronously validated might be surprised to find the API synchronously rejecting their invalid requests instead.
+We should communicate this change to users and operators in release notes and in mailing list announcements, and be available to answer any questions.
+
+## Design Details
+
+### Test Plan
+
+Our current tests to validate resources should be mostly reusable; validation logic itself isn't going anywhere, just moving.
+
+Any tests that we have that assume an invalid resource will be accepted and eventually reconciled should be updated to expect immediate failure.
+
+### Version Skew Strategy
+
+A user who has previously installed a version of Shipwright that did not synchronously validate might have invalid resources in their etcd storage, and our controller may be asked to reconcile them.
+Basic validation logic should remain in the reconciler, but either update a status to indicate invalidity, or merely log and ignore invalid resources.
+
+During installation or upgrade of Shipwright components, the webhook job and the reconciling controller job might briefly run two versions of validation code, so we should be careful to consider this as we add (or remove, or refactor) validation support over time.
+In practice, Tekton hasn't experienced significant issues with this, but I wanted to call it out because it's possible.
+
+## Implementation History
+
+Major milestones in the life cycle of a proposal should be tracked in `Implementation History`.
+
+## Drawbacks
+
+This requires us to build a new component in the Shipwright installation, and for the operator component to operate it.
+
+## Alternatives
+
+Continue to validate asynchronously, which probably requires investing more in scaling the addition and documentation of validation failures.
diff --git a/pkg/apis/build/v1alpha1/build_types.go b/pkg/apis/build/v1alpha1/build_types.go
index 64f77e8c..49b980fb 100644
--- a/pkg/apis/build/v1alpha1/build_types.go
+++ b/pkg/apis/build/v1alpha1/build_types.go
@@ -26,8 +26,8 @@ const (
 	SpecSourceSecretRefNotFound BuildReason = "SpecSourceSecretRefNotFound"
 	// SpecOutputSecretRefNotFound indicates the referenced secret in output is missing
 	SpecOutputSecretRefNotFound BuildReason = "SpecOutputSecretRefNotFound"
-	// SpecBuilderSecretRefNotFound indicates the referenced secret in builder is missing
-	SpecBuilderSecretRefNotFound BuildReason = "SpecBuilderSecretRefNotFound"
+	// SpecRuntimeSecretRefNotFound indicates the referenced secret in runtime is missing
+	SpecRuntimeSecretRefNotFound BuildReason = "SpecRuntimeSecretRefNotFound"
 	// MultipleSecretRefNotFound indicates that multiple secrets are missing
 	MultipleSecretRefNotFound BuildReason = "MultipleSecretRefNotFound"
 	// RuntimePathsCanNotBeEmpty indicates that the spec.runtime feature is used but the paths were not specified
diff --git a/pkg/apis/build/v1alpha1/buildrun_types.go b/pkg/apis/build/v1alpha1/buildrun_types.go
index 276df5d0..a6a8a488 100644
--- a/pkg/apis/build/v1alpha1/buildrun_types.go
+++ b/pkg/apis/build/v1alpha1/buildrun_types.go
@@ -215,17 +215,6 @@ func (brs *BuildRunStatus) GetCondition(t Type) *Condition {
 	return nil
 }
 
-// IsFailed returns a condition with a False Status
-// based on a type from a list of Conditions.
-func (brs *BuildRunStatus) IsFailed(t Type) bool {
-	for _, c := range brs.Conditions {
-		if c.Type == t {
-			return c.Status == corev1.ConditionFalse
-		}
-	}
-	return false
-}
-
 // SetCondition updates a list of conditions with the provided condition
 func (brs *BuildRunStatus) SetCondition(condition *Condition) {
 	var idx = -1
diff --git a/pkg/apis/build/v1alpha1/gitsource.go b/pkg/apis/build/v1alpha1/gitsource.go
index 56b25106..5800b85a 100644
--- a/pkg/apis/build/v1alpha1/gitsource.go
+++ b/pkg/apis/build/v1alpha1/gitsource.go
@@ -22,6 +22,18 @@ type GitSource struct {
 	// +optional
 	ContextDir *string `json:"contextDir,omitempty"`
 
+	// HTTPProxy is optional.
+	HTTPProxy string `json:"httpProxy,omitempty"`
+
+	// HTTPSProxy is optional.
+	HTTPSProxy string `json:"httpsProxy,omitempty"`
+
+	// NoProxy can be used to specify domains for which no proxying should be performed. Optional.
+	NoProxy string `json:"noProxy,omitempty"`
+
 	// SecretRef refers to the secret that contains credentials to access the git repo. Optional.
 	SecretRef *corev1.LocalObjectReference `json:"credentials,omitempty"`
+
+	// Flavor of the git provider like github, gitlab, bitbucket, generic, etc. Optional.
+	Flavor string `json:"flavor,omitempty"`
 }
diff --git a/pkg/reconciler/buildrun/buildrun.go b/pkg/reconciler/buildrun/buildrun.go
index ecc60aec..ca5ef8c8 100644
--- a/pkg/reconciler/buildrun/buildrun.go
+++ b/pkg/reconciler/buildrun/buildrun.go
@@ -15,6 +15,7 @@ import (
 
 	corev1 "k8s.io/api/core/v1"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/types"
 	"sigs.k8s.io/controller-runtime/pkg/client"
@@ -91,33 +92,16 @@ func (r *ReconcileBuildRun) Reconcile(request reconcile.Request) (reconcile.Resu
 			}
 
 			build = &buildv1alpha1.Build{}
-			err = resources.GetBuildObject(ctx, r.client, buildRun, build)
-			if err != nil {
-				if !resources.IsClientStatusUpdateError(err) && buildRun.Status.IsFailed(buildv1alpha1.Succeeded) {
-					return reconcile.Result{}, nil
-				}
-				// system call failure, reconcile again
-				return reconcile.Result{}, err
+			if err = resources.GetBuildObject(ctx, r.client, buildRun.Spec.BuildRef.Name, buildRun.Namespace, build); err != nil {
+				updateErr := r.updateBuildRunErrorStatus(ctx, buildRun, err.Error())
+				return reconcile.Result{}, resources.HandleError("Failed to fetch the Build instance", err, updateErr)
 			}
 
 			// Validate if the Build was successfully registered
-			if build.Status.Registered == "" {
-				err := fmt.Errorf("the Build is not yet validated, build: %s", build.Name)
-				// reconcile again until it gets a registration value
+			if err := r.ValidateBuildRegistration(ctx, build, buildRun); err != nil {
 				return reconcile.Result{}, err
 			}
 
-			if build.Status.Registered != corev1.ConditionTrue {
-				// stop reconciling and mark the BuildRun as Failed
-				// we only reconcile again if the status.Update call fails
-				message := fmt.Sprintf("the Build is not registered correctly, build: %s, registered status: %s, reason: %s", build.Name, build.Status.Registered, build.Status.Reason)
-				if updateErr := resources.UpdateConditionWithFalseStatus(ctx, r.client, buildRun, message, resources.ConditionBuildRegistrationFailed); updateErr != nil {
-					return reconcile.Result{}, updateErr
-				}
-
-				return reconcile.Result{}, nil
-			}
-
 			// Ensure the build-related labels on the BuildRun
 			if buildRun.GetLabels() == nil {
 				buildRun.Labels = make(map[string]string)
@@ -158,39 +142,16 @@ func (r *ReconcileBuildRun) Reconcile(request reconcile.Request) (reconcile.Resu
 				return reconcile.Result{}, err
 			}
 
-			// Choose a service account to use
-			svcAccount, err := resources.RetrieveServiceAccount(ctx, r.client, build, buildRun)
-			if err != nil {
-				if !resources.IsClientStatusUpdateError(err) && buildRun.Status.IsFailed(buildv1alpha1.Succeeded) {
-					return reconcile.Result{}, nil
-				}
-				// system call failure, reconcile again
-				return reconcile.Result{}, err
-			}
-
-			strategy, err := r.getReferencedStrategy(ctx, build, buildRun)
-			if err != nil {
-				if !resources.IsClientStatusUpdateError(err) && buildRun.Status.IsFailed(buildv1alpha1.Succeeded) {
-					return reconcile.Result{}, nil
-				}
-				return reconcile.Result{}, err
-			}
-
 			// Create the TaskRun, this needs to be the last step in this block to be idempotent
-			generatedTaskRun, err := r.createTaskRun(ctx, svcAccount, strategy, build, buildRun)
+			generatedTaskRun, err := r.createTaskRun(ctx, build, buildRun)
 			if err != nil {
-				if !resources.IsClientStatusUpdateError(err) && buildRun.Status.IsFailed(buildv1alpha1.Succeeded) {
-					ctxlog.Info(ctx, "taskRun generation failed", namespace, request.Namespace, name, request.Name)
-					return reconcile.Result{}, nil
-				}
-				// system call failure, reconcile again
 				return reconcile.Result{}, err
 			}
 
 			ctxlog.Info(ctx, "creating TaskRun from BuildRun", namespace, request.Namespace, name, generatedTaskRun.GenerateName, "BuildRun", buildRun.Name)
 			if err = r.client.Create(ctx, generatedTaskRun); err != nil {
-				// system call failure, reconcile again
-				return reconcile.Result{}, err
+				updateErr := r.updateBuildRunErrorStatus(ctx, buildRun, err.Error())
+				return reconcile.Result{}, resources.HandleError("Failed to create TaskRun if no TaskRun for that BuildRun exists", err, updateErr)
 			}
 
 			// Set the LastTaskRunRef in the BuildRun status
@@ -365,79 +326,92 @@ func (r *ReconcileBuildRun) VerifyRequestName(ctx context.Context, request recon
 				// We ignore the errors from the following call, because the parent call of this function will always
 				// return back a reconcile.Result{}, nil. This is done to avoid infinite reconcile loops when a BuildRun
 				// does not longer exists
-				_ = resources.UpdateConditionWithFalseStatus(ctx, r.client, buildRun, fmt.Sprintf("taskRun %s doesn't exist", request.Name), resources.ConditionTaskRunIsMissing)
+				r.updateBuildRunErrorStatus(ctx, buildRun, fmt.Sprintf("taskRun %s doesn't exist", request.Name))
 			}
 		}
 	}
 }
 
-func (r *ReconcileBuildRun) getReferencedStrategy(ctx context.Context, build *buildv1alpha1.Build, buildRun *buildv1alpha1.BuildRun) (strategy buildv1alpha1.BuilderStrategy, err error) {
-
-	if build.Spec.StrategyRef.Kind == nil {
-		// If the strategy Kind is not specified, we default to a namespaced-scope strategy
-		ctxlog.Info(ctx, "missing strategy Kind, defaulting to a namespaced-scope one", buildRun.Name, build.Name, namespace)
-		strategy, err = resources.RetrieveBuildStrategy(ctx, r.client, build)
-		if err != nil {
-			if apierrors.IsNotFound(err) {
-				if updateErr := resources.UpdateConditionWithFalseStatus(ctx, r.client, buildRun, err.Error(), resources.BuildStrategyNotFound); updateErr != nil {
-					return nil, resources.HandleError("failed to get referenced strategy", err, updateErr)
-				}
-			}
-		}
-		return strategy, err
+func (r *ReconcileBuildRun) createTaskRun(ctx context.Context, build *buildv1alpha1.Build, buildRun *buildv1alpha1.BuildRun) (*v1beta1.TaskRun, error) {
+	var generatedTaskRun *v1beta1.TaskRun
+	// Choose a service account to use
+	serviceAccount, err := resources.RetrieveServiceAccount(ctx, r.client, build, buildRun)
+	if err != nil {
+		updateErr := r.updateBuildRunErrorStatus(ctx, buildRun, err.Error())
+		return nil, resources.HandleError("Failed to choose a service account to use", err, updateErr)
 	}
 
-	switch *build.Spec.StrategyRef.Kind {
-	case buildv1alpha1.NamespacedBuildStrategyKind:
-		strategy, err = resources.RetrieveBuildStrategy(ctx, r.client, build)
+	if build.Spec.StrategyRef.Kind == nil || *build.Spec.StrategyRef.Kind == buildv1alpha1.NamespacedBuildStrategyKind {
+		buildStrategy, err := resources.RetrieveBuildStrategy(ctx, r.client, build)
 		if err != nil {
-			if apierrors.IsNotFound(err) {
-				if updateErr := resources.UpdateConditionWithFalseStatus(ctx, r.client, buildRun, err.Error(), resources.BuildStrategyNotFound); updateErr != nil {
-					return nil, resources.HandleError("failed to get referenced strategy", err, updateErr)
-				}
-			}
+			return nil, err
 		}
-	case buildv1alpha1.ClusterBuildStrategyKind:
-		strategy, err = resources.RetrieveClusterBuildStrategy(ctx, r.client, build)
-		if err != nil {
-			if apierrors.IsNotFound(err) {
-				if updateErr := resources.UpdateConditionWithFalseStatus(ctx, r.client, buildRun, err.Error(), resources.ClusterBuildStrategyNotFound); updateErr != nil {
-					return nil, resources.HandleError("failed to get referenced strategy", err, updateErr)
-				}
+		if buildStrategy != nil {
+			generatedTaskRun, err = resources.GenerateTaskRun(r.config, build, buildRun, serviceAccount.Name, buildStrategy)
+			if err != nil {
+				updateErr := r.updateBuildRunErrorStatus(ctx, buildRun, err.Error())
+				return nil, resources.HandleError("Failed to generate the taskrun with buildStrategy", err, updateErr)
 			}
 		}
-	default:
-		err = fmt.Errorf("unknown strategy %s", string(*build.Spec.StrategyRef.Kind))
-		if updateErr := resources.UpdateConditionWithFalseStatus(ctx, r.client, buildRun, err.Error(), resources.ConditionUnknownStrategyKind); updateErr != nil {
-			return nil, resources.HandleError("failed to get referenced strategy", err, updateErr)
+	} else if *build.Spec.StrategyRef.Kind == buildv1alpha1.ClusterBuildStrategyKind {
+		clusterBuildStrategy, err := resources.RetrieveClusterBuildStrategy(ctx, r.client, build)
+		if err != nil {
+			return nil, err
 		}
-	}
-
-	return strategy, err
-}
-
-func (r *ReconcileBuildRun) createTaskRun(ctx context.Context, serviceAccount *corev1.ServiceAccount, strategy buildv1alpha1.BuilderStrategy, build *buildv1alpha1.Build, buildRun *buildv1alpha1.BuildRun) (*v1beta1.TaskRun, error) {
-	var (
-		generatedTaskRun *v1beta1.TaskRun
-	)
-
-	generatedTaskRun, err := resources.GenerateTaskRun(r.config, build, buildRun, serviceAccount.Name, strategy)
-	if err != nil {
-		if updateErr := resources.UpdateConditionWithFalseStatus(ctx, r.client, buildRun, err.Error(), resources.ConditionTaskRunGenerationFailed); updateErr != nil {
-			return nil, resources.HandleError("failed to create taskrun runtime object", err, updateErr)
+		if clusterBuildStrategy != nil {
+			generatedTaskRun, err = resources.GenerateTaskRun(r.config, build, buildRun, serviceAccount.Name, clusterBuildStrategy)
+			if err != nil {
+				updateErr := r.updateBuildRunErrorStatus(ctx, buildRun, err.Error())
+				return nil, resources.HandleError("Failed to generate the taskrun with clusterBuildStrategy", err, updateErr)
+			}
 		}
-
-		return nil, err
+	} else {
+		err := fmt.Errorf("unknown strategy %s", string(*build.Spec.StrategyRef.Kind))
+		updateErr := r.updateBuildRunErrorStatus(ctx, buildRun, err.Error())
+		return nil, resources.HandleError(fmt.Sprintf("Unsupported BuildStrategy Kind: %v", build.Spec.StrategyRef.Kind), err, updateErr)
 	}
 
 	// Set OwnerReference for BuildRun and TaskRun
 	if err := r.setOwnerReferenceFunc(buildRun, generatedTaskRun, r.scheme); err != nil {
-		if updateErr := resources.UpdateConditionWithFalseStatus(ctx, r.client, buildRun, err.Error(), resources.ConditionSetOwnerReferenceFailed); updateErr != nil {
-			return nil, resources.HandleError("failed to create taskrun runtime object", err, updateErr)
-		}
-
-		return nil, err
+		updateErr := r.updateBuildRunErrorStatus(ctx, buildRun, err.Error())
+		return nil, resources.HandleError("failed to set OwnerReference for BuildRun and TaskRun", err, updateErr)
 	}
 
 	return generatedTaskRun, nil
 }
+
+// updateBuildRunErrorStatus updates buildRun status fields
+func (r *ReconcileBuildRun) updateBuildRunErrorStatus(ctx context.Context, buildRun *buildv1alpha1.BuildRun, errorMessage string) error {
+	// these two fields are deprecated and will be removed soon
+	//lint:ignore SA1019 should be set until removed
+	buildRun.Status.Succeeded = corev1.ConditionFalse
+	//lint:ignore SA1019 should be set until removed
+	buildRun.Status.Reason = errorMessage
+
+	now := metav1.Now()
+	buildRun.Status.CompletionTime = &now
+	buildRun.Status.SetCondition(&buildv1alpha1.Condition{
+		LastTransitionTime: now,
+		Type:               buildv1alpha1.Succeeded,
+		Status:             corev1.ConditionFalse,
+		Reason:             "Failed",
+		Message:            errorMessage,
+	})
+	ctxlog.Debug(ctx, "updating buildRun status", namespace, buildRun.Namespace, name, buildRun.Name)
+	updateErr := r.client.Status().Update(ctx, buildRun)
+	return updateErr
+}
+
+// ValidateBuildRegistration verifies that a referenced Build is properly registered
+func (r *ReconcileBuildRun) ValidateBuildRegistration(ctx context.Context, build *buildv1alpha1.Build, buildRun *buildv1alpha1.BuildRun) error {
+	if build.Status.Registered == "" {
+		err := fmt.Errorf("the Build is not yet validated, build: %s", build.Name)
+		return err
+	}
+	if build.Status.Registered != corev1.ConditionTrue {
+		err := fmt.Errorf("the Build is not registered correctly, build: %s, registered status: %s, reason: %s", build.Name, build.Status.Registered, build.Status.Reason)
+		updateErr := r.updateBuildRunErrorStatus(ctx, buildRun, err.Error())
+		return resources.HandleError("Build is not ready", err, updateErr)
+	}
+	return nil
+}
diff --git a/pkg/reconciler/buildrun/controller.go b/pkg/reconciler/buildrun/controller.go
index 139ea063..de3b350e 100644
--- a/pkg/reconciler/buildrun/controller.go
+++ b/pkg/reconciler/buildrun/controller.go
@@ -58,17 +58,15 @@ func add(ctx context.Context, mgr manager.Manager, r reconcile.Reconciler, maxCo
 
 			// The CreateFunc is also called when the controller is started and iterates over all objects. For those BuildRuns that have a TaskRun referenced already,
 			// we do not need to do a further reconciliation. BuildRun updates then only happen from the TaskRun.
-			return o.Status.LatestTaskRunRef == nil && o.Status.CompletionTime == nil
+			return o.Status.LatestTaskRunRef == nil
 		},
 		UpdateFunc: func(e event.UpdateEvent) bool {
 			// Ignore updates to CR status in which case metadata.Generation does not change
 			o := e.ObjectOld.(*buildv1alpha1.BuildRun)
 
-			// Avoid reconciling when for updates on the BuildRun the following takes place
-			// - the build.shipwright.io/name label is set
-			// - when a BuildRun already have a referenced TaskRun
-			// - when a BuildRun have a completionTime set
-			if o.GetLabels()[buildv1alpha1.LabelBuild] == "" || o.Status.LatestTaskRunRef != nil || o.Status.CompletionTime != nil {
+			// Avoid reconciling when for updates on the BuildRun, the build.shipwright.io/name
+			// label is set, and when a BuildRun already have a referenced TaskRun.
+			if o.GetLabels()[buildv1alpha1.LabelBuild] == "" || o.Status.LatestTaskRunRef != nil {
 				return false
 			}
 
diff --git a/pkg/reconciler/buildrun/resources/build.go b/pkg/reconciler/buildrun/resources/build.go
index cab7fe78..3bfb640e 100644
--- a/pkg/reconciler/buildrun/resources/build.go
+++ b/pkg/reconciler/buildrun/resources/build.go
@@ -6,29 +6,16 @@ package resources
 
 import (
 	"context"
-	"fmt"
 
 	buildv1alpha1 "github.com/shipwright-io/build/pkg/apis/build/v1alpha1"
-	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
 // GetBuildObject retrieves an existing Build based on a name and namespace
-func GetBuildObject(ctx context.Context, client client.Client, buildRun *buildv1alpha1.BuildRun, build *buildv1alpha1.Build) error {
-	err := client.Get(ctx, types.NamespacedName{Name: buildRun.Spec.BuildRef.Name, Namespace: buildRun.Namespace}, build)
-	if err != nil {
-		if apierrors.IsNotFound(err) {
-			// stop reconciling and mark the BuildRun as Failed
-			// we only reconcile again if the status.Update call fails
-			if updateErr := UpdateConditionWithFalseStatus(ctx, client, buildRun, fmt.Sprintf("build.shipwright.io \"%s\" not found", buildRun.Spec.BuildRef.Name), ConditionBuildNotFound); updateErr != nil {
-				return HandleError("build object not found", err, updateErr)
-			}
-		}
-	}
-
-	return err
+func GetBuildObject(ctx context.Context, client client.Client, objectName string, objectNS string, build *buildv1alpha1.Build) error {
+	return client.Get(ctx, types.NamespacedName{Name: objectName, Namespace: objectNS}, build)
 }
 
 // IsOwnedByBuild checks if the controllerReferences contains a well known owner Kind
diff --git a/pkg/reconciler/buildrun/resources/conditions.go b/pkg/reconciler/buildrun/resources/conditions.go
index 806fc267..783f5e0c 100644
--- a/pkg/reconciler/buildrun/resources/conditions.go
+++ b/pkg/reconciler/buildrun/resources/conditions.go
@@ -18,21 +18,6 @@ import (
 	"k8s.io/apimachinery/pkg/types"
 
 	buildv1alpha1 "github.com/shipwright-io/build/pkg/apis/build/v1alpha1"
-	"github.com/shipwright-io/build/pkg/ctxlog"
-)
-
-// Common condition strings for reason, kind, etc.
-const (
-	ConditionUnknownStrategyKind     string = "UnknownStrategyKind"
-	ClusterBuildStrategyNotFound     string = "ClusterBuildStrategyNotFound"
-	BuildStrategyNotFound            string = "BuildStrategyNotFound"
-	ConditionSetOwnerReferenceFailed string = "SetOwnerReferenceFailed"
-	ConditionFailed                  string = "Failed"
-	ConditionTaskRunIsMissing        string = "TaskRunIsMissing"
-	ConditionTaskRunGenerationFailed string = "TaskRunGenerationFailed"
-	ConditionServiceAccountNotFound  string = "ServiceAccountNotFound"
-	ConditionBuildRegistrationFailed string = "BuildRegistrationFailed"
-	ConditionBuildNotFound           string = "BuildNotFound"
 )
 
 // UpdateBuildRunUsingTaskRunCondition updates the BuildRun Succeeded Condition
@@ -109,30 +94,3 @@ func UpdateBuildRunUsingTaskRunCondition(ctx context.Context, client client.Clie
 
 	return nil
 }
-
-// UpdateConditionWithFalseStatus sets the Succeeded condition fields and mark
-// the condition as Status False. It also updates the object in the cluster by
-// calling client Status Update
-func UpdateConditionWithFalseStatus(ctx context.Context, client client.Client, buildRun *buildv1alpha1.BuildRun, errorMessage string, reason string) error {
-	// these two fields are deprecated and will be removed soon
-	//lint:ignore SA1019 should be set until removed
-	buildRun.Status.Succeeded = corev1.ConditionFalse
-	//lint:ignore SA1019 should be set until removed
-	buildRun.Status.Reason = errorMessage
-
-	now := metav1.Now()
-	buildRun.Status.CompletionTime = &now
-	buildRun.Status.SetCondition(&buildv1alpha1.Condition{
-		LastTransitionTime: now,
-		Type:               buildv1alpha1.Succeeded,
-		Status:             corev1.ConditionFalse,
-		Reason:             reason,
-		Message:            errorMessage,
-	})
-	ctxlog.Debug(ctx, "updating buildRun status", namespace, buildRun.Namespace, name, buildRun.Name, "reason", reason)
-	if err := client.Status().Update(ctx, buildRun); err != nil {
-		return &ClientStatusUpdateError{err}
-	}
-
-	return nil
-}
diff --git a/pkg/reconciler/buildrun/resources/errors.go b/pkg/reconciler/buildrun/resources/errors.go
index c697c0a7..7394186a 100644
--- a/pkg/reconciler/buildrun/resources/errors.go
+++ b/pkg/reconciler/buildrun/resources/errors.go
@@ -9,53 +9,14 @@ import (
 	"strings"
 )
 
-// ClientStatusUpdateError is an error that occurrs when trying to update a runtime object status
-type ClientStatusUpdateError struct {
-	reason error
-}
-
-func (e ClientStatusUpdateError) Error() string {
-	return fmt.Sprintf("failed to update client status: %v", e.reason)
-}
-
-// IsClientStatusUpdateError checks whether the given error is of type ClientStatusUpdateError or
-// in case this is a list of errors, that it contains at least one error of type ClientStatusUpdateError
-func IsClientStatusUpdateError(err error) bool {
-	switch terr := err.(type) {
-	case *ClientStatusUpdateError, ClientStatusUpdateError:
-		return true
-
-	case Errors:
-		for _, e := range terr.errors {
-			if IsClientStatusUpdateError(e) {
-				return true
-			}
-		}
-	}
-
-	return false
-}
-
-// Errors allows you to wrap multiple errors
-// in a single struct. Useful when wrapping multiple
-// errors with a single message.
-type Errors struct {
-	message string
-	errors  []error
-}
-
-func (e Errors) Error() string {
-	strErrors := make([]string, len(e.errors))
-	for i, err := range e.errors {
-		if err != nil {
-			strErrors[i] = err.Error()
-		}
-	}
-	return fmt.Sprintf("errors: %s, msg: %s", strings.Join(strErrors, ", "), e.message)
-}
-
 // HandleError returns multiple errors if each error is not nil.
 // And its error message.
-func HandleError(message string, listOfErrors ...error) Errors {
-	return Errors{message: message, errors: listOfErrors}
+func HandleError(message string, listOfErrors ...error) error {
+	var errSlice []string
+	for _, e := range listOfErrors {
+		if e != nil {
+			errSlice = append(errSlice, e.Error())
+		}
+	}
+	return fmt.Errorf("errors: %s, msg: %s", strings.Join(errSlice, ", "), message)
 }
diff --git a/pkg/reconciler/buildrun/resources/service_accounts.go b/pkg/reconciler/buildrun/resources/service_accounts.go
index 73380b77..023501a8 100644
--- a/pkg/reconciler/buildrun/resources/service_accounts.go
+++ b/pkg/reconciler/buildrun/resources/service_accounts.go
@@ -6,7 +6,6 @@ package resources
 
 import (
 	"context"
-	"fmt"
 
 	buildv1alpha1 "github.com/shipwright-io/build/pkg/apis/build/v1alpha1"
 	"github.com/shipwright-io/build/pkg/ctxlog"
@@ -14,8 +13,8 @@ import (
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
-	"k8s.io/utils/pointer"
 	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 )
 
 const (
@@ -39,116 +38,70 @@ func IsGeneratedServiceAccountUsed(buildRun *buildv1alpha1.BuildRun) bool {
 	return buildRun.Spec.ServiceAccount != nil && buildRun.Spec.ServiceAccount.Generate
 }
 
-// GenerateSA generates a new service account on the fly
-func GenerateSA(ctx context.Context, client client.Client, build *buildv1alpha1.Build, buildRun *buildv1alpha1.BuildRun) (serviceAccount *corev1.ServiceAccount, err error) {
-	serviceAccount = &corev1.ServiceAccount{}
-	err = client.Get(
-		ctx,
-		types.NamespacedName{
-			Name:      GetGeneratedServiceAccountName(buildRun),
-			Namespace: buildRun.Namespace},
-		serviceAccount)
-
-	switch {
-	case err == nil: // if the service account already exists, do nothing and just return it
-		ctxlog.Info(ctx, "serviceAccount for BuildRun already exists", namespace, buildRun.Namespace, name, serviceAccount.Name, "BuildRun", buildRun.Name)
-		return serviceAccount, nil
-
-	case apierrors.IsNotFound(err):
-		// populate the object with well known required fields
-		serviceAccount = &corev1.ServiceAccount{
-			ObjectMeta: metav1.ObjectMeta{
-				Name:      GetGeneratedServiceAccountName(buildRun),
-				Namespace: buildRun.Namespace,
-				Labels:    map[string]string{buildv1alpha1.LabelBuildRun: buildRun.Name},
-				OwnerReferences: []metav1.OwnerReference{
-					*metav1.NewControllerRef(buildRun, buildv1alpha1.SchemeGroupVersion.WithKind("BuildRun")),
-				},
-			},
-			AutomountServiceAccountToken: pointer.BoolPtr(false),
-		}
-		ctxlog.Debug(ctx, "automatic generation of service account", namespace, serviceAccount.Namespace, name, serviceAccount.Name)
-
-		// add the secrets references into the new sa
-		ApplyCredentials(ctx, build, serviceAccount)
-
-		// if we didnt have the sa, then create one and ensure the Build secrets are referenced
-		if err := client.Create(ctx, serviceAccount); err != nil {
-			return nil, err
-		}
-
-		ctxlog.Info(ctx, "created serviceAccount for BuildRun", namespace, buildRun.Namespace, name, serviceAccount.Name, "BuildRun", buildRun.Name)
-		return serviceAccount, nil
-
-	default:
-		return nil, err
-	}
-}
-
-// getDefaultNamespaceSA retrieves a pipeline or default sa per namespace. This is used when users do not specify a service account
-// to use on BuildRuns
-func getDefaultNamespaceSA(ctx context.Context, client client.Client, buildRun *buildv1alpha1.BuildRun) (*corev1.ServiceAccount, error) {
-	// Note: If the default SA is not in the namespace, the controller will be always reconciling until if finds it or until the
-	// BuildRun gets deleted
-	serviceAccount := &corev1.ServiceAccount{}
-
-	err := client.Get(ctx, types.NamespacedName{Name: PipelineServiceAccountName, Namespace: buildRun.Namespace}, serviceAccount)
-	if err != nil && !apierrors.IsNotFound(err) {
-		return nil, err
-	} else if apierrors.IsNotFound(err) {
-		ctxlog.Info(ctx, "falling back to default serviceAccount", namespace, buildRun.Namespace)
-		err = client.Get(ctx, types.NamespacedName{Name: DefaultServiceAccountName, Namespace: buildRun.Namespace}, serviceAccount)
-		if err != nil {
-			return nil, err
-		}
-	}
-	return serviceAccount, nil
-}
-
 // RetrieveServiceAccount provides either a default sa with a referenced secret or it will generate a new sa on the fly.
 // When not using the generate feature, it will modify and return the default sa from a k8s namespace, which is "default"
 // or the default sa inside an openshift namespace, which is "pipeline".
 func RetrieveServiceAccount(ctx context.Context, client client.Client, build *buildv1alpha1.Build, buildRun *buildv1alpha1.BuildRun) (*corev1.ServiceAccount, error) {
+	serviceAccount := &corev1.ServiceAccount{}
 
-	var (
-		err error
-	)
-
-	// generate or retrieve an existing autogenerated sa
 	if IsGeneratedServiceAccountUsed(buildRun) {
-		return GenerateSA(ctx, client, build, buildRun)
-	}
+		serviceAccountName := GetGeneratedServiceAccountName(buildRun)
 
-	serviceAccount := &corev1.ServiceAccount{}
+		serviceAccount.Name = serviceAccountName
+		serviceAccount.Namespace = buildRun.Namespace
 
-	if buildRun.Spec.ServiceAccount != nil && buildRun.Spec.ServiceAccount.Name != nil {
-		serviceAccountName := *buildRun.Spec.ServiceAccount.Name
-		err := client.Get(ctx, types.NamespacedName{Name: serviceAccountName, Namespace: buildRun.Namespace}, serviceAccount)
-		// here we might need to update Status Conditions and Fail the BR
-		if err != nil {
-			if apierrors.IsNotFound(err) {
-				if updateErr := UpdateConditionWithFalseStatus(ctx, client, buildRun, fmt.Sprintf("service account %s not found", serviceAccountName), ConditionServiceAccountNotFound); updateErr != nil {
-					return nil, HandleError("failed to retrieve service account", err, updateErr)
-				}
-			}
+		// when generating a ServiceAccount on the fly, it will generate a corresponding ServiceAccount
+		// token Secret to allow API access. Avoid mounting this at the pod level while it is
+		// not used and might bring more problems during mounting.
+		mountSAToken := false
+
+		// Create the service account, use CreateOrUpdate as it might exist already from a previous reconciliation that
+		// succeeded to create the service account but failed to update the build run that references it
+		ctxlog.Info(ctx, "create or update serviceAccount for BuildRun", namespace, buildRun.Namespace, name, serviceAccountName, "BuildRun", buildRun.Name)
+		op, err := controllerutil.CreateOrUpdate(ctx, client, serviceAccount, func() error {
+			serviceAccount.SetLabels(map[string]string{buildv1alpha1.LabelBuildRun: buildRun.Name})
+
+			ownerReference := metav1.NewControllerRef(buildRun, buildv1alpha1.SchemeGroupVersion.WithKind("BuildRun"))
+			serviceAccount.SetOwnerReferences([]metav1.OwnerReference{*ownerReference})
+			serviceAccount.AutomountServiceAccountToken = &mountSAToken
+			ApplyCredentials(ctx, build, serviceAccount)
 
+			return nil
+		})
+		if err != nil {
 			return nil, err
 		}
+		ctxlog.Debug(ctx, "automatic generation of service account", namespace, serviceAccount.Namespace, name, serviceAccount.Name, "Operation", op)
 	} else {
-		// we default to pipeline/default sa
-		serviceAccount, err = getDefaultNamespaceSA(ctx, client, buildRun)
-		if err != nil {
-			return nil, err
+		// If ServiceAccount or the name of ServiceAccount in buildRun is nil, use pipeline serviceaccount
+		if buildRun.Spec.ServiceAccount == nil || buildRun.Spec.ServiceAccount.Name == nil {
+			serviceAccountName := PipelineServiceAccountName
+			err := client.Get(ctx, types.NamespacedName{Name: serviceAccountName, Namespace: buildRun.Namespace}, serviceAccount)
+			if err != nil && !apierrors.IsNotFound(err) {
+				return nil, err
+			} else if apierrors.IsNotFound(err) {
+				serviceAccountName = DefaultServiceAccountName
+				ctxlog.Info(ctx, "falling back to default serviceAccount", namespace, buildRun.Namespace)
+				err = client.Get(ctx, types.NamespacedName{Name: serviceAccountName, Namespace: buildRun.Namespace}, serviceAccount)
+				if err != nil {
+					return nil, err
+				}
+			}
+		} else {
+			serviceAccountName := *buildRun.Spec.ServiceAccount.Name
+			err := client.Get(ctx, types.NamespacedName{Name: serviceAccountName, Namespace: buildRun.Namespace}, serviceAccount)
+			if err != nil {
+				return nil, err
+			}
 		}
-	}
 
-	// Add credentials and update the service account
-	if modified := ApplyCredentials(ctx, build, serviceAccount); modified {
-		ctxlog.Info(ctx, "updating ServiceAccount with secrets from build", namespace, serviceAccount.Namespace, name, serviceAccount.Name)
-		if err := client.Update(ctx, serviceAccount); err != nil {
-			return nil, err
+		// Add credentials and update the service account
+		if modified := ApplyCredentials(ctx, build, serviceAccount); modified {
+			ctxlog.Info(ctx, "updating ServiceAccount with secrets from build", namespace, serviceAccount.Namespace, name, serviceAccount.Name)
+			if err := client.Update(ctx, serviceAccount); err != nil {
+				return nil, err
+			}
 		}
 	}
-
 	return serviceAccount, nil
 }
diff --git a/pkg/reconciler/buildrun/resources/strategies.go b/pkg/reconciler/buildrun/resources/strategies.go
index f613d845..cbebb581 100644
--- a/pkg/reconciler/buildrun/resources/strategies.go
+++ b/pkg/reconciler/buildrun/resources/strategies.go
@@ -19,9 +19,10 @@ func RetrieveBuildStrategy(ctx context.Context, client client.Client, build *bui
 	buildStrategyInstance := &buildv1alpha1.BuildStrategy{}
 
 	ctxlog.Debug(ctx, "retrieving BuildStrategy", namespace, build.Namespace, name, build.Name)
-
-	// Note: When returning the client.Get call, the buildStrategyInstance gets populated and properly returned as the first argument
-	return buildStrategyInstance, client.Get(ctx, types.NamespacedName{Name: build.Spec.StrategyRef.Name, Namespace: build.Namespace}, buildStrategyInstance)
+	if err := client.Get(ctx, types.NamespacedName{Name: build.Spec.StrategyRef.Name, Namespace: build.Namespace}, buildStrategyInstance); err != nil {
+		return nil, err
+	}
+	return buildStrategyInstance, nil
 }
 
 // RetrieveClusterBuildStrategy returns a cluster scoped strategy
@@ -29,7 +30,8 @@ func RetrieveClusterBuildStrategy(ctx context.Context, client client.Client, bui
 	clusterBuildStrategyInstance := &buildv1alpha1.ClusterBuildStrategy{}
 
 	ctxlog.Debug(ctx, "retrieving ClusterBuildStrategy", namespace, build.Namespace, name, build.Name)
-
-	// Note: When returning the client.Get call, the clusterBuildStrategyInstance gets populated and properly returned as the first argument
-	return clusterBuildStrategyInstance, client.Get(ctx, types.NamespacedName{Name: build.Spec.StrategyRef.Name}, clusterBuildStrategyInstance)
+	if err := client.Get(ctx, types.NamespacedName{Name: build.Spec.StrategyRef.Name}, clusterBuildStrategyInstance); err != nil {
+		return nil, err
+	}
+	return clusterBuildStrategyInstance, nil
 }
diff --git a/pkg/validate/secrets.go b/pkg/validate/secrets.go
index 780e4ca0..7360ee67 100644
--- a/pkg/validate/secrets.go
+++ b/pkg/validate/secrets.go
@@ -62,7 +62,7 @@ func (s SecretRef) buildSecretReferences() map[string]build.BuildReason {
 		secretRefMap[s.Build.Spec.Source.SecretRef.Name] = build.SpecSourceSecretRefNotFound
 	}
 	if s.Build.Spec.BuilderImage != nil && s.Build.Spec.BuilderImage.SecretRef != nil && s.Build.Spec.BuilderImage.SecretRef.Name != "" {
-		secretRefMap[s.Build.Spec.BuilderImage.SecretRef.Name] = build.SpecBuilderSecretRefNotFound
+		secretRefMap[s.Build.Spec.BuilderImage.SecretRef.Name] = build.SpecRuntimeSecretRefNotFound
 	}
 	return secretRefMap
 }


Test patch:
diff --git a/pkg/reconciler/build/build_test.go b/pkg/reconciler/build/build_test.go
index 2ea9880d..2ca1113a 100644
--- a/pkg/reconciler/build/build_test.go
+++ b/pkg/reconciler/build/build_test.go
@@ -138,7 +138,7 @@ var _ = Describe("Reconcile Build", func() {
 				}
 				buildSample.Spec.Output.SecretRef = nil
 
-				statusCall := ctl.StubFunc(corev1.ConditionFalse, build.SpecBuilderSecretRefNotFound, "referenced secret non-existing not found")
+				statusCall := ctl.StubFunc(corev1.ConditionFalse, build.SpecRuntimeSecretRefNotFound, "referenced secret non-existing not found")
 				statusWriter.UpdateCalls(statusCall)
 
 				_, err := reconciler.Reconcile(request)
diff --git a/pkg/reconciler/buildrun/buildrun_test.go b/pkg/reconciler/buildrun/buildrun_test.go
index 0c0af469..f74ab80e 100644
--- a/pkg/reconciler/buildrun/buildrun_test.go
+++ b/pkg/reconciler/buildrun/buildrun_test.go
@@ -7,11 +7,15 @@ package buildrun_test
 import (
 	"context"
 	"fmt"
+	"strconv"
 	"time"
 
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 	v1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
+	knativeapi "knative.dev/pkg/apis"
+	knativev1beta1 "knative.dev/pkg/apis/duck/v1beta1"
+
 	corev1 "k8s.io/api/core/v1"
 	k8serrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -20,8 +24,6 @@ import (
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/client-go/kubernetes/scheme"
 	"k8s.io/utils/pointer"
-	knativeapi "knative.dev/pkg/apis"
-	knativev1beta1 "knative.dev/pkg/apis/duck/v1beta1"
 	crc "sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 	"sigs.k8s.io/controller-runtime/pkg/reconcile"
@@ -32,7 +34,6 @@ import (
 	"github.com/shipwright-io/build/pkg/controller/fakes"
 	"github.com/shipwright-io/build/pkg/ctxlog"
 	buildrunctl "github.com/shipwright-io/build/pkg/reconciler/buildrun"
-	"github.com/shipwright-io/build/pkg/reconciler/buildrun/resources"
 	"github.com/shipwright-io/build/test"
 )
 
@@ -47,6 +48,7 @@ var _ = Describe("Reconcile BuildRun", func() {
 		buildRunSample                                         *build.BuildRun
 		taskRunSample                                          *v1beta1.TaskRun
 		statusWriter                                           *fakes.FakeStatusWriter
+		fakeBuildStrategyKind                                  build.BuildStrategyKind
 		taskRunName, buildRunName, buildName, strategyName, ns string
 	)
 
@@ -467,61 +469,7 @@ var _ = Describe("Reconcile BuildRun", func() {
 				buildRunSample = ctl.BuildRunWithSA(buildRunName, buildName, saName)
 			})
 
-			It("should return none error and stop reconciling if referenced Build is not found", func() {
-				buildRunSample = ctl.BuildRunWithoutSA(buildRunName, buildName)
-
-				// override the initial getClientStub, and generate a new stub
-				// that only contains a Buildrun
-				stubGetCalls := func(context context.Context, nn types.NamespacedName, object runtime.Object) error {
-					switch object := object.(type) {
-					case *build.Build:
-						return k8serrors.NewNotFound(schema.GroupResource{}, nn.Name)
-					case *build.BuildRun:
-						buildRunSample.DeepCopyInto(object)
-						return nil
-					}
-					return k8serrors.NewNotFound(schema.GroupResource{}, nn.Name)
-				}
-				client.GetCalls(stubGetCalls)
-
-				_, err := reconciler.Reconcile(buildRunRequest)
-				Expect(err).To(BeNil())
-				Expect(resources.IsClientStatusUpdateError(err)).To(BeFalse())
-			})
-
-			It("should return an error and continue reconciling if referenced Build is not found and the status update fails", func() {
-				buildRunSample = ctl.BuildRunWithoutSA(buildRunName, buildName)
-
-				// override the initial getClientStub, and generate a new stub
-				// that only contains a BuildRun
-				stubGetCalls := func(context context.Context, nn types.NamespacedName, object runtime.Object) error {
-					switch object := object.(type) {
-					case *build.Build:
-						return k8serrors.NewNotFound(schema.GroupResource{}, nn.Name)
-					case *build.BuildRun:
-						buildRunSample.DeepCopyInto(object)
-						return nil
-					}
-					return k8serrors.NewNotFound(schema.GroupResource{}, nn.Name)
-				}
-				client.GetCalls(stubGetCalls)
-
-				statusWriter.UpdateCalls(func(_ context.Context, object runtime.Object, _ ...crc.UpdateOption) error {
-					switch buildRun := object.(type) {
-					case *build.BuildRun:
-						if buildRun.Status.IsFailed(build.Succeeded) {
-							return fmt.Errorf("failed miserably")
-						}
-					}
-					return nil
-				})
-
-				_, err := reconciler.Reconcile(buildRunRequest)
-				Expect(err).ToNot(BeNil())
-				Expect(resources.IsClientStatusUpdateError(err)).To(BeTrue())
-			})
-
-			It("fails on a TaskRun creation due to service account not found", func() {
+			It("fails on a TaskRun creation due to missing service account", func() {
 
 				// override the initial getClientStub, and generate a new stub
 				// that only contains a Build and Buildrun, none TaskRun
@@ -542,11 +490,11 @@ var _ = Describe("Reconcile BuildRun", func() {
 				// Stub that asserts the BuildRun status fields when
 				// Status updates for a BuildRun take place
 				statusCall := ctl.StubBuildRunStatus(
-					fmt.Sprintf("service account %s not found", saName),
+					fmt.Sprintf(" \"%s\" not found", saName),
 					emptyTaskRunName,
 					build.Condition{
 						Type:   build.Succeeded,
-						Reason: "ServiceAccountNotFound",
+						Reason: "Failed",
 						Status: corev1.ConditionFalse,
 					},
 					corev1.ConditionFalse,
@@ -555,17 +503,19 @@ var _ = Describe("Reconcile BuildRun", func() {
 				)
 				statusWriter.UpdateCalls(statusCall)
 
-				// we mark the BuildRun as Failed and do not reconcile again
 				_, err := reconciler.Reconcile(buildRunRequest)
-				Expect(err).ToNot(HaveOccurred())
+				Expect(err).To(HaveOccurred())
+				Expect(err.Error()).To(ContainSubstring("Failed to choose a service account to use"))
 				Expect(client.GetCallCount()).To(Equal(4))
 				Expect(client.StatusCallCount()).To(Equal(2))
 			})
-			It("fails on a TaskRun creation due to issues when retrieving the service account", func() {
+
+			It("use the default serviceAccount when pipeline serviceAccount doesn't exist and generate serviceAccount is false", func() {
+				// override the BuildRun without serviceAccount and generate is false
+				buildRunSample = ctl.BuildRunWithoutSA(buildRunName, buildName)
 
 				// override the initial getClientStub, and generate a new stub
-				// that only contains a Build, BuildRun and a random error when
-				// retrieving a service account
+				// that only contains a Build and Buildrun, none TaskRun
 				stubGetCalls := func(context context.Context, nn types.NamespacedName, object runtime.Object) error {
 					switch object := object.(type) {
 					case *build.Build:
@@ -574,23 +524,17 @@ var _ = Describe("Reconcile BuildRun", func() {
 					case *build.BuildRun:
 						buildRunSample.DeepCopyInto(object)
 						return nil
-					case *corev1.ServiceAccount:
-						return fmt.Errorf("something wrong happen")
 					}
 					return k8serrors.NewNotFound(schema.GroupResource{}, nn.Name)
 				}
-
 				client.GetCalls(stubGetCalls)
 
-				// we reconcile again on system call errors
 				_, err := reconciler.Reconcile(buildRunRequest)
 				Expect(err).To(HaveOccurred())
-				Expect(err.Error()).To(ContainSubstring("something wrong happen"))
-				Expect(client.GetCallCount()).To(Equal(4))
-				Expect(client.StatusCallCount()).To(Equal(1))
+				Expect(err.Error()).To(ContainSubstring(`"default" not found, msg: Failed to choose a service account to use`))
 			})
 
-			It("fails on a TaskRun creation due to namespaced buildstrategy not found", func() {
+			It("fails on a TaskRun creation due to missing namespaced buildstrategy", func() {
 
 				// override the Build to use a namespaced BuildStrategy
 				buildSample = ctl.DefaultBuild(buildName, strategyName, build.NamespacedBuildStrategyKind)
@@ -603,130 +547,30 @@ var _ = Describe("Reconcile BuildRun", func() {
 					ctl.DefaultServiceAccount(saName)),
 				)
 
-				// Stub that asserts the BuildRun status fields when
-				// Status updates for a BuildRun take place
-				statusCall := ctl.StubBuildRunStatus(
-					fmt.Sprintf(" \"%s\" not found", strategyName),
-					emptyTaskRunName,
-					build.Condition{
-						Type:   build.Succeeded,
-						Reason: "BuildStrategyNotFound",
-						Status: corev1.ConditionFalse,
-					},
-					corev1.ConditionFalse,
-					buildSample.Spec,
-					true,
-				)
-				statusWriter.UpdateCalls(statusCall)
-
 				_, err := reconciler.Reconcile(buildRunRequest)
-				// we mark the BuildRun as Failed and do not reconcile again
-				Expect(err).ToNot(HaveOccurred())
-			})
-
-			It("fails on a TaskRun creation due to issues when retrieving the buildstrategy", func() {
-
-				// override the Build to use a namespaced BuildStrategy
-				buildSample = ctl.DefaultBuild(buildName, strategyName, build.NamespacedBuildStrategyKind)
-
-				// stub get calls so that on namespaced strategy retrieval, we throw a random error
-				stubGetCalls := func(context context.Context, nn types.NamespacedName, object runtime.Object) error {
-					switch object := object.(type) {
-					case *build.Build:
-						buildSample.DeepCopyInto(object)
-						return nil
-					case *build.BuildRun:
-						buildRunSample.DeepCopyInto(object)
-						return nil
-					case *corev1.ServiceAccount:
-						ctl.DefaultServiceAccount(saName).DeepCopyInto(object)
-						return nil
-					case *build.BuildStrategy:
-						return fmt.Errorf("something wrong happen")
-					}
-					return k8serrors.NewNotFound(schema.GroupResource{}, nn.Name)
-				}
-
-				// Override Stub get calls to include a service account
-				// but none BuildStrategy
-				client.GetCalls(stubGetCalls)
-
-				_, err := reconciler.Reconcile(buildRunRequest)
-				// we reconcile again
 				Expect(err).To(HaveOccurred())
-				Expect(err.Error()).To(ContainSubstring("something wrong happen"))
-				Expect(client.GetCallCount()).To(Equal(5))
-				Expect(client.StatusCallCount()).To(Equal(1))
+				Expect(err.Error()).To(ContainSubstring(fmt.Sprintf(" \"%s\" not found", strategyName)))
 			})
 
-			It("fails on a TaskRun creation due to cluster buildstrategy not found", func() {
+			It("fails on a TaskRun creation due to missing cluster buildstrategy", func() {
 				// override the Build to use a cluster BuildStrategy
 				buildSample = ctl.DefaultBuild(buildName, strategyName, build.ClusterBuildStrategyKind)
 
 				// Override Stub get calls to include a service account
-				// but none ClusterBuildStrategy
+				// but none BuildStrategy
 				client.GetCalls(ctl.StubBuildRunGetWithSA(
 					buildSample,
 					buildRunSample,
 					ctl.DefaultServiceAccount(saName)),
 				)
 
-				// Stub that asserts the BuildRun status fields when
-				// Status updates for a BuildRun take place
-				statusCall := ctl.StubBuildRunStatus(
-					fmt.Sprintf(" \"%s\" not found", strategyName),
-					emptyTaskRunName,
-					build.Condition{
-						Type:   build.Succeeded,
-						Reason: "ClusterBuildStrategyNotFound",
-						Status: corev1.ConditionFalse,
-					},
-					corev1.ConditionFalse,
-					buildSample.Spec,
-					true,
-				)
-				statusWriter.UpdateCalls(statusCall)
-
 				_, err := reconciler.Reconcile(buildRunRequest)
-				// we mark the BuildRun as Failed and do not reconcile again
-				Expect(err).ToNot(HaveOccurred())
-			})
-
-			It("fails on a TaskRun creation due to issues when retrieving the clusterbuildstrategy", func() {
-
-				// override the Build to use a namespaced BuildStrategy
-				buildSample = ctl.DefaultBuild(buildName, strategyName, build.ClusterBuildStrategyKind)
-
-				// stub get calls so that on cluster strategy retrieval, we throw a random error
-				stubGetCalls := func(context context.Context, nn types.NamespacedName, object runtime.Object) error {
-					switch object := object.(type) {
-					case *build.Build:
-						buildSample.DeepCopyInto(object)
-						return nil
-					case *build.BuildRun:
-						buildRunSample.DeepCopyInto(object)
-						return nil
-					case *corev1.ServiceAccount:
-						ctl.DefaultServiceAccount(saName).DeepCopyInto(object)
-						return nil
-					case *build.ClusterBuildStrategy:
-						return fmt.Errorf("something wrong happen")
-					}
-					return k8serrors.NewNotFound(schema.GroupResource{}, nn.Name)
-				}
-
-				client.GetCalls(stubGetCalls)
-
-				_, err := reconciler.Reconcile(buildRunRequest)
-				// we reconcile again
 				Expect(err).To(HaveOccurred())
-				Expect(err.Error()).To(ContainSubstring("something wrong happen"))
-				Expect(client.GetCallCount()).To(Equal(5))
-				Expect(client.StatusCallCount()).To(Equal(1))
+				Expect(err.Error()).To(ContainSubstring(fmt.Sprintf(" \"%s\" not found", strategyName)))
 			})
 
 			It("fails on a TaskRun creation due to unknown buildStrategy kind", func() {
-				buildSample = ctl.DefaultBuild(buildName, strategyName, "foobar")
+				buildSample = ctl.DefaultBuild(buildName, strategyName, fakeBuildStrategyKind)
 
 				// Override Stub get calls to include a service account
 				// but none BuildStrategy
@@ -736,85 +580,56 @@ var _ = Describe("Reconcile BuildRun", func() {
 					ctl.DefaultServiceAccount(saName)),
 				)
 
-				// Stub that asserts the BuildRun status fields when
-				// Status updates for a BuildRun take place
-				statusCall := ctl.StubBuildRunStatus(
-					"unknown strategy foobar",
-					emptyTaskRunName,
-					build.Condition{
-						Type:   build.Succeeded,
-						Reason: "UnknownStrategyKind",
-						Status: corev1.ConditionFalse,
-					},
-					corev1.ConditionFalse,
-					buildSample.Spec,
-					true,
-				)
-				statusWriter.UpdateCalls(statusCall)
-
-				// we mark the BuildRun as Failed and do not reconcile again
 				_, err := reconciler.Reconcile(buildRunRequest)
-				Expect(err).ToNot(HaveOccurred())
-				Expect(client.GetCallCount()).To(Equal(4))
-				Expect(client.StatusCallCount()).To(Equal(2))
+				Expect(err).To(HaveOccurred())
+				Expect(err.Error()).To(ContainSubstring(" Unsupported BuildStrategy Kind"))
 			})
 
-			It("defaults to a namespaced strategy if strategy kind is not set", func() {
-				// use a Build object that does not defines the strategy Kind field
-				buildSample = ctl.BuildWithoutStrategyKind(buildName, strategyName)
+			It("only generates the service account once if the taskRun cannot be created", func() {
+				// override the Build to use a cluster BuildStrategy
+				buildSample = ctl.DefaultBuild(buildName, strategyName, build.ClusterBuildStrategyKind)
 
-				// Override Stub get calls to include
-				// a Build, a BuildRun, a SA and the default namespaced strategy
-				client.GetCalls(ctl.StubBuildRunGetWithSAandStrategies(
-					buildSample,
-					buildRunSample,
-					ctl.DefaultServiceAccount(saName),
-					nil,
-					ctl.DefaultNamespacedBuildStrategy()), // See how we include a namespaced strategy
-				)
+				// override buildrun to use a generated service account
+				buildRunName = "foobar-buildrun-sa-generate"
+				buildRunSample = ctl.BuildRunWithSAGenerate(buildRunName, buildName)
+				buildRunSample.Labels = make(map[string]string)
+				buildRunSample.Labels[build.LabelBuild] = buildName
+				buildRunSample.Labels[build.LabelBuildGeneration] = strconv.FormatInt(buildSample.Generation, 10)
 
-				// We do not expect an error because all resources are in place
+				// Override stub calls to include only build and buildrun
+				client.GetCalls(ctl.StubBuildRunGetWithoutSA(buildSample, buildRunSample))
+
+				// Call the reconciler
 				_, err := reconciler.Reconcile(buildRunRequest)
-				Expect(err).ToNot(HaveOccurred())
-				Expect(client.GetCallCount()).To(Equal(5))
-				Expect(client.StatusCallCount()).To(Equal(2))
-			})
 
-			It("should fail when strategy kind is not specied, because the namespaced strategy is not found", func() {
-				// use a Build object that does not defines the strategy Kind field
-				buildSample = ctl.BuildWithoutStrategyKind(buildName, strategyName)
+				// Expect an error stating that the strategy does not exist
+				Expect(err).To(HaveOccurred())
+				Expect(err.Error()).To(ContainSubstring(fmt.Sprintf(" \"%s\" not found", strategyName)))
 
-				// Override Stub get calls to include
-				// a Build, a BuildRun and a SA
-				client.GetCalls(ctl.StubBuildRunGetWithSAandStrategies(
-					buildSample,
-					buildRunSample,
-					ctl.DefaultServiceAccount(saName),
-					nil,
-					nil), // See how we do NOT include a namespaced strategy
-				)
+				// Expect one create call (service account)
+				Expect(client.CreateCallCount()).To(Equal(1))
+				_, obj, _ := client.CreateArgsForCall(0)
+				serviceAccount, castSuccessful := obj.(*corev1.ServiceAccount)
+				Expect(castSuccessful).To(BeTrue())
 
-				// Stub that asserts the BuildRun status fields when
-				// Status updates for a BuildRun take place
-				statusWriter.UpdateCalls(ctl.StubBuildRunStatus(
-					" \"foobar-strategy\" not found",
-					emptyTaskRunName,
-					build.Condition{
-						Type:   build.Succeeded,
-						Reason: "BuildStrategyNotFound",
-						Status: corev1.ConditionFalse,
-					},
-					corev1.ConditionFalse,
-					buildSample.Spec,
-					true,
-				))
+				// Expect zero update calls
+				Expect(client.UpdateCallCount()).To(Equal(0))
 
-				// We do not expect an error because we fail the BuildRun,
-				// update its Status.Condition and stop reconciling
-				_, err := reconciler.Reconcile(buildRunRequest)
-				Expect(err).ToNot(HaveOccurred())
-				Expect(client.GetCallCount()).To(Equal(5))
-				Expect(client.StatusCallCount()).To(Equal(2))
+				// Change the Get stub to also return the service account
+				client.GetCalls(ctl.StubBuildRunGetWithSA(buildSample, buildRunSample, serviceAccount))
+
+				// Call the reconciler again
+				_, err = reconciler.Reconcile(buildRunRequest)
+
+				// Expect an error stating that the strategy does not exist
+				Expect(err).To(HaveOccurred())
+				Expect(err.Error()).To(ContainSubstring(fmt.Sprintf(" \"%s\" not found", strategyName)))
+
+				// Expect no more create call because service account already existed
+				Expect(client.CreateCallCount()).To(Equal(1))
+
+				// Expect zero update calls because service account already existed and did not need to be modified
+				Expect(client.UpdateCallCount()).To(Equal(0))
 			})
 
 			It("fails on a TaskRun creation due to owner references errors", func() {
@@ -831,32 +646,14 @@ var _ = Describe("Reconcile BuildRun", func() {
 					ctl.DefaultNamespacedBuildStrategy()),
 				)
 
-				// Stub that asserts the BuildRun status fields when
-				// Status updates for a BuildRun take place
-				statusCall := ctl.StubBuildRunStatus(
-					"foobar error",
-					emptyTaskRunName,
-					build.Condition{
-						Type:   build.Succeeded,
-						Reason: "SetOwnerReferenceFailed",
-						Status: corev1.ConditionFalse,
-					},
-					corev1.ConditionFalse,
-					buildSample.Spec,
-					true,
-				)
-				statusWriter.UpdateCalls(statusCall)
-
 				testCtx := ctxlog.NewContext(context.TODO(), "fake-logger")
 				reconciler = buildrunctl.NewReconciler(testCtx, config.NewDefaultConfig(), manager,
 					func(owner, object metav1.Object, scheme *runtime.Scheme) error {
 						return fmt.Errorf("foobar error")
 					})
-
-				// we mark the BuildRun as Failed and do not reconcile again
 				_, err := reconciler.Reconcile(buildRunRequest)
-				Expect(err).ToNot(HaveOccurred())
-				Expect(client.StatusCallCount()).To(Equal(2))
+				Expect(err).To(HaveOccurred())
+				Expect(err.Error()).To(ContainSubstring("errors: foobar error"))
 			})
 
 			It("succeeds creating a TaskRun from a namespaced buildstrategy", func() {
@@ -930,26 +727,9 @@ var _ = Describe("Reconcile BuildRun", func() {
 				}
 
 				client.GetCalls(getClientStub)
-
-				// Stub that asserts the BuildRun status fields when
-				// Status updates for a BuildRun take place
-				statusCall := ctl.StubBuildRunStatus(
-					fmt.Sprintf("the Build is not registered correctly, build: %s, registered status: False, reason: something bad happened", buildName),
-					emptyTaskRunName,
-					build.Condition{
-						Type:   build.Succeeded,
-						Reason: "BuildRegistrationFailed",
-						Status: corev1.ConditionFalse,
-					},
-					corev1.ConditionFalse,
-					buildSample.Spec,
-					true,
-				)
-				statusWriter.UpdateCalls(statusCall)
-
-				// we mark the BuildRun as Failed and do not reconcile again
 				_, err := reconciler.Reconcile(buildRunRequest)
-				Expect(err).ToNot(HaveOccurred())
+				Expect(err).To(HaveOccurred())
+				Expect(err.Error()).To(ContainSubstring("reason: something bad happened"))
 				Expect(client.StatusCallCount()).To(Equal(1))
 			})
 
@@ -1088,35 +868,6 @@ var _ = Describe("Reconcile BuildRun", func() {
 				_, err := reconciler.Reconcile(buildRunRequest)
 				Expect(err).ToNot(HaveOccurred())
 			})
-
-			It("should return an error and stop reconciling if buildstrategy is not found", func() {
-				buildRunSample = ctl.BuildRunWithoutSA(buildRunName, buildName)
-				buildSample = ctl.BuildWithBuildRunDeletions(buildName, strategyName, build.ClusterBuildStrategyKind)
-
-				// Override Stub get calls to include a service account
-				// but none BuildStrategy
-				client.GetCalls(ctl.StubBuildRunGetWithSA(
-					buildSample,
-					buildRunSample,
-					ctl.DefaultServiceAccount(saName)),
-				)
-
-				statusWriter.UpdateCalls(func(_ context.Context, object runtime.Object, _ ...crc.UpdateOption) error {
-					switch buildRun := object.(type) {
-					case *build.BuildRun:
-						if buildRun.Status.IsFailed(build.Succeeded) {
-							return fmt.Errorf("failed miserably")
-						}
-					}
-					return nil
-				})
-
-				_, err := reconciler.Reconcile(buildRunRequest)
-				// we expect an error because a Client.Status Update failed and we expect another reconciliation
-				// to take place
-				Expect(err).ToNot(BeNil())
-				Expect(resources.IsClientStatusUpdateError(err)).To(BeTrue())
-			})
 		})
 	})
 })
diff --git a/pkg/reconciler/buildrun/resources/build_test.go b/pkg/reconciler/buildrun/resources/build_test.go
index 10ada2bf..3b076c17 100644
--- a/pkg/reconciler/buildrun/resources/build_test.go
+++ b/pkg/reconciler/buildrun/resources/build_test.go
@@ -33,19 +33,6 @@ var _ = Describe("Build Resource", func() {
 		// init vars
 		buildName = "foobuild"
 		client = &fakes.FakeClient{}
-		buildRun := &build.BuildRun{
-			ObjectMeta: metav1.ObjectMeta{
-				Name:      "foo",
-				Namespace: "bar",
-			},
-			Spec: build.BuildRunSpec{
-				// buildRef is a mandatory field,
-				// therefore we can assume is always present
-				BuildRef: &build.BuildRef{
-					Name: buildName,
-				},
-			},
-		}
 
 		It("should be able to retrieve a build object if exists", func() {
 			buildSample := ctl.DefaultBuild(buildName, "foostrategy", build.ClusterBuildStrategyKind)
@@ -63,8 +50,8 @@ var _ = Describe("Build Resource", func() {
 			// fake the calls with the above stub definition
 			client.GetCalls(getClientStub)
 
-			buildObject := &build.Build{}
-			Expect(resources.GetBuildObject(context.TODO(), client, buildRun, buildObject)).To(BeNil())
+			build := &build.Build{}
+			Expect(resources.GetBuildObject(context.TODO(), client, buildName, "default", build)).To(BeNil())
 		})
 		It("should not retrieve a missing build object when missing", func() {
 			// stub a GET API call with buildSample contents that returns "not found"
@@ -79,7 +66,7 @@ var _ = Describe("Build Resource", func() {
 			client.GetCalls(getClientStub)
 
 			build := &build.Build{}
-			Expect(resources.GetBuildObject(context.TODO(), client, buildRun, build)).ToNot(BeNil())
+			Expect(resources.GetBuildObject(context.TODO(), client, buildName, "default", build)).ToNot(BeNil())
 		})
 		It("should be able to verify valid ownerships", func() {
 			managingController := true
diff --git a/pkg/reconciler/buildrun/resources/errors_test.go b/pkg/reconciler/buildrun/resources/errors_test.go
index 15833f21..c4be5db7 100644
--- a/pkg/reconciler/buildrun/resources/errors_test.go
+++ b/pkg/reconciler/buildrun/resources/errors_test.go
@@ -20,7 +20,7 @@ var _ = Describe("Multiple errors", func() {
 			error02 := errors.New("error02")
 			msg := "handling multiple errors"
 			customError := resources.HandleError(msg, error01, error02)
-			Expect(customError.Error()).To(Equal(fmt.Sprintf("errors: %s, %s, msg: %s", error01, error02, msg)))
+			Expect(customError).To(Equal(fmt.Errorf("errors: %s, %s, msg: %s", error01, error02, msg)))
 		})
 	})
 })
diff --git a/pkg/reconciler/buildrun/resources/service_accounts_test.go b/pkg/reconciler/buildrun/resources/service_accounts_test.go
index b8d858f7..b9154f1f 100644
--- a/pkg/reconciler/buildrun/resources/service_accounts_test.go
+++ b/pkg/reconciler/buildrun/resources/service_accounts_test.go
@@ -6,11 +6,9 @@ package resources_test
 
 import (
 	"context"
-	"fmt"
 
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
-	buildv1alpha1 "github.com/shipwright-io/build/pkg/apis/build/v1alpha1"
 	"github.com/shipwright-io/build/pkg/controller/fakes"
 	"github.com/shipwright-io/build/pkg/reconciler/buildrun/resources"
 	"github.com/shipwright-io/build/test"
@@ -19,7 +17,6 @@ import (
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/apimachinery/pkg/types"
-	crc "sigs.k8s.io/controller-runtime/pkg/client"
 )
 
 var _ = Describe("Operating service accounts", func() {
@@ -27,155 +24,38 @@ var _ = Describe("Operating service accounts", func() {
 		client                  *fakes.FakeClient
 		ctl                     test.Catalog
 		buildName, buildRunName string
-		buildRunSample          *buildv1alpha1.BuildRun
 	)
 
-	BeforeEach(func() {
+	Context("Retrieving service accounts", func() {
+
 		// init vars
 		buildName = "foobuild"
 		buildRunName = "foobuildrun"
 		client = &fakes.FakeClient{}
-		buildRunSample = ctl.DefaultBuildRun(buildRunName, buildName)
-	})
-
-	// stub client GET calls and return a initialized sa when asking for a sa
-	var generateGetSAStub = func(saName string) func(context context.Context, nn types.NamespacedName, object runtime.Object) error {
-		return func(context context.Context, nn types.NamespacedName, object runtime.Object) error {
-			switch object := object.(type) {
-			case *corev1.ServiceAccount:
-				ctl.DefaultServiceAccount(saName).DeepCopyInto(object)
-				return nil
-			}
-			return k8serrors.NewNotFound(schema.GroupResource{}, nn.Name)
-		}
-	}
+		buildRunSample := ctl.DefaultBuildRun(buildRunName, buildName)
 
-	// stub client GET calls and return an error when asking for a service account
-	var generateGetSAStubWithError = func(customError error) func(context context.Context, nn types.NamespacedName, object runtime.Object) error {
-		return func(context context.Context, nn types.NamespacedName, object runtime.Object) error {
-			switch object.(type) {
-			case *corev1.ServiceAccount:
-				return customError
-			}
-			return k8serrors.NewNotFound(schema.GroupResource{}, nn.Name)
-		}
-	}
-
-	Context("Retrieving specified service accounts", func() {
-
-		It("should return a modified sa with a secret reference", func() {
-			buildRunSample := ctl.BuildRunWithSA(buildRunName, buildName, "foobarsa")
+		It("should return a modified one with a secret ref", func() {
 
 			// stub a GET API call for a service account
-			client.GetCalls(generateGetSAStub("foobarsa"))
-
-			sa, err := resources.RetrieveServiceAccount(context.TODO(), client, ctl.BuildWithOutputSecret(buildName, "default", "foosecret"), buildRunSample)
-			Expect(err).To(BeNil())
-			Expect(len(sa.Secrets)).To(Equal(1))
-			Expect(sa.Secrets[0].Name).To(Equal("foosecret"))
-		})
-		It("should return a namespace default sa with a secret reference", func() {
-			buildRunSample := ctl.BuildRunWithoutSA(buildRunName, buildName)
-
-			// stub a GET API call for a service account
-			client.GetCalls(generateGetSAStub("default"))
+			getClientStub := func(context context.Context, nn types.NamespacedName, object runtime.Object) error {
+				switch object := object.(type) {
+				case *corev1.ServiceAccount:
+					ctl.DefaultServiceAccount("foobar").DeepCopyInto(object)
+					return nil
+				}
+				return k8serrors.NewNotFound(schema.GroupResource{}, nn.Name)
+			}
+			// fake the calls with the above stub
+			client.GetCalls(getClientStub)
 
 			sa, err := resources.RetrieveServiceAccount(context.TODO(), client, ctl.BuildWithOutputSecret(buildName, "default", "foosecret"), buildRunSample)
 			Expect(err).To(BeNil())
+			// assert the build output secret is defined in the default SA
 			Expect(len(sa.Secrets)).To(Equal(1))
-			Expect(sa.Secrets[0].Name).To(Equal("foosecret"))
-		})
-
-		It("should return an error if the specified sa is not found", func() {
-			buildRunSample := ctl.BuildRunWithSA(buildRunName, buildName, "foobarsa")
-
-			client.GetCalls(generateGetSAStubWithError(k8serrors.NewNotFound(schema.GroupResource{}, "")))
-
-			client.StatusCalls(func() crc.StatusWriter {
-				statusWriter := &fakes.FakeStatusWriter{}
-				statusWriter.UpdateCalls(func(ctx context.Context, object runtime.Object, _ ...crc.UpdateOption) error {
-					return nil
-				})
-				return statusWriter
-			})
-
-			sa, err := resources.RetrieveServiceAccount(context.TODO(), client, ctl.BuildWithOutputSecret(buildName, "default", "foosecret"), buildRunSample)
-			Expect(sa).To(BeNil())
-			Expect(err).ToNot(BeNil())
-			Expect(k8serrors.IsNotFound(err)).To(BeTrue())
 		})
 
-		It("should return multiple errors if the specified sa is not found and the condition update is not working", func() {
-			buildRunSample := ctl.BuildRunWithSA(buildRunName, buildName, "foobarsa")
-
-			client.GetCalls(generateGetSAStubWithError(k8serrors.NewNotFound(schema.GroupResource{}, "")))
-
-			client.StatusCalls(func() crc.StatusWriter {
-				statusWriter := &fakes.FakeStatusWriter{}
-				statusWriter.UpdateCalls(func(ctx context.Context, object runtime.Object, _ ...crc.UpdateOption) error {
-					switch object.(type) {
-					case *buildv1alpha1.BuildRun:
-						return fmt.Errorf("failed")
-					}
-					return nil
-				})
-				return statusWriter
-			})
-
-			sa, err := resources.RetrieveServiceAccount(context.TODO(), client, ctl.BuildWithOutputSecret(buildName, "default", "foosecret"), buildRunSample)
-			Expect(sa).To(BeNil())
-			Expect(err).ToNot(BeNil())
-			Expect(resources.IsClientStatusUpdateError(err)).To(BeTrue())
-		})
-	})
-
-	Context("Retrieving autogenerated service accounts when the spec.serviceAccount.generate key is used", func() {
-
 		It("should provide a generated sa name", func() {
 			Expect(resources.GetGeneratedServiceAccountName(buildRunSample)).To(Equal(buildRunSample.Name + "-sa"))
 		})
-		It("should return a generated sa with a label, ownerreference and a ref secret if it does not exists", func() {
-			buildRunSample := ctl.BuildRunWithSAGenerate(buildRunName, buildName)
-
-			// stub a GET API call for a service account
-			client.GetCalls(generateGetSAStubWithError(k8serrors.NewNotFound(schema.GroupResource{}, "foobar")))
-
-			mountTokenVal := false
-
-			client.CreateCalls(func(context context.Context, object runtime.Object, _ ...crc.CreateOption) error {
-				switch object := object.(type) {
-				case *corev1.ServiceAccount:
-					Expect(len(object.Secrets)).To(Equal(1))
-					Expect(len(object.OwnerReferences)).To(Equal(1))
-					Expect(object.Labels[buildv1alpha1.LabelBuildRun]).To(Equal(buildRunName))
-					Expect(object.Secrets[0].Name).To(Equal("foosecret"))
-					Expect(object.AutomountServiceAccountToken).To(Equal(&mountTokenVal))
-				}
-				return nil
-			})
-
-			_, err := resources.RetrieveServiceAccount(context.TODO(), client, ctl.BuildWithOutputSecret(buildName, "default", "foosecret"), buildRunSample)
-			Expect(err).To(BeNil())
-
-		})
-		It("should return an existing sa and not generate it again if already exists", func() {
-			buildRunSample := ctl.BuildRunWithSAGenerate(buildRunName, buildName)
-
-			// stub a GET API call for a service account
-			client.GetCalls(generateGetSAStub(buildRunName + "-sa"))
-
-			_, err := resources.RetrieveServiceAccount(context.TODO(), client, ctl.BuildWithOutputSecret(buildName, "default", "foosecret"), buildRunSample)
-			Expect(err).To(BeNil())
-		})
-		It("should return an error if the sa automatic generation fails", func() {
-			buildRunSample := ctl.BuildRunWithSAGenerate(buildRunName, buildName)
-
-			// stub a GET API call for a service account
-			// fake the calls with the above stub
-			client.GetCalls(generateGetSAStubWithError(fmt.Errorf("something wrong happened")))
-
-			_, err := resources.RetrieveServiceAccount(context.TODO(), client, ctl.BuildWithOutputSecret(buildName, "default", "foosecret"), buildRunSample)
-			Expect(err).ToNot(BeNil())
-		})
 	})
 })
diff --git a/test/build_samples.go b/test/build_samples.go
index 0807a512..080464be 100644
--- a/test/build_samples.go
+++ b/test/build_samples.go
@@ -213,23 +213,6 @@ spec:
   timeout: 5s
 `
 
-// BuildCBSWithShortTimeOutAndRefOutputSecret defines a Build with a
-// ClusterBuildStrategy, a short timeout and an output secret
-const BuildCBSWithShortTimeOutAndRefOutputSecret = `
-apiVersion: shipwright.io/v1alpha1
-kind: Build
-spec:
-  source:
-    url: "https://github.com/shipwright-io/sample-go"
-  strategy:
-    kind: ClusterBuildStrategy
-  output:
-    image: image-registry.openshift-image-registry.svc:5000/example/buildpacks-app
-    credentials:
-      name: foobarsecret
-  timeout: 5s
-`
-
 // BuildCBSWithWrongURL defines a Build with a
 // ClusterBuildStrategy and a non-existing url
 const BuildCBSWithWrongURL = `
diff --git a/test/catalog.go b/test/catalog.go
index 1766380c..e6c25055 100644
--- a/test/catalog.go
+++ b/test/catalog.go
@@ -412,30 +412,20 @@ func (c *Catalog) StubBuildRunGetWithSAandStrategies(
 	return func(context context.Context, nn types.NamespacedName, object runtime.Object) error {
 		switch object := object.(type) {
 		case *build.Build:
-			if b != nil {
-				b.DeepCopyInto(object)
-				return nil
-			}
+			b.DeepCopyInto(object)
+			return nil
 		case *build.BuildRun:
-			if br != nil {
-				br.DeepCopyInto(object)
-				return nil
-			}
+			br.DeepCopyInto(object)
+			return nil
 		case *corev1.ServiceAccount:
-			if sa != nil {
-				sa.DeepCopyInto(object)
-				return nil
-			}
+			sa.DeepCopyInto(object)
+			return nil
 		case *build.ClusterBuildStrategy:
-			if cb != nil {
-				cb.DeepCopyInto(object)
-				return nil
-			}
+			cb.DeepCopyInto(object)
+			return nil
 		case *build.BuildStrategy:
-			if bs != nil {
-				bs.DeepCopyInto(object)
-				return nil
-			}
+			bs.DeepCopyInto(object)
+			return nil
 		}
 		return errors.NewNotFound(schema.GroupResource{}, nn.Name)
 	}
@@ -624,23 +614,6 @@ func (c *Catalog) DefaultBuild(buildName string, strategyName string, strategyKi
 	}
 }
 
-// BuildWithoutStrategyKind returns a minimal Build object without an strategy kind definition
-func (c *Catalog) BuildWithoutStrategyKind(buildName string, strategyName string) *build.Build {
-	return &build.Build{
-		ObjectMeta: metav1.ObjectMeta{
-			Name: buildName,
-		},
-		Spec: build.BuildSpec{
-			StrategyRef: &build.StrategyRef{
-				Name: strategyName,
-			},
-		},
-		Status: build.BuildStatus{
-			Registered: corev1.ConditionTrue,
-		},
-	}
-}
-
 // BuildWithBuildRunDeletions returns a minimal Build object with the
 // build.shipwright.io/build-run-deletion annotation set to true
 func (c *Catalog) BuildWithBuildRunDeletions(buildName string, strategyName string, strategyKind build.BuildStrategyKind) *build.Build {
@@ -892,7 +865,6 @@ func (c *Catalog) BuildRunWithSA(buildRunName string, buildName string, saName s
 				Generate: false,
 			},
 		},
-		Status: build.BuildRunStatus{},
 	}
 }
 
diff --git a/test/integration/build_to_buildruns_test.go b/test/integration/build_to_buildruns_test.go
index a0904d35..9b09604f 100644
--- a/test/integration/build_to_buildruns_test.go
+++ b/test/integration/build_to_buildruns_test.go
@@ -232,10 +232,10 @@ var _ = Describe("Integration tests Build and BuildRuns", func() {
 
 			br, err := tb.GetBR(buildRunObject.Name)
 			Expect(err).To(BeNil())
-			Expect(br.Status.Reason).To(Equal(fmt.Sprintf("build.shipwright.io \"%s\" not found", BUILD+tb.Namespace)))
+			Expect(br.Status.Reason).To(Equal(fmt.Sprintf("Build.shipwright.io \"%s\" not found", BUILD+tb.Namespace)))
 			Expect(br.Status.StartTime).To(BeNil())
 			Expect(br.Status.GetCondition(v1alpha1.Succeeded).Status).To(Equal(corev1.ConditionFalse))
-			Expect(br.Status.GetCondition(v1alpha1.Succeeded).Reason).To(Equal("BuildNotFound"))
+			Expect(br.Status.GetCondition(v1alpha1.Succeeded).Reason).To(Equal("Failed"))
 			Expect(br.Status.GetCondition(v1alpha1.Succeeded).Message).To(ContainSubstring("not found"))
 
 		})
@@ -262,7 +262,7 @@ var _ = Describe("Integration tests Build and BuildRuns", func() {
 
 			Expect(br.Status.Reason).To(Equal(fmt.Sprintf("the Build is not registered correctly, build: %s, registered status: False, reason: SpecOutputSecretRefNotFound", BUILD+tb.Namespace)))
 			Expect(br.Status.GetCondition(v1alpha1.Succeeded).Status).To(Equal(corev1.ConditionFalse))
-			Expect(br.Status.GetCondition(v1alpha1.Succeeded).Reason).To(Equal("BuildRegistrationFailed"))
+			Expect(br.Status.GetCondition(v1alpha1.Succeeded).Reason).To(Equal("Failed"))
 			Expect(br.Status.GetCondition(v1alpha1.Succeeded).Message).To(ContainSubstring("Build is not registered correctly"))
 		})
 	})
@@ -293,9 +293,9 @@ var _ = Describe("Integration tests Build and BuildRuns", func() {
 			Expect(err).To(BeNil())
 			Expect(br.Status.CompletionTime).ToNot(BeNil())
 			Expect(br.Status.StartTime).To(BeNil())
-			Expect(br.Status.Reason).To(Equal(fmt.Sprintf("build.shipwright.io \"%s\" not found", BUILD+tb.Namespace+"foobar")))
+			Expect(br.Status.Reason).To(Equal(fmt.Sprintf("Build.shipwright.io \"%s\" not found", BUILD+tb.Namespace+"foobar")))
 			Expect(br.Status.GetCondition(v1alpha1.Succeeded).Status).To(Equal(corev1.ConditionFalse))
-			Expect(br.Status.GetCondition(v1alpha1.Succeeded).Reason).To(Equal("BuildNotFound"))
+			Expect(br.Status.GetCondition(v1alpha1.Succeeded).Reason).To(Equal("Failed"))
 			Expect(br.Status.GetCondition(v1alpha1.Succeeded).Message).To(ContainSubstring("not found"))
 		})
 	})
diff --git a/test/integration/build_to_secrets_test.go b/test/integration/build_to_secrets_test.go
index 396fc524..822f3be2 100644
--- a/test/integration/build_to_secrets_test.go
+++ b/test/integration/build_to_secrets_test.go
@@ -309,7 +309,7 @@ var _ = Describe("Integration tests Build and referenced Secrets", func() {
 			buildObject, err = tb.GetBuildTillRegistration(buildName, corev1.ConditionFalse)
 			Expect(err).To(BeNil())
 			Expect(buildObject.Status.Registered).To(Equal(corev1.ConditionFalse))
-			Expect(buildObject.Status.Reason).To(Equal(v1alpha1.SpecBuilderSecretRefNotFound))
+			Expect(buildObject.Status.Reason).To(Equal(v1alpha1.SpecRuntimeSecretRefNotFound))
 			Expect(buildObject.Status.Message).To(Equal(fmt.Sprintf("referenced secret %s not found", buildObject.Spec.BuilderImage.SecretRef.Name)))
 
 		})
@@ -330,7 +330,7 @@ var _ = Describe("Integration tests Build and referenced Secrets", func() {
 			buildObject, err := tb.GetBuildTillValidation(buildName)
 			Expect(err).To(BeNil())
 			Expect(buildObject.Status.Registered).To(Equal(corev1.ConditionFalse))
-			Expect(buildObject.Status.Reason).To(Equal(v1alpha1.SpecBuilderSecretRefNotFound))
+			Expect(buildObject.Status.Reason).To(Equal(v1alpha1.SpecRuntimeSecretRefNotFound))
 			Expect(buildObject.Status.Message).To(Equal(fmt.Sprintf("referenced secret %s not found", buildObject.Spec.BuilderImage.SecretRef.Name)))
 
 			sampleSecret := tb.Catalog.SecretWithAnnotation(buildObject.Spec.BuilderImage.SecretRef.Name, buildObject.Namespace)
diff --git a/test/integration/buildruns_to_sa_test.go b/test/integration/buildruns_to_sa_test.go
index 0c04f133..b2eb5df1 100644
--- a/test/integration/buildruns_to_sa_test.go
+++ b/test/integration/buildruns_to_sa_test.go
@@ -7,9 +7,10 @@ package integration_test
 import (
 	"fmt"
 
+	corev1 "k8s.io/api/core/v1"
+
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
-	corev1 "k8s.io/api/core/v1"
 
 	"github.com/shipwright-io/build/pkg/apis/build/v1alpha1"
 	"github.com/shipwright-io/build/test"
@@ -63,26 +64,12 @@ var _ = Describe("Integration tests BuildRuns and Service-accounts", func() {
 	Context("when a buildrun is created with autogenerated service-account", func() {
 
 		BeforeEach(func() {
-			buildSample = []byte(test.BuildCBSWithShortTimeOutAndRefOutputSecret)
+			buildSample = []byte(test.BuildCBSWithShortTimeOut)
 			buildRunSample = []byte(test.MinimalBuildRunWithSAGeneration)
 		})
 
 		It("creates a new service-account and deletes it after the build is terminated", func() {
 
-			// loop and find a match
-			var contains = func(secretList []corev1.ObjectReference, secretName string) bool {
-				for _, s := range secretList {
-					if s.Name == secretName {
-						return true
-					}
-				}
-				return false
-			}
-
-			sampleSecret := tb.Catalog.SecretWithAnnotation(buildObject.Spec.Output.SecretRef.Name, buildObject.Namespace)
-
-			Expect(tb.CreateSecret(sampleSecret)).To(BeNil())
-
 			Expect(tb.CreateBuild(buildObject)).To(BeNil())
 
 			buildObject, err = tb.GetBuildTillValidation(buildObject.Name)
@@ -93,12 +80,9 @@ var _ = Describe("Integration tests BuildRuns and Service-accounts", func() {
 			_, err = tb.GetBRTillStartTime(buildRunObject.Name)
 			Expect(err).To(BeNil())
 
-			sa, err := tb.GetSA(fmt.Sprintf("%s-sa", buildRunObject.Name))
+			_, err = tb.GetSA(fmt.Sprintf("%s-sa", buildRunObject.Name))
 			Expect(err).To(BeNil())
 
-			// Verify that the sa have our Build specified secret
-			Expect(contains(sa.Secrets, buildObject.Spec.Output.SecretRef.Name)).To(BeTrue())
-
 			_, err = tb.GetBRTillCompletion(buildRunObject.Name)
 			Expect(err).To(BeNil())
 
@@ -168,13 +152,12 @@ var _ = Describe("Integration tests BuildRuns and Service-accounts", func() {
 
 			Expect(tb.CreateBR(buildRunObject)).To(BeNil())
 
-			br, _ := tb.GetBRTillCompletion(buildRunObject.Name)
+			br, err := tb.GetBRTillCompletion(buildRunObject.Name)
 			Expect(err).To(BeNil())
 			buildRunCondition := br.Status.GetCondition(v1alpha1.Succeeded)
-
 			Expect(buildRunCondition).ToNot(BeNil())
 			Expect(buildRunCondition.Status).To(Equal(corev1.ConditionFalse))
-			Expect(buildRunCondition.Reason).To(Equal("ServiceAccountNotFound"))
+			Expect(buildRunCondition.Reason).To(Equal("Failed"))
 			Expect(buildRunCondition.Message).To(ContainSubstring("not found"))
 		})
 	})