From 434a498d31eb6e80e0eed6dcfd6c7d6583a6d4f2 Mon Sep 17 00:00:00 2001 From: Tempris Admin Date: Thu, 18 Jun 2026 03:34:39 +0700 Subject: [PATCH] fix: autoscaling annotation format and empty image guard Two bug fixes: 1. pkg/knative/deployer.go: setServiceOptions used fmt.Sprintf(%f) to format autoscaling Target and Utilization annotations, producing values like 100.000000 instead of 100. Changed to %g which strips trailing zeros (100.0 -> 100, 70.5 -> 70.5). 2. pkg/functions/function.go: ImageNameWithDigest did not guard against an empty Build.Image. When called with a non-empty digest but empty image name, it produced the invalid OCI reference @sha256:... (no image name prefix). Added early return for empty image. Also adds a regression test TestSetServiceOptions_ScaleAnnotationFormat that verifies the annotation values are clean integers. --- pkg/functions/function.go | 3 +++ pkg/knative/deployer.go | 4 ++-- pkg/knative/deployer_test.go | 30 ++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/pkg/functions/function.go b/pkg/functions/function.go index 86c96321ba..cc17a6f273 100644 --- a/pkg/functions/function.go +++ b/pkg/functions/function.go @@ -862,6 +862,9 @@ func (f Function) ImageNameWithDigest(newDigest string) string { return f.Build.Image } image := f.Build.Image + if image == "" { + return "" + } // overwrite current digest shaIndex := strings.Index(image, "@sha256:") diff --git a/pkg/knative/deployer.go b/pkg/knative/deployer.go index 1bd011d142..8d7dd43fa1 100644 --- a/pkg/knative/deployer.go +++ b/pkg/knative/deployer.go @@ -589,13 +589,13 @@ func setServiceOptions(template *servingv1.RevisionTemplateSpec, options fn.Opti } if options.Scale.Target != nil { - toUpdate[autoscaling.TargetAnnotationKey] = fmt.Sprintf("%f", *options.Scale.Target) + toUpdate[autoscaling.TargetAnnotationKey] = fmt.Sprintf("%g", *options.Scale.Target) } else { toRemove = append(toRemove, autoscaling.TargetAnnotationKey) } if options.Scale.Utilization != nil { - toUpdate[autoscaling.TargetUtilizationPercentageKey] = fmt.Sprintf("%f", *options.Scale.Utilization) + toUpdate[autoscaling.TargetUtilizationPercentageKey] = fmt.Sprintf("%g", *options.Scale.Utilization) } else { toRemove = append(toRemove, autoscaling.TargetUtilizationPercentageKey) } diff --git a/pkg/knative/deployer_test.go b/pkg/knative/deployer_test.go index e024ffec6e..c46e093caa 100644 --- a/pkg/knative/deployer_test.go +++ b/pkg/knative/deployer_test.go @@ -29,6 +29,7 @@ import ( v1 "k8s.io/client-go/kubernetes/typed/core/v1" fn "knative.dev/func/pkg/functions" "knative.dev/pkg/ptr" + "knative.dev/serving/pkg/apis/autoscaling" servingv1 "knative.dev/serving/pkg/apis/serving/v1" ) @@ -451,6 +452,35 @@ func TestGenerateNewService_ResourceSetsPopulated(t *testing.T) { } } +func TestSetServiceOptions_ScaleAnnotationFormat(t *testing.T) { + target := 100.0 + utilization := 70.0 + template := &servingv1.RevisionTemplateSpec{ + Spec: servingv1.RevisionSpec{ + PodSpec: corev1.PodSpec{ + Containers: []corev1.Container{{}}, + }, + }, + } + options := fn.Options{ + Scale: &fn.ScaleOptions{ + Target: &target, + Utilization: &utilization, + }, + } + + if err := setServiceOptions(template, options); err != nil { + t.Fatalf("setServiceOptions returned unexpected error: %v", err) + } + + if got := template.Annotations[autoscaling.TargetAnnotationKey]; got != "100" { + t.Errorf("expected target annotation to be %q, got %q", "100", got) + } + if got := template.Annotations[autoscaling.TargetUtilizationPercentageKey]; got != "70" { + t.Errorf("expected utilization annotation to be %q, got %q", "70", got) + } +} + func assertAuth(uname, pwd string, w http.ResponseWriter, r *http.Request) bool { user, pass, ok := r.BasicAuth() if ok && user == uname && pass == pwd {