package main import ( "context" "errors" "reflect" "slices" "testing" "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/dynamic" ) type admitClient struct { dynamic.Interface before func(*unstructured.Unstructured) afterList func() } type admitScope struct { dynamic.NamespaceableResourceInterface before func(*unstructured.Unstructured) afterList func() } type admitResource struct { dynamic.ResourceInterface before func(*unstructured.Unstructured) afterList func() } func (c admitClient) Resource(gvr schema.GroupVersionResource) dynamic.NamespaceableResourceInterface { resource := c.Interface.Resource(gvr) if gvr == workflowGVR { return admitScope{NamespaceableResourceInterface: resource, before: c.before, afterList: c.afterList} } return resource } func (r admitScope) Namespace(namespace string) dynamic.ResourceInterface { return admitResource{ResourceInterface: r.NamespaceableResourceInterface.Namespace(namespace), before: r.before, afterList: r.afterList} } func (r admitResource) Create(ctx context.Context, object *unstructured.Unstructured, options metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error) { if r.before != nil { r.before(object) } return r.ResourceInterface.Create(ctx, object, options, subresources...) } func TestLateAdmission(t *testing.T) { ctx := context.Background() instance, template := bundleFixture(t) peer := *instance previous, err := peer.readyTemplate(ctx, "delivery", template.GetName()) if err != nil { t.Fatal(err) } old, err := peer.client.Resource(templateGVR).Namespace("delivery").Get(ctx, previous, metav1.GetOptions{}) if err != nil { t.Fatal(err) } published := "" instance.client = admitClient{Interface: peer.client, before: func(_ *unstructured.Unstructured) { changeImage(t, &peer, template.GetName(), "example.invalid/builder:v2") published, err = peer.readyTemplate(ctx, "delivery", template.GetName()) if err != nil { t.Fatal(err) } }} delivery, err := decodeProjectDelivery(continuousDelivery()) if err != nil { t.Fatal(err) } if err := instance.ensureWorkflow(ctx, &delivery, "late", template.GetName(), "build", nil, nil); err != nil { t.Fatal(err) } captured := boundTemplate(t, instance, "late") if !reflect.DeepEqual(old.Object["spec"], captured.Object["spec"]) { t.Fatal("captured content changed") } if captured.GetName() == published { t.Fatal("the schedule did not overlap two published revisions") } } func (r admitResource) List(ctx context.Context, options metav1.ListOptions) (*unstructured.UnstructuredList, error) { items, err := r.ResourceInterface.List(ctx, options) if err == nil && r.afterList != nil { r.afterList() } return items, err } func TestPublishOverlap(t *testing.T) { ctx := context.Background() instance, template := bundleFixture(t) peer := *instance base := peer.client previous, err := peer.readyTemplate(ctx, "delivery", template.GetName()) if err != nil { t.Fatal(err) } published := "" instance.client = admitClient{Interface: base, before: func(workflow *unstructured.Unstructured) { changeImage(t, &peer, template.GetName(), "example.invalid/builder:v2") peer.client = admitClient{Interface: base, afterList: func() { if _, err := base.Resource(workflowGVR).Namespace("delivery").Create(ctx, workflow.DeepCopy(), metav1.CreateOptions{}); err != nil { t.Fatal(err) } }} published, err = peer.readyTemplate(ctx, "delivery", template.GetName()) if err != nil { t.Fatal(err) } }} delivery, err := decodeProjectDelivery(continuousDelivery()) if err != nil { t.Fatal(err) } if err := instance.ensureWorkflow(ctx, &delivery, "late", template.GetName(), "build", nil, nil); err != nil { t.Fatal(err) } captured := boundTemplate(t, instance, "late") if captured.GetName() != previous { t.Fatal("execution lost its captured revision") } if published == previous { t.Fatal("the schedule did not publish during an in-flight admission") } } func TestQuietSameBundle(t *testing.T) { ctx := context.Background() instance, template := bundleFixture(t) now := instance.now() instance.now = func() time.Time { return now } instance.config.templateQuiet = time.Minute if err := unstructured.SetNestedField(template.Object, "nodeSelector: {}", "spec", "podSpecPatch"); err != nil { t.Fatal(err) } if _, err := instance.client.Resource(templateGVR).Namespace("delivery").Update(ctx, template, metav1.UpdateOptions{}); err != nil { t.Fatal(err) } if _, err := instance.readyTemplate(ctx, "delivery", template.GetName()); !errors.Is(err, templatePending) { t.Fatalf("initial observation = %v", err) } now = now.Add(time.Minute) previous, err := instance.readyTemplate(ctx, "delivery", template.GetName()) if err != nil { t.Fatal(err) } template, err = instance.client.Resource(templateGVR).Namespace("delivery").Get(ctx, template.GetName(), metav1.GetOptions{}) if err != nil { t.Fatal(err) } template.SetGeneration(template.GetGeneration() + 1) if err := unstructured.SetNestedField(template.Object, "{nodeSelector: {}}\n", "spec", "podSpecPatch"); err != nil { t.Fatal(err) } if _, err := instance.client.Resource(templateGVR).Namespace("delivery").Update(ctx, template, metav1.UpdateOptions{}); err != nil { t.Fatal(err) } bundle, err := instance.captureBundle(ctx, template) if err != nil { t.Fatal(err) } if bundle.name != previous { t.Fatal("equivalent patches changed captured revision") } published, err := instance.readyTemplate(ctx, "delivery", template.GetName()) if err != nil || published != previous { t.Fatalf("unchanged revision restarted quiet interval: published=%q error=%v", published, err) } } func TestPointCheckpoint(t *testing.T) { ctx := context.Background() now := time.Date(2026, 10, 2, 0, 0, 0, 0, time.UTC) revisions := []string{"0123456789abcdef0123456789abcdef01234567", "1123456789abcdef0123456789abcdef01234567"} object := pointDelivery(revisions...) instance := testController(t, object, &mutableRefs{}, &now) delivery, err := decodeProjectDelivery(object) if err != nil { t.Fatal(err) } for _, revision := range revisions { attempt := &attemptStatus{Revision: revision} if err := instance.ensureWorkflow(ctx, &delivery, attemptName(&delivery, attempt), delivery.Spec.WorkflowTemplateRef.Name, "build", map[string]string{"source-ref": "", "source-revision": revision}, nil); err != nil { t.Fatal(err) } } if err := instance.reconcileKey(ctx, "delivery", "point"); err != nil { t.Fatal(err) } stored, err := decodeProjectDelivery(getDelivery(t, instance, "point")) if err != nil { t.Fatal(err) } if len(stored.Status.Points) != 1 { t.Fatalf("Point checkpoint count = %d", len(stored.Status.Points)) } first := stored.Status.Points[0].WorkflowName for _, revision := range revisions { name := attemptName(&delivery, &attemptStatus{Revision: revision}) workflow, err := instance.client.Resource(workflowGVR).Namespace("delivery").Get(ctx, name, metav1.GetOptions{}) if err != nil { t.Fatal(err) } held := slices.Contains(workflow.GetFinalizers(), recordKey) if held != (name != first) { t.Fatalf("checkpoint protection for %s = %t", name, held) } } setNamedWorkflowStatus(t, instance, first, "Succeeded", nil) for range 2 { if err := instance.reconcileKey(ctx, "delivery", "point"); err != nil { t.Fatal(err) } } stored, err = decodeProjectDelivery(getDelivery(t, instance, "point")) if err != nil { t.Fatal(err) } if len(stored.Status.Points) != 2 { t.Fatalf("recovered checkpoint count = %d", len(stored.Status.Points)) } } func TestRetryOldMode(t *testing.T) { ctx := context.Background() now := time.Date(2026, 10, 2, 0, 0, 0, 0, time.UTC) revision := "0123456789abcdef0123456789abcdef01234567" instance := testController(t, continuousDelivery(), &mutableRefs{values: map[string]string{"refs/heads/main": revision}}, &now) for range 3 { instance.reconcileAll(ctx) now = now.Add(time.Minute) } object := getDelivery(t, instance, "continuous") delivery, err := decodeProjectDelivery(object) if err != nil { t.Fatal(err) } first := delivery.Status.Continuous.Attempt.WorkflowName setNamedWorkflowStatus(t, instance, first, "Failed", nil) instance.reconcileAll(ctx) object = getDelivery(t, instance, "continuous") unstructured.RemoveNestedField(object.Object, "spec", "source", "continuous") if err := unstructured.SetNestedMap(object.Object, map[string]any{"revisions": []any{revision}}, "spec", "source", "point"); err != nil { t.Fatal(err) } annotations := object.GetAnnotations() if annotations == nil { annotations = make(map[string]string) } annotations[retryAnnotation] = first object.SetAnnotations(annotations) if _, err := instance.client.Resource(projectDeliveryGVR).Namespace("delivery").Update(ctx, object, metav1.UpdateOptions{}); err != nil { t.Fatal(err) } if err := instance.reconcileKey(ctx, "delivery", "continuous"); err != nil { t.Fatal(err) } stored, err := decodeProjectDelivery(getDelivery(t, instance, "continuous")) if err != nil { t.Fatal(err) } retry := stored.Status.Continuous.Attempt if stored.Spec.Source.Point == nil || retry.RetryOf != first || retry.Ref != "refs/heads/main" || retry.WorkflowName == first { t.Fatalf("old-mode retry did not preserve captured selection: %+v", retry) } t.Log("retry accepted in Continuous mode while the declared source mode is Point") } func TestTreeOverlap(t *testing.T) { ctx := context.Background() instance, _ := bundleFixture(t) peer := *instance delivery, err := decodeProjectDelivery(continuousDelivery()) if err != nil { t.Fatal(err) } first := &attemptStatus{Ref: "refs/heads/main", Revision: "0123456789abcdef0123456789abcdef01234567", SourceIdentity: "sha256:tree"} second := &attemptStatus{Ref: first.Ref, Revision: "1123456789abcdef0123456789abcdef01234567", SourceIdentity: first.SourceIdentity} instance.client = admitClient{Interface: peer.client, before: func(_ *unstructured.Unstructured) { if err := peer.advanceAttempt(ctx, &delivery, second); err != nil { t.Fatal(err) } }} if err := instance.advanceAttempt(ctx, &delivery, first); err != nil { t.Fatal(err) } if count := countWorkflows(t, instance, "build"); count != 1 { t.Fatalf("one source identity produced %d accepted workflows from overlapping SHA observations", count) } if first.WorkflowName != second.WorkflowName { t.Fatal("overlapping observations did not converge on one captured execution") } if first.Revision != first.Input["source-revision"] { t.Fatalf("accepted Workflow SHA %q differs from recorded attempt SHA %q", first.Input["source-revision"], first.Revision) } } func TestRefOverlap(t *testing.T) { ctx := context.Background() instance, _ := bundleFixture(t) peer := *instance delivery, err := decodeProjectDelivery(continuousDelivery()) if err != nil { t.Fatal(err) } first := &attemptStatus{Ref: "refs/heads/main", Revision: "0123456789abcdef0123456789abcdef01234567", SourceIdentity: "0123456789abcdef0123456789abcdef01234567"} second := &attemptStatus{Ref: "refs/heads/release", Revision: first.Revision, SourceIdentity: first.SourceIdentity} instance.client = admitClient{Interface: peer.client, before: func(_ *unstructured.Unstructured) { if err := peer.advanceAttempt(ctx, &delivery, second); err != nil { t.Fatal(err) } }} if err := instance.advanceAttempt(ctx, &delivery, first); err != nil { t.Fatal(err) } if count := countWorkflows(t, instance, "build"); count != 1 { t.Fatalf("one trigger identity produced %d workflows after a ref change", count) } if first.Ref != first.Input["source-ref"] || first.WorkflowName != second.WorkflowName { t.Fatal("captured ref did not follow the accepted execution") } } func TestDetachedPublish(t *testing.T) { ctx := context.Background() instance, template := bundleFixture(t) delivery, err := decodeProjectDelivery(continuousDelivery()) if err != nil { t.Fatal(err) } if err := instance.ensureWorkflow(ctx, &delivery, "old", template.GetName(), "build", nil, nil); err != nil { t.Fatal(err) } changeImage(t, instance, template.GetName(), "example.invalid/builder:v2") if _, err := instance.readyTemplate(ctx, "delivery", template.GetName()); !errors.Is(err, templatePending) { t.Fatalf("pending update = %v", err) } object := getDelivery(t, instance, "continuous") if err := unstructured.SetNestedField(object.Object, "other-delivery", "spec", "workflowTemplateRef", "name"); err != nil { t.Fatal(err) } if _, err := instance.client.Resource(projectDeliveryGVR).Namespace("delivery").Update(ctx, object, metav1.UpdateOptions{}); err != nil { t.Fatal(err) } setNamedWorkflowStatus(t, instance, "old", "Succeeded", nil) for range 2 { if err := instance.reconcileTemplates(ctx); err != nil { t.Fatal(err) } } stored, err := instance.client.Resource(templateGVR).Namespace("delivery").Get(ctx, template.GetName(), metav1.GetOptions{}) if err != nil { t.Fatal(err) } if stored.GetAnnotations()[publishedKey] != stored.GetAnnotations()[candidateKey] { t.Fatal("unreferenced template retained its update but never published it after drain") } }