From 94de803e7fb592b8189503c914bc26188f9e7a68 Mon Sep 17 00:00:00 2001 From: grandwizard28 Date: Fri, 26 Jun 2026 11:52:21 +0530 Subject: [PATCH] fix: promote variable defaultValue to a named oneOf component The list variable defaultValue was an inline string | []string oneOf, which downstream codegen can't canonicalize: tfplugingen-openapi rejects the inline scalar-or-array multi-type, and oapi-codegen has no named type to attach the union's Marshal/UnmarshalJSON to. Shape the vendored variable.DefaultValue as the named VariableDefaultValue oneOf via a reflector InterceptSchema hook and let defaultValue $ref it, instead of overriding the property inline. Regenerate the OpenAPI spec and frontend client accordingly. --- docs/api/openapi.yml | 12 +++---- .../api/generated/services/sigNoz.schemas.ts | 10 ++---- .../Variables/variableFormModel.ts | 4 +-- pkg/signoz/openapi.go | 36 +++++++++++++++++++ pkg/types/dashboardtypes/perses_replicas.go | 17 --------- 5 files changed, 47 insertions(+), 32 deletions(-) diff --git a/docs/api/openapi.yml b/docs/api/openapi.yml index 37d3ce8531..aea7b6ab23 100644 --- a/docs/api/openapi.yml +++ b/docs/api/openapi.yml @@ -2971,11 +2971,7 @@ components: customAllValue: type: string defaultValue: - oneOf: - - type: string - - items: - type: string - type: array + $ref: '#/components/schemas/VariableDefaultValue' display: $ref: '#/components/schemas/DashboardtypesDisplay' name: @@ -7895,7 +7891,11 @@ components: - id type: object VariableDefaultValue: - type: object + oneOf: + - type: string + - items: + type: string + type: array ZeustypesGettableHost: properties: hosts: diff --git a/frontend/src/api/generated/services/sigNoz.schemas.ts b/frontend/src/api/generated/services/sigNoz.schemas.ts index b32117f319..5494653937 100644 --- a/frontend/src/api/generated/services/sigNoz.schemas.ts +++ b/frontend/src/api/generated/services/sigNoz.schemas.ts @@ -4564,6 +4564,8 @@ export type DashboardtypesLayoutDTO = export enum DashboardtypesVariableEnvelopeGithubComSigNozSignozPkgTypesDashboardtypesListVariableSpecDTOKind { ListVariable = 'ListVariable', } +export type VariableDefaultValueDTO = string | string[]; + export enum DashboardtypesVariablePluginVariantGithubComSigNozSignozPkgTypesDashboardtypesDynamicVariableSpecDTOKind { 'signoz/DynamicVariable' = 'signoz/DynamicVariable', } @@ -4629,8 +4631,6 @@ export enum DashboardtypesListVariableSpecSortDTO { 'alphabetical-ci-asc' = 'alphabetical-ci-asc', 'alphabetical-ci-desc' = 'alphabetical-ci-desc', } -export type DashboardtypesListVariableSpecDTODefaultValue = string | string[]; - export interface DashboardtypesListVariableSpecDTO { /** * @type boolean @@ -4648,7 +4648,7 @@ export interface DashboardtypesListVariableSpecDTO { * @type string */ customAllValue?: string; - defaultValue?: DashboardtypesListVariableSpecDTODefaultValue; + defaultValue?: VariableDefaultValueDTO; display: DashboardtypesDisplayDTO; /** * @type string @@ -9023,10 +9023,6 @@ export interface TypesUserDTO { updatedAt?: string; } -export interface VariableDefaultValueDTO { - [key: string]: unknown; -} - export interface ZeustypesHostDTO { /** * @type boolean diff --git a/frontend/src/pages/DashboardPageV2/DashboardContainer/DashboardSettings/Variables/variableFormModel.ts b/frontend/src/pages/DashboardPageV2/DashboardContainer/DashboardSettings/Variables/variableFormModel.ts index 2f34fbe94c..89b98be98d 100644 --- a/frontend/src/pages/DashboardPageV2/DashboardContainer/DashboardSettings/Variables/variableFormModel.ts +++ b/frontend/src/pages/DashboardPageV2/DashboardContainer/DashboardSettings/Variables/variableFormModel.ts @@ -2,7 +2,7 @@ import { DashboardtypesListVariableSpecSortDTO, TelemetrytypesSignalDTO, } from 'api/generated/services/sigNoz.schemas'; -import type { DashboardtypesListVariableSpecDTODefaultValue } from 'api/generated/services/sigNoz.schemas'; +import type { VariableDefaultValueDTO } from 'api/generated/services/sigNoz.schemas'; import { sortBy } from 'lodash-es'; /** @@ -136,7 +136,7 @@ export interface VariableFormModel { * Runtime-selected default, not editable in the management tab yet; carried * through edits so saving a definition doesn't clobber it. */ - defaultValue?: DashboardtypesListVariableSpecDTODefaultValue; + defaultValue?: VariableDefaultValueDTO; } export function emptyVariableFormModel(): VariableFormModel { diff --git a/pkg/signoz/openapi.go b/pkg/signoz/openapi.go index 21697d5816..3e19b7ef07 100644 --- a/pkg/signoz/openapi.go +++ b/pkg/signoz/openapi.go @@ -39,6 +39,7 @@ import ( "github.com/SigNoz/signoz/pkg/statsreporter" "github.com/SigNoz/signoz/pkg/types/authtypes" "github.com/SigNoz/signoz/pkg/zeus" + "github.com/perses/spec/go/dashboard/variable" "github.com/swaggest/jsonschema-go" "github.com/swaggest/openapi-go" "github.com/swaggest/openapi-go/openapi3" @@ -104,6 +105,41 @@ func NewOpenAPI(ctx context.Context, instrumentation instrumentation.Instrumenta return defaultDefName })) + // variable.DefaultValue (perses) is the string | []string union used by a + // list variable's defaultValue. It marshals as a scalar-or-array, so its + // reflected struct shape (a bare object) is wrong. Emit it as a named oneOf + // component (VariableDefaultValue) and let defaultValue $ref it, instead of + // inlining the union onto the property: a named component gives downstream + // codegen a hook to canonicalize — oapi-codegen generates the union's + // Marshal/UnmarshalJSON and skaff's scalar-union pre-pass flattens it to a + // string attribute. An inline oneOf has no such component to hook. + reflector.JSONSchemaReflector().DefaultOptions = append(reflector.JSONSchemaReflector().DefaultOptions, jsonschema.InterceptSchema(func(params jsonschema.InterceptSchemaParams) (bool, error) { + if !params.Processed || !params.Value.IsValid() { + return false, nil + } + + typ := params.Value.Type() + if typ.Kind() == reflect.Pointer { + typ = typ.Elem() + } + if typ != reflect.TypeOf(variable.DefaultValue{}) { + return false, nil + } + + stringItem := jsonschema.String.ToSchemaOrBool() + params.Schema.Type = nil + params.Schema.Properties = nil + params.Schema.WithOneOf( + jsonschema.String.ToSchemaOrBool(), + (&jsonschema.Schema{}). + WithType(jsonschema.Array.Type()). + WithItems(jsonschema.Items{SchemaOrBool: &stringItem}). + ToSchemaOrBool(), + ) + + return false, nil + })) + reflector.Spec.WithInfo(*(&openapi3.Info{}). WithTitle("SigNoz"). WithDescription("OpenTelemetry-Native Logs, Metrics and Traces in a single pane"). diff --git a/pkg/types/dashboardtypes/perses_replicas.go b/pkg/types/dashboardtypes/perses_replicas.go index 0aacd83044..7ef0cae999 100644 --- a/pkg/types/dashboardtypes/perses_replicas.go +++ b/pkg/types/dashboardtypes/perses_replicas.go @@ -156,23 +156,6 @@ type ListVariableSpec struct { Name string `json:"name" required:"true" minLength:"1"` } -// PrepareJSONSchema types defaultValue as the string | []string union. -func (ListVariableSpec) PrepareJSONSchema(s *jsonschema.Schema) error { - if _, ok := s.Properties["defaultValue"]; !ok { - return nil - } - stringItem := jsonschema.String.ToSchemaOrBool() - defaultValue := (&jsonschema.Schema{}).WithOneOf( - jsonschema.String.ToSchemaOrBool(), - (&jsonschema.Schema{}). - WithType(jsonschema.Array.Type()). - WithItems(jsonschema.Items{SchemaOrBool: &stringItem}). - ToSchemaOrBool(), - ) - s.Properties["defaultValue"] = defaultValue.ToSchemaOrBool() - return nil -} - // validate mirrors perses ListVariableSpec validation (plus the digits-only name // check perses only applies to text variables); run by decodeSpec on unmarshal. func (s *ListVariableSpec) validate() error {