diff --git a/src/data/schemas/v0/pipeline.ts b/src/data/schemas/v0/pipeline.ts index c43922fda..8c1d20c9b 100644 --- a/src/data/schemas/v0/pipeline.ts +++ b/src/data/schemas/v0/pipeline.ts @@ -35940,6 +35940,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|selectManyFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "markNextChangeSetRun": { "type": "boolean" }, @@ -36175,6 +36190,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|selectManyFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "resources": { "$ref": "#/definitions/pipeline/common/ContainerResource" }, @@ -36391,6 +36421,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|selectManyFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "excludeChangeLogFile": { "type": "boolean" }, @@ -36502,6 +36547,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|selectManyFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "excludeChangeLogFile": { "type": "boolean" }, @@ -37003,6 +37063,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "resources": { "$ref": "#/definitions/pipeline/common/ContainerResource" }, @@ -37113,6 +37188,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "resources": { "$ref": "#/definitions/pipeline/common/ContainerResource" }, @@ -37328,6 +37418,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "resources": { "$ref": "#/definitions/pipeline/common/ContainerResource" }, @@ -37432,6 +37537,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "resources": { "$ref": "#/definitions/pipeline/common/ContainerResource" }, @@ -37677,6 +37797,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "resources": { "$ref": "#/definitions/pipeline/common/ContainerResource" }, @@ -37811,6 +37946,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "resources": { "$ref": "#/definitions/pipeline/common/ContainerResource" }, @@ -38030,6 +38180,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|selectManyFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "resources": { "$ref": "#/definitions/pipeline/common/ContainerResource" }, diff --git a/src/data/schemas/v0/template.ts b/src/data/schemas/v0/template.ts index 6be1a3307..19267f69d 100644 --- a/src/data/schemas/v0/template.ts +++ b/src/data/schemas/v0/template.ts @@ -100573,6 +100573,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|selectManyFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "markNextChangeSetRun": { "type": "boolean" }, @@ -100794,6 +100809,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|selectManyFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "resources": { "$ref": "#/definitions/pipeline/common/ContainerResource" }, @@ -102788,6 +102818,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|selectManyFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "excludeChangeLogFile": { "type": "boolean" }, @@ -102899,6 +102944,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|selectManyFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "excludeChangeLogFile": { "type": "boolean" }, @@ -105639,6 +105699,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "resources": { "$ref": "#/definitions/pipeline/common/ContainerResource" }, @@ -105749,6 +105824,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "resources": { "$ref": "#/definitions/pipeline/common/ContainerResource" }, @@ -105950,6 +106040,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "resources": { "$ref": "#/definitions/pipeline/common/ContainerResource" }, @@ -106054,6 +106159,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "resources": { "$ref": "#/definitions/pipeline/common/ContainerResource" }, @@ -106285,6 +106405,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "resources": { "$ref": "#/definitions/pipeline/common/ContainerResource" }, @@ -106419,6 +106554,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "resources": { "$ref": "#/definitions/pipeline/common/ContainerResource" }, @@ -106624,6 +106774,21 @@ const schema: Record = { } ] }, + "reuse": { + "oneOf": [ + { + "type": "string", + "not": { + "pattern": "^<\\+.*>.*$" + } + }, + { + "type": "string", + "pattern": "^<\\+input>((\\.)(allowedValues|selectOneFrom|selectManyFrom|default|regex)\\(.+?\\))*$", + "minLength": 1 + } + ] + }, "resources": { "$ref": "#/definitions/pipeline/common/ContainerResource" }, diff --git a/tests/schemas/schema-bundle-contract.test.ts b/tests/schemas/schema-bundle-contract.test.ts index dc51f3f88..2dda19972 100644 --- a/tests/schemas/schema-bundle-contract.test.ts +++ b/tests/schemas/schema-bundle-contract.test.ts @@ -220,4 +220,58 @@ describe("schema bundle contract", () => { expect(dynamicStage.properties.dynamic.properties).toHaveProperty("source-config"); } }); + + it("includes upstream reuse field on DB DevOps step definitions in v0 pipeline and template", () => { + const dbOpsStepInfosWithReuse = [ + "DBApplySchemaStepInfo", + "DBRollbackSchemaStepInfo", + "LiquibaseCommandStepInfo", + "DBOPSTestAndPreviewStepInfo", + "DBSchemaUpdateSQLInfo", + "DBSchemaRollbackSQLInfo", + "FlywayCommandStepInfo", + ] as const; + + const stepInfosWithSelectManyFrom = new Set([ + "DBApplySchemaStepInfo", + "DBRollbackSchemaStepInfo", + "LiquibaseCommandStepInfo", + "FlywayCommandStepInfo", + ]); + + for (const key of ["pipeline", "template"] as const) { + const common = (SCHEMAS[key].definitions as Record>).pipeline + .steps.common as Record< + string, + { allOf?: Array<{ properties?: Record }> } + >; + + for (const stepInfo of dbOpsStepInfosWithReuse) { + expect(common).toHaveProperty(stepInfo); + const properties = common[stepInfo].allOf?.[1]?.properties; + expect(properties).toHaveProperty("reuse"); + + const reuse = properties!.reuse as { + oneOf: Array<{ type?: string; not?: { pattern: string }; pattern?: string; minLength?: number }>; + }; + expect(reuse.oneOf).toHaveLength(2); + expect(reuse.oneOf[0]).toEqual({ + type: "string", + not: { pattern: "^<\\+.*>.*$" }, + }); + + const inputExpr = reuse.oneOf[1]; + expect(inputExpr.type).toBe("string"); + expect(inputExpr.minLength).toBe(1); + expect(inputExpr.pattern?.startsWith("^<\\+input>")).toBe(true); + expect(inputExpr.pattern).toContain("allowedValues"); + expect(inputExpr.pattern).toContain("selectOneFrom"); + if (stepInfosWithSelectManyFrom.has(stepInfo)) { + expect(inputExpr.pattern).toContain("selectManyFrom"); + } else { + expect(inputExpr.pattern).not.toContain("selectManyFrom"); + } + } + } + }); });