From 64f92344a90632a7dded77bfd353c5faf9fe1d85 Mon Sep 17 00:00:00 2001 From: Eloi BERLINGER Date: Sun, 5 Jul 2026 21:41:54 +0200 Subject: [PATCH 1/3] fix(project): validate billingReference for standalone public projects --- internal/cmd/project/create/create.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/internal/cmd/project/create/create.go b/internal/cmd/project/create/create.go index ef95167e9..6baeafc54 100644 --- a/internal/cmd/project/create/create.go +++ b/internal/cmd/project/create/create.go @@ -112,6 +112,8 @@ func configureFlags(cmd *cobra.Command) { func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { globalFlags := globalflags.Parse(p, cmd) + networkAreaId := flags.FlagToStringPointer(p, cmd, networkAreaIdFlag) + labels := flags.FlagToStringToStringPointer(p, cmd, labelFlag) if labels != nil { labelKeyRegex := regexp.MustCompile(labelKeyRegex) @@ -131,6 +133,18 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } } } + + if scope, hasScope := (*labels)["scope"]; hasScope && scope == "PUBLIC" { + _, hasBilling := (*labels)["billingReference"] + + if networkAreaId == nil && !hasBilling { + return nil, &errors.FlagValidationError{ + Flag: labelFlag, + Details: "creating a standalone public project (without a network area) requires a 'billingReference' label (e.g., --label billingReference=)", + } + } + } + } model := inputModel{ From 0ddc902211acac0a69cd8cb922d644dbded5c72d Mon Sep 17 00:00:00 2001 From: Eloi BERLINGER Date: Mon, 6 Jul 2026 08:41:31 +0200 Subject: [PATCH 2/3] fix(project): prevent empty billingReference value and add unit tests --- internal/cmd/project/create/create.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cmd/project/create/create.go b/internal/cmd/project/create/create.go index 6baeafc54..5343934f2 100644 --- a/internal/cmd/project/create/create.go +++ b/internal/cmd/project/create/create.go @@ -135,9 +135,9 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } if scope, hasScope := (*labels)["scope"]; hasScope && scope == "PUBLIC" { - _, hasBilling := (*labels)["billingReference"] + billingReference, hasBilling := (*labels)["billingReference"] - if networkAreaId == nil && !hasBilling { + if networkAreaId == nil && (!hasBilling || billingReference == "") { return nil, &errors.FlagValidationError{ Flag: labelFlag, Details: "creating a standalone public project (without a network area) requires a 'billingReference' label (e.g., --label billingReference=)", From bee477fe46274cc4cb814e5c358067c3a0eb80a8 Mon Sep 17 00:00:00 2001 From: Eloi BERLINGER Date: Mon, 6 Jul 2026 08:43:11 +0200 Subject: [PATCH 3/3] test: add unit tests for public project validation --- .../cmd/affinity-groups/create/create_test.go | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/internal/cmd/affinity-groups/create/create_test.go b/internal/cmd/affinity-groups/create/create_test.go index e547a4990..f58fe7dc9 100644 --- a/internal/cmd/affinity-groups/create/create_test.go +++ b/internal/cmd/affinity-groups/create/create_test.go @@ -121,6 +121,26 @@ func TestParseInput(t *testing.T) { }, ), }, + { + description: "fails public project without network area and without billing reference", + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + flagValues["label"] = "scope=PUBLIC" + delete(flagValues, "network-area-id") + }, + ), + isValid: false, + }, + { + description: "fails public project with empty billing reference", + flagValues: fixtureFlagValues( + func(flagValues map[string]string) { + flagValues["label"] = "scope=PUBLIC,billingReference=" + delete(flagValues, "network-area-id") + }, + ), + isValid: false, + }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) {