diff --git a/pkg/apis/build/v1alpha1/build_pod.go b/pkg/apis/build/v1alpha1/build_pod.go index b7a9a68b2..4d43c08c9 100644 --- a/pkg/apis/build/v1alpha1/build_pod.go +++ b/pkg/apis/build/v1alpha1/build_pod.go @@ -207,7 +207,7 @@ func (b *Build) BuildPod(config BuildPodImages, secrets []corev1.Secret, bc Buil "-analyzed=/layers/analyzed.toml", "-cache-dir=/cache", func() string { - if b.Spec.LastBuild != nil { + if b.Spec.LastBuild != nil && b.Spec.LastBuild.Image != "" { return b.Spec.LastBuild.Image } return b.Tag() diff --git a/pkg/apis/build/v1alpha1/build_pod_test.go b/pkg/apis/build/v1alpha1/build_pod_test.go index fe99209ac..28dfdb081 100644 --- a/pkg/apis/build/v1alpha1/build_pod_test.go +++ b/pkg/apis/build/v1alpha1/build_pod_test.go @@ -467,6 +467,15 @@ func testBuildPod(t *testing.T, when spec.G, it spec.S) { }, pod.Spec.InitContainers[2].Args) }) + it("configures analyze step with the current tag if previous build is corrupted", func() { + build.Spec.LastBuild = &v1alpha1.LastBuild{} + + pod, err := build.BuildPod(config, secrets, buildPodBuilderConfig) + require.NoError(t, err) + + assert.Contains(t, pod.Spec.InitContainers[2].Args, build.Tag()) + }) + it("configures restore step", func() { pod, err := build.BuildPod(config, secrets, buildPodBuilderConfig) require.NoError(t, err) diff --git a/pkg/apis/build/v1alpha1/image_builds.go b/pkg/apis/build/v1alpha1/image_builds.go index 681b0b01c..f1245a760 100644 --- a/pkg/apis/build/v1alpha1/image_builds.go +++ b/pkg/apis/build/v1alpha1/image_builds.go @@ -100,6 +100,10 @@ func lastBuild(latestBuild *Build) *LastBuild { return nil } + if latestBuild.IsFailure() { + return latestBuild.Spec.LastBuild + } + return &LastBuild{ Image: latestBuild.BuiltImage(), StackId: latestBuild.Stack(), diff --git a/pkg/reconciler/v1alpha1/image/image_test.go b/pkg/reconciler/v1alpha1/image/image_test.go index 2f5f30d3b..d953d0ecd 100644 --- a/pkg/reconciler/v1alpha1/image/image_test.go +++ b/pkg/reconciler/v1alpha1/image/image_test.go @@ -1448,6 +1448,116 @@ func testImageReconciler(t *testing.T, when spec.G, it spec.S) { }) }) + it("schedules a build with previous build's LastBuild if the last build failed", func() { + image.Status.BuildCounter = 2 + image.Status.LatestBuildRef = "image-name-build200001" + + sourceResolver := resolvedSourceResolver(image) + rt.Test(rtesting.TableRow{ + Key: key, + Objects: []runtime.Object{ + image, + builder, + sourceResolver, + &v1alpha1.Build{ + ObjectMeta: metav1.ObjectMeta{ + Name: "image-name-build-1-00001", + Namespace: namespace, + OwnerReferences: []metav1.OwnerReference{ + *kmeta.NewControllerRef(image), + }, + Labels: map[string]string{ + v1alpha1.BuildNumberLabel: "2", + v1alpha1.ImageLabel: imageName, + }, + }, + Spec: v1alpha1.BuildSpec{ + Tags: []string{image.Spec.Tag}, + Builder: v1alpha1.BuildBuilderSpec{ + Image: builder.Status.LatestImage, + ImagePullSecrets: builder.Spec.ImagePullSecrets, + }, + ServiceAccount: "old-service-account", + Source: v1alpha1.SourceConfig{ + Git: &v1alpha1.Git{ + URL: "out-of-date-git-url", + Revision: "out-of-date-git-revision", + }, + }, + LastBuild: &v1alpha1.LastBuild{ + Image: image.Spec.Tag + "@sha256:from-build-before-this-build", + StackId: "io.buildpacks.stacks.bionic", + }, + }, + Status: v1alpha1.BuildStatus{ + Status: corev1alpha1.Status{ + Conditions: corev1alpha1.Conditions{ + { + Type: corev1alpha1.ConditionSucceeded, + Status: corev1.ConditionFalse, + }, + }, + }, + }, + }, + }, + WantErr: false, + WantCreates: []runtime.Object{ + &v1alpha1.Build{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: imageName + "-build-3-", + Namespace: namespace, + OwnerReferences: []metav1.OwnerReference{ + *kmeta.NewControllerRef(image), + }, + Labels: map[string]string{ + v1alpha1.BuildNumberLabel: "3", + v1alpha1.ImageLabel: imageName, + someLabelKey: someValueToPassThrough, + }, + Annotations: map[string]string{ + v1alpha1.BuildReasonAnnotation: strings.Join([]string{v1alpha1.BuildReasonConfig, v1alpha1.BuildReasonCommit}, ","), + }, + }, + Spec: v1alpha1.BuildSpec{ + Tags: []string{image.Spec.Tag}, + Builder: v1alpha1.BuildBuilderSpec{ + Image: builder.Status.LatestImage, + ImagePullSecrets: builder.Spec.ImagePullSecrets, + }, + ServiceAccount: image.Spec.ServiceAccount, + Source: v1alpha1.SourceConfig{ + Git: &v1alpha1.Git{ + URL: sourceResolver.Status.Source.Git.URL, + Revision: sourceResolver.Status.Source.Git.Revision, + }, + }, + LastBuild: &v1alpha1.LastBuild{ + Image: "some/image@sha256:from-build-before-this-build", + StackId: "io.buildpacks.stacks.bionic", + }, + }, + }, + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{ + { + Object: &v1alpha1.Image{ + ObjectMeta: image.ObjectMeta, + Spec: image.Spec, + Status: v1alpha1.ImageStatus{ + Status: corev1alpha1.Status{ + ObservedGeneration: originalGeneration, + Conditions: conditionReadyUnknown(), + }, + LatestBuildRef: "image-name-build-3-00001", // GenerateNameReactor + BuildCounter: 3, + }, + }, + }, + }, + }) + }) + it("does not schedule a build if the previous build is running", func() { image.Generation = 2 image.Status.BuildCounter = 1