From 345f8d8b0dbbed5b77deb54802b005d812e47a1e Mon Sep 17 00:00:00 2001 From: Danielle Adams Date: Mon, 22 Jul 2024 15:24:39 -0600 Subject: [PATCH 1/6] ARCH-2126 - Adding a pattern to the metadata.name prop --- dist/index.js | 110 +++++++++++++++++++-- schema/Entity.schema.json | 11 ++- src/main.js | 24 +++-- src/validate.js | 3 +- test/catalog-infos/invalid-entities.yml | 19 +++- test/expected-markdown/invalid-entities.md | 5 +- 6 files changed, 149 insertions(+), 23 deletions(-) diff --git a/dist/index.js b/dist/index.js index 23e734a..11eb906 100644 --- a/dist/index.js +++ b/dist/index.js @@ -29413,7 +29413,15 @@ var require_Domain_v1alpha1_schema = __commonJS({ kind: 'Domain', metadata: { name: 'front-end-tooling', - description: 'Tools and components to unify and streamline front-end development, browser performance, and consistency.' + description: 'Tools and components to unify and streamline front-end development, browser performance, and consistency.', + needs: { + 'print-vendor': 'to send printed materials', + telephony: 'to notify when there are calls in the queue' + }, + annotations: { + 'mktp.io/notes': 'Tools and components to unify and streamline front-end development.', + 'mktp.io/owners': 'Any additional info about ownership' + } }, spec: { owner: 'group:default/customization' @@ -29421,9 +29429,6 @@ var require_Domain_v1alpha1_schema = __commonJS({ } ], allOf: [ - { - $ref: 'Entity.schema.json' - }, { type: 'object', required: ['spec'], @@ -29431,6 +29436,75 @@ var require_Domain_v1alpha1_schema = __commonJS({ kind: { enum: ['Domain'] }, + metadata: { + type: 'object', + required: ['annotations'], + properties: { + needs: { + type: 'object', + description: + "A collection of key-value pairs of other domains and what this domain needs from them. \nKeys be up to 63 alphanumeric characters including '[-_.]'. Values are a string and markdown is supported.", + propertyNames: { + minLength: 1, + maxLength: 63, + pattern: '^([a-z0-9A-Z\\-\\_\\.]+)$', + $comment: "The domain key cannot exceed 63 characters and can only contain alphanumeric values including '-', '_', and '.'." + }, + additionalProperties: { + type: 'string', + minLength: 1, + description: + "Each entry should have a Domain key which represents the other domain that is needed and a string value that describes what is needed from the other domain. Markdown is supported.\nThe value should be worded to fill in a sentence like: 'This Domain needs the Other Domain to ___.'", + examples: [ + { + 'print-vendor': 'to send printed materials', + telephony: 'to notify when there are calls in the queue' + } + ] + }, + examples: [ + { + 'print-vendor': 'to send printed materials', + telephony: 'to notify when there are calls in the queue' + } + ], + $comment: + "Needs is a map of key-value pairs where key is the string name of the domain that is needed and the value is a string that describes what is needed from that domain. The key cannot exceed 63 characters and can only contain alphanumeric values including '-', '_', and '.'. The value is a string and markdown is supported." + }, + annotations: { + type: 'object', + description: 'A collection of key-value pairs of non-identifying auxiliary information attached to the entity.', + required: ['mktp.io/notes'], + properties: { + 'mktp.io/notes': { + type: 'string', + description: + 'Long form notes about the responsibilities, scope, and other important details about the bounded context. Markdown is supported.', + examples: [ + 'Tools and components to unify and streamline front-end development.', + '\nThe source of truth for allocating time to handle customer appts.' + ] + }, + 'mktp.io/owners': { + type: 'string', + description: + 'Information regarding Domain ownership. Generally used only when ownership is unsettled. Markdown is supported.', + examples: [ + '## Unsettled Ownership\nOwnership is NOT settled. The apps that this context should own are currently stewarded by many teams.' + ] + } + }, + additionalProperties: true, + patternProperties: { + '^.+$': { + type: 'string' + } + }, + $comment: + "Annotations is a map of key-value pairs containing auxiliary information attached to the entity. For Domains, the 'mktp.io/notes' annotation is required and any other annotations are optional." + } + } + }, spec: { type: 'object', required: ['type', 'owner'], @@ -29657,7 +29731,11 @@ var require_Entity_schema = __commonJS({ type: 'string', description: 'The name of the entity. Must be unique within the catalog for the given kind.', examples: ['front-end-tooling'], - minLength: 1 + pattern: '^([a-z0-9A-Z\\-\\_\\.]+)$', + minLength: 1, + maxLength: 63, + $comment: + "The name must be unique within the catalog for the given kind, it cannot exceed 63 characters and it can only contain alphanumeric values including '-', '_', and '.'." }, title: { type: 'string', @@ -29671,7 +29749,7 @@ var require_Entity_schema = __commonJS({ }, annotations: { type: 'object', - description: 'Key/value pairs of non-identifying auxiliary information attached to the entity.', + description: 'Key-value pairs of non-identifying auxiliary information attached to the entity.', additionalProperties: true, patternProperties: { '^.+$': { @@ -29679,7 +29757,7 @@ var require_Entity_schema = __commonJS({ } }, $comment: - 'The object should be populated with key value pairs containing auxiliary information attached to the entity or be removed completely.' + 'The object should be populated with key-value pairs containing auxiliary information attached to the entity or be removed completely.' }, links: { type: 'array', @@ -29768,7 +29846,9 @@ var require_validate2 = __commonJS({ allErrors: true, async: true, verbose: true, - unicodeRegExp: false + unicodeRegExp: false, + allowMatchingProperties: true + // Allow overlap between 'properties' and 'patternProperties' }); ajv.addSchema(catalogInfoSchema, 'root'); ajv.addSchema(entitySchema, 'entity'); @@ -30002,6 +30082,12 @@ function setOutputsForErrors(errors, filename2, failIfThereAreErrors2) { if (generateJobSummary) { core.summary.addRaw(markdown, true).write(); } + fs.writeFile('./errors-markdown.md', markdown, err => { + if (err) { + console.error(`An error occurred writing the md to file: ${err}`); + return; + } + }); if (failIfThereAreErrors2) { core.setFailed(`${filename2} file is invalid`); } else { @@ -30081,6 +30167,14 @@ validationMetadata: lines.push(`metadata_links: ${i}`); } else if (formattedLine.startsWith('deployment-environments:')) { lines.push(`metadata_deployment_environments: ${i}`); + } else if (formattedLine.startsWith('addresses:')) { + lines.push(`metadata_addresses: ${i}`); + } else if (formattedLine.startsWith('mktp.io/notes:')) { + lines.push(`metadata_mktp_io_notes: ${i}`); + } else if (formattedLine.startsWith('mktp.io/owners:')) { + lines.push(`metadata_mktp_io_owners: ${i}`); + } else if (formattedLine.startsWith('needs:')) { + lines.push(`metadata_needs: ${i}`); } } else if (currentParent === 'spec') { if (formattedLine.startsWith('type:')) { diff --git a/schema/Entity.schema.json b/schema/Entity.schema.json index 871f61c..871c0ae 100644 --- a/schema/Entity.schema.json +++ b/schema/Entity.schema.json @@ -55,7 +55,10 @@ "examples": [ "front-end-tooling" ], - "minLength": 1 + "pattern": "^([a-z0-9A-Z\\-\\_\\.]+)$", + "minLength": 1, + "maxLength": 63, + "$comment": "The name must be unique within the catalog for the given kind, it cannot exceed 63 characters and it can only contain alphanumeric values including '-', '_', and '.'." }, "title": { "type": "string", @@ -71,14 +74,14 @@ }, "annotations": { "type": "object", - "description": "Key/value pairs of non-identifying auxiliary information attached to the entity.", + "description": "Key-value pairs of non-identifying auxiliary information attached to the entity.", "additionalProperties": true, "patternProperties": { "^.+$": { "type": "string" } }, - "$comment": "The object should be populated with key value pairs containing auxiliary information attached to the entity or be removed completely." + "$comment": "The object should be populated with key-value pairs containing auxiliary information attached to the entity or be removed completely." }, "links": { "type": "array", @@ -148,4 +151,4 @@ "description": "Used during automated validation, not to be used in catalog-info.yml files. Contains the information about the original yaml file so errors can be attributed to the correct lines." } } -} \ No newline at end of file +} diff --git a/src/main.js b/src/main.js index b13f16f..ddc41b1 100644 --- a/src/main.js +++ b/src/main.js @@ -57,14 +57,14 @@ function setOutputsForErrors(errors, filename, failIfThereAreErrors) { core.summary.addRaw(markdown, true).write(); } - // Uncomment if debugging locally to see what the generated markdown looks like - // Helpful if adjustments are made to schemas or catalog-info files used for testing - // fs.writeFile('./errors-markdown.md', markdown, err => { - // if (err) { - // console.error(`An error occurred writing the md to file: ${err}`); - // return; - // } - // }); + // Print out an errors-markdown file which contains the markdown fragment. + // This will make it easier to compare expected/actual output. + fs.writeFile('./errors-markdown.md', markdown, err => { + if (err) { + console.error(`An error occurred writing the md to file: ${err}`); + return; + } + }); if (failIfThereAreErrors) { core.setFailed(`${filename} file is invalid`); @@ -165,6 +165,14 @@ validationMetadata: lines.push(`metadata_links: ${i}`); } else if (formattedLine.startsWith('deployment-environments:')) { lines.push(`metadata_deployment_environments: ${i}`); + } else if (formattedLine.startsWith('addresses:')) { + lines.push(`metadata_addresses: ${i}`); + } else if (formattedLine.startsWith('mktp.io/notes:')) { + lines.push(`metadata_mktp_io_notes: ${i}`); + } else if (formattedLine.startsWith('mktp.io/owners:')) { + lines.push(`metadata_mktp_io_owners: ${i}`); + } else if (formattedLine.startsWith('needs:')) { + lines.push(`metadata_needs: ${i}`); } } else if (currentParent === 'spec') { if (formattedLine.startsWith('type:')) { diff --git a/src/validate.js b/src/validate.js index e59265c..724d5e5 100644 --- a/src/validate.js +++ b/src/validate.js @@ -15,7 +15,8 @@ function setupAjvSchemaValidation(Ajv) { allErrors: true, async: true, verbose: true, - unicodeRegExp: false + unicodeRegExp: false, + allowMatchingProperties: true // Allow overlap between 'properties' and 'patternProperties' }); ajv.addSchema(catalogInfoSchema, 'root'); diff --git a/test/catalog-infos/invalid-entities.yml b/test/catalog-infos/invalid-entities.yml index e818d89..43f8436 100644 --- a/test/catalog-infos/invalid-entities.yml +++ b/test/catalog-infos/invalid-entities.yml @@ -142,4 +142,21 @@ kind: System metadata: name: content-management-16 extra-props: not-allowed -... \ No newline at end of file +... +--- + +# Doc 17 - metadata.name too long +apiVersion: backstage.io/v1alpha1 +kind: System +metadata: + name: entity-names-can-only-be-63-characters-long-and-this-one-has--64 +... +--- + +# Doc 18 - metadata.name uses invalid chars +apiVersion: backstage.io/v1alpha1 +kind: System +metadata: + name: content-management-18! +... +--- \ No newline at end of file diff --git a/test/expected-markdown/invalid-entities.md b/test/expected-markdown/invalid-entities.md index 88216bf..b99b40e 100644 --- a/test/expected-markdown/invalid-entities.md +++ b/test/expected-markdown/invalid-entities.md @@ -16,7 +16,7 @@ - Doc 10, Line 78, `System[Doc10]/metadata` is an object that cannot be empty. The metadata object requires a name property. - Doc 11, Line 85, `System[Doc11]/metadata/name` is a string that cannot be empty. It should be populated or be removed completely if not required. - Doc 12, Line 94, `System[content-management-12]/metadata/title` cannot be empty if provided. -- Doc 13, Line 103, `System[content-management-13]/metadata/annotations` is an object that cannot be empty. The object should be populated with key value pairs containing auxiliary information attached to the entity or be removed completely. +- Doc 13, Line 103, `System[content-management-13]/metadata/annotations` is an object that cannot be empty. The object should be populated with key-value pairs containing auxiliary information attached to the entity or be removed completely. - Doc 14, Line 113, `System[content-management-14]/metadata/links` is an array that cannot be empty. It should contain at least one list item or be removed completely if not required. - Doc 15, Line 122, `System[content-management-15]/metadata/links/0` must have required property **url**. - Doc 15, Line 122, `System[content-management-15]/metadata/links/1/url` cannot be empty if provided. @@ -26,3 +26,6 @@ - Doc 15, Line 122, `System[content-management-15]/metadata/links/4/icon` value **description** is invalid - Allowed values: *catalog, scaffolder, techdocs, search, chat, dashboard, docs, email, github, group, help, kind:api, kind:component, kind:domain, kind:group, kind:location, kind:system, kind:user, kind:resource, user, warning* - Doc 16, Line 138, `System[content-management-16]` cannot be extended with additional properties. **extra-props** should be removed. +- Doc 17, Line 152, `System[entity-names-can-only-be-63-characters-long-and-this-one-has--64]/metadata/name` value **entity-names-can-only-be-63-characters-long-and-this-one-has--64** must NOT have more than 63 characters. +- Doc 18, Line 160, `System[content-management-18!]/metadata/name` value **content-management-18!** is invalid. +The name must be unique within the catalog for the given kind, it cannot exceed 63 characters and it can only contain alphanumeric values including **-**, **_**, and **.**. e.g. **front-end-tooling** From dad922500e21ad75fd12c8f71e1efc064c5202f5 Mon Sep 17 00:00:00 2001 From: Danielle Adams Date: Mon, 22 Jul 2024 15:58:32 -0600 Subject: [PATCH 2/6] ARCH-2126 - Adding additional props to valid entity in api and component files. (Missed this in a previous PR) --- README.md | 2 +- dist/index.js | 82 +------------------- test/catalog-infos/invalid-apis.yml | 7 +- test/catalog-infos/invalid-components.yml | 5 ++ test/expected-markdown/invalid-apis.md | 44 +++++------ test/expected-markdown/invalid-components.md | 72 ++++++++--------- 6 files changed, 74 insertions(+), 138 deletions(-) diff --git a/README.md b/README.md index 20aa305..b7c36a3 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ jobs: - name: Validate catalog-info.yml id: catalogInfo - uses: im-open/validate-catalog-info@v1.0.1 + uses: im-open/validate-catalog-info@v1.0.2 with: filename: ./docs/catalog-info.yml # Defaults to ./catalog-info.yml fail-if-errors: false # Defaults to true diff --git a/dist/index.js b/dist/index.js index 11eb906..33f2851 100644 --- a/dist/index.js +++ b/dist/index.js @@ -29413,15 +29413,7 @@ var require_Domain_v1alpha1_schema = __commonJS({ kind: 'Domain', metadata: { name: 'front-end-tooling', - description: 'Tools and components to unify and streamline front-end development, browser performance, and consistency.', - needs: { - 'print-vendor': 'to send printed materials', - telephony: 'to notify when there are calls in the queue' - }, - annotations: { - 'mktp.io/notes': 'Tools and components to unify and streamline front-end development.', - 'mktp.io/owners': 'Any additional info about ownership' - } + description: 'Tools and components to unify and streamline front-end development, browser performance, and consistency.' }, spec: { owner: 'group:default/customization' @@ -29429,6 +29421,9 @@ var require_Domain_v1alpha1_schema = __commonJS({ } ], allOf: [ + { + $ref: 'Entity.schema.json' + }, { type: 'object', required: ['spec'], @@ -29436,75 +29431,6 @@ var require_Domain_v1alpha1_schema = __commonJS({ kind: { enum: ['Domain'] }, - metadata: { - type: 'object', - required: ['annotations'], - properties: { - needs: { - type: 'object', - description: - "A collection of key-value pairs of other domains and what this domain needs from them. \nKeys be up to 63 alphanumeric characters including '[-_.]'. Values are a string and markdown is supported.", - propertyNames: { - minLength: 1, - maxLength: 63, - pattern: '^([a-z0-9A-Z\\-\\_\\.]+)$', - $comment: "The domain key cannot exceed 63 characters and can only contain alphanumeric values including '-', '_', and '.'." - }, - additionalProperties: { - type: 'string', - minLength: 1, - description: - "Each entry should have a Domain key which represents the other domain that is needed and a string value that describes what is needed from the other domain. Markdown is supported.\nThe value should be worded to fill in a sentence like: 'This Domain needs the Other Domain to ___.'", - examples: [ - { - 'print-vendor': 'to send printed materials', - telephony: 'to notify when there are calls in the queue' - } - ] - }, - examples: [ - { - 'print-vendor': 'to send printed materials', - telephony: 'to notify when there are calls in the queue' - } - ], - $comment: - "Needs is a map of key-value pairs where key is the string name of the domain that is needed and the value is a string that describes what is needed from that domain. The key cannot exceed 63 characters and can only contain alphanumeric values including '-', '_', and '.'. The value is a string and markdown is supported." - }, - annotations: { - type: 'object', - description: 'A collection of key-value pairs of non-identifying auxiliary information attached to the entity.', - required: ['mktp.io/notes'], - properties: { - 'mktp.io/notes': { - type: 'string', - description: - 'Long form notes about the responsibilities, scope, and other important details about the bounded context. Markdown is supported.', - examples: [ - 'Tools and components to unify and streamline front-end development.', - '\nThe source of truth for allocating time to handle customer appts.' - ] - }, - 'mktp.io/owners': { - type: 'string', - description: - 'Information regarding Domain ownership. Generally used only when ownership is unsettled. Markdown is supported.', - examples: [ - '## Unsettled Ownership\nOwnership is NOT settled. The apps that this context should own are currently stewarded by many teams.' - ] - } - }, - additionalProperties: true, - patternProperties: { - '^.+$': { - type: 'string' - } - }, - $comment: - "Annotations is a map of key-value pairs containing auxiliary information attached to the entity. For Domains, the 'mktp.io/notes' annotation is required and any other annotations are optional." - } - } - }, spec: { type: 'object', required: ['type', 'owner'], diff --git a/test/catalog-infos/invalid-apis.yml b/test/catalog-infos/invalid-apis.yml index ffc8d0a..28992d5 100644 --- a/test/catalog-infos/invalid-apis.yml +++ b/test/catalog-infos/invalid-apis.yml @@ -6,7 +6,12 @@ apiVersion: backstage.io/v1alpha1 kind: API metadata: name: content-mgmt-api -spec: + addresses: + mktp.io: + - subdomain: api + path: / + envs: dev qa stage prod +spec: type: openapi lifecycle: maintaining system: system:default/content-management diff --git a/test/catalog-infos/invalid-components.yml b/test/catalog-infos/invalid-components.yml index a17f5dc..873075c 100644 --- a/test/catalog-infos/invalid-components.yml +++ b/test/catalog-infos/invalid-components.yml @@ -10,6 +10,11 @@ metadata: - Dev - QA - Prod + addresses: + mktp.io: + - subdomain: api + path: / + envs: dev qa stage prod spec: type: mfe lifecycle: maintaining diff --git a/test/expected-markdown/invalid-apis.md b/test/expected-markdown/invalid-apis.md index 7418e58..a2945e9 100644 --- a/test/expected-markdown/invalid-apis.md +++ b/test/expected-markdown/invalid-apis.md @@ -2,32 +2,32 @@ `./test/catalog-infos/invalid-apis.yml` contains the following validation errors: -- Doc 3, Line 30, `API[content-mgmt-api-3]/spec` is an object that cannot be empty. It should contain definition, lifecycle, system, and type properties and may contain an optional owner prop. -- Doc 4, Line 39, `API[content-mgmt-api-4]/spec` must have required property **type**. -- Doc 5, Line 54, `API[content-mgmt-api-5]/spec/type` value cannot be empty +- Doc 3, Line 35, `API[content-mgmt-api-3]/spec` is an object that cannot be empty. It should contain definition, lifecycle, system, and type properties and may contain an optional owner prop. +- Doc 4, Line 44, `API[content-mgmt-api-4]/spec` must have required property **type**. +- Doc 5, Line 59, `API[content-mgmt-api-5]/spec/type` value cannot be empty - Allowed values: *openapi, asyncapi* -- Doc 6, Line 68, `API[content-mgmt-api-6]/spec/type` value **myapi** is invalid +- Doc 6, Line 73, `API[content-mgmt-api-6]/spec/type` value **myapi** is invalid - Allowed values: *openapi, asyncapi* -- Doc 7, Line 81, `API[content-mgmt-api-7]/spec` must have required property **lifecycle**. -- Doc 8, Line 97, `API[content-mgmt-api-8]/spec/lifecycle` value cannot be empty +- Doc 7, Line 86, `API[content-mgmt-api-7]/spec` must have required property **lifecycle**. +- Doc 8, Line 102, `API[content-mgmt-api-8]/spec/lifecycle` value cannot be empty - Allowed values: *experimenting, developing, maintaining, deprecating, obsolete* -- Doc 9, Line 111, `API[content-mgmt-api-9]/spec/lifecycle` value **mylifecycle** is invalid +- Doc 9, Line 116, `API[content-mgmt-api-9]/spec/lifecycle` value **mylifecycle** is invalid - Allowed values: *experimenting, developing, maintaining, deprecating, obsolete* -- Doc 10, Line 123, `API[content-mgmt-api-8]/spec` must have required property **system**. -- Doc 11, Line 140, `API[content-mgmt-api-11]/spec/system` is a string that cannot be empty. It should be populated or be removed completely if not required. -- Doc 12, Line 154, `API[content-mgmt-api-11]/spec/system` value **content-management** is invalid. +- Doc 10, Line 128, `API[content-mgmt-api-8]/spec` must have required property **system**. +- Doc 11, Line 145, `API[content-mgmt-api-11]/spec/system` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 12, Line 159, `API[content-mgmt-api-11]/spec/system` value **content-management** is invalid. - Expected Pattern: `system:[/]` e.g. **system:default/appointment-manager**, **system:appointment-manager** -- Doc 13, Line 169, `API[content-mgmt-api-13]/spec/owner` is a string that cannot be empty. It should be populated or be removed completely if not required. -- Doc 14, Line 187, `API[content-mgmt-api-14]/spec/owner` value **customization** is invalid. +- Doc 13, Line 174, `API[content-mgmt-api-13]/spec/owner` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 14, Line 192, `API[content-mgmt-api-14]/spec/owner` value **customization** is invalid. - Expected Pattern: `:[/]` e.g. **group:default/ce2**, **group:ce2**, **user:RyanHauert**, **user:default/RyanHauert** -- Doc 15, Line 198, `API[content-mgmt-api-15]/spec` must have required property **definition**. -- Doc 16, Line 216, `API[content-mgmt-api-16]/spec/definition` Is required and must be a string or an object with a $text, $json, or $yaml property. +- Doc 15, Line 203, `API[content-mgmt-api-15]/spec` must have required property **definition**. +- Doc 16, Line 221, `API[content-mgmt-api-16]/spec/definition` Is required and must be a string or an object with a $text, $json, or $yaml property. - See the [catalog info schema](https://github.com/im-open/validate-catalog-info/blob/main/schema/CatalogInfo.schema.json) for details and examples. -- Doc 17, Line 220, `API[content-mgmt-api-17]/metadata/addresses` is an object that cannot be empty. Addresses should be have one or more domains as the property name and a corresponding list of address objects as the value for each domain property. -- Doc 18, Line 235, `API[content-mgmt-api-18]/metadata/addresses/mktp.io` is an array that cannot be empty. It should contain at least one list item or be removed completely if not required. -- Doc 19, Line 251, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/0/subdomain` is a string that cannot be empty. It should be populated or be removed completely if not required. -- Doc 19, Line 251, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/1/path` is a string that cannot be empty. It should be populated or be removed completely if not required. -- Doc 19, Line 251, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/2/envs` is a string that cannot be empty. It should be populated or be removed completely if not required. -- Doc 19, Line 251, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/3/subdomain` cannot be empty if provided. -- Doc 19, Line 251, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/4/path` cannot be empty if provided. -- Doc 19, Line 251, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/5/envs` cannot be empty if provided. +- Doc 17, Line 230, `API[content-mgmt-api-17]/metadata/addresses` is an object that cannot be empty. Addresses should be have one or more domains as the property name and a corresponding list of address objects as the value for each domain property. +- Doc 18, Line 240, `API[content-mgmt-api-18]/metadata/addresses/mktp.io` is an array that cannot be empty. It should contain at least one list item or be removed completely if not required. +- Doc 19, Line 256, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/0/subdomain` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 19, Line 256, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/1/path` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 19, Line 256, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/2/envs` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 19, Line 256, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/3/subdomain` cannot be empty if provided. +- Doc 19, Line 256, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/4/path` cannot be empty if provided. +- Doc 19, Line 256, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/5/envs` cannot be empty if provided. diff --git a/test/expected-markdown/invalid-components.md b/test/expected-markdown/invalid-components.md index 06f5989..f0e627d 100644 --- a/test/expected-markdown/invalid-components.md +++ b/test/expected-markdown/invalid-components.md @@ -2,56 +2,56 @@ `./test/catalog-infos/invalid-components.yml` contains the following validation errors: -- Doc 3, Line 39, `Component[content-mfe-3]/metadata/deployment-environments` is an array that cannot be empty. It should contain at least one list item or be removed completely if not required. -- Doc 4, Line 52, `Component[content-mfe-4]/metadata/deployment-environments` must NOT have duplicate items (items 2 and 0 are identical). -- Doc 5, Line 69, `Component[content-mfe-5]/spec` is an object that cannot be empty. It should contain lifecycle, system, and type properties and may contain optional owner, subcomponentOf, providesApis, consumesApis and dependsOn props. -- Doc 6, Line 78, `Component[content-mfe-6]/spec` must have required property **type**. -- Doc 7, Line 91, `Component[content-mfe-7]/spec/type` value cannot be empty +- Doc 3, Line 44, `Component[content-mfe-3]/metadata/deployment-environments` is an array that cannot be empty. It should contain at least one list item or be removed completely if not required. +- Doc 4, Line 57, `Component[content-mfe-4]/metadata/deployment-environments` must NOT have duplicate items (items 2 and 0 are identical). +- Doc 5, Line 74, `Component[content-mfe-5]/spec` is an object that cannot be empty. It should contain lifecycle, system, and type properties and may contain optional owner, subcomponentOf, providesApis, consumesApis and dependsOn props. +- Doc 6, Line 83, `Component[content-mfe-6]/spec` must have required property **type**. +- Doc 7, Line 96, `Component[content-mfe-7]/spec/type` value cannot be empty - Allowed values: *service, library, documentation, tool, mfe, site* -- Doc 8, Line 103, `Component[content-mfe-8]/spec/type` value **InvalidResourceType** is invalid +- Doc 8, Line 108, `Component[content-mfe-8]/spec/type` value **InvalidResourceType** is invalid - Allowed values: *service, library, documentation, tool, mfe, site* -- Doc 9, Line 114, `Component[content-mfe-9]/spec` must have required property **system**. -- Doc 10, Line 128, `Component[content-mfe-10]/spec/system` value cannot be empty. +- Doc 9, Line 119, `Component[content-mfe-9]/spec` must have required property **system**. +- Doc 10, Line 133, `Component[content-mfe-10]/spec/system` value cannot be empty. - Expected Pattern: `system:[/]` e.g. **system:default/appointment-manager**, **system:appointment-manager** -- Doc 11, Line 140, `Component[content-mfe-11]/spec/system` value **content-management** is invalid. +- Doc 11, Line 145, `Component[content-mfe-11]/spec/system` value **content-management** is invalid. - Expected Pattern: `system:[/]` e.g. **system:default/appointment-manager**, **system:appointment-manager** -- Doc 12, Line 150, `Component[content-mfe-12]/spec` must have required property **lifecycle**. -- Doc 13, Line 165, `Component[content-mfe-13]/spec/lifecycle` value cannot be empty +- Doc 12, Line 155, `Component[content-mfe-12]/spec` must have required property **lifecycle**. +- Doc 13, Line 170, `Component[content-mfe-13]/spec/lifecycle` value cannot be empty - Allowed values: *experimenting, developing, maintaining, deprecating, obsolete* -- Doc 14, Line 177, `Component[content-mfe-14]/spec/lifecycle` value **prod** is invalid +- Doc 14, Line 182, `Component[content-mfe-14]/spec/lifecycle` value **prod** is invalid - Allowed values: *experimenting, developing, maintaining, deprecating, obsolete* -- Doc 15, Line 190, `Component[content-mfe-15]/spec/owner` is a string that cannot be empty. It should be populated or be removed completely if not required. -- Doc 16, Line 203, `Component[content-mfe-16]/spec/owner` value **customization** is invalid. +- Doc 15, Line 195, `Component[content-mfe-15]/spec/owner` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 16, Line 208, `Component[content-mfe-16]/spec/owner` value **customization** is invalid. - Expected Pattern: `:[/]` e.g. **group:default/customization**, **group:customization**, **user:RyanHauert**, **user:default/RyanHauert** -- Doc 17, Line 216, `Component[content-mfe-17]/spec/subcomponentOf` is a string that cannot be empty. It should be populated or be removed completely if not required. -- Doc 18, Line 229, `Component[content-mfe-18]/spec/subcomponentOf` value **content-management-db** is invalid. +- Doc 17, Line 221, `Component[content-mfe-17]/spec/subcomponentOf` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 18, Line 234, `Component[content-mfe-18]/spec/subcomponentOf` value **content-management-db** is invalid. - Expected Pattern: `component:[/]` e.g. **component:default/discover-mfe**, **component:discover-mfe** -- Doc 19, Line 241, `Component[content-mfe-19]/spec/providesApis` is an array that cannot be empty. It should contain at least one list item or be removed completely if not required. -- Doc 20, Line 254, `Component[content-mfe-20]/spec/providesApis/0` value cannot be empty. +- Doc 19, Line 246, `Component[content-mfe-19]/spec/providesApis` is an array that cannot be empty. It should contain at least one list item or be removed completely if not required. +- Doc 20, Line 259, `Component[content-mfe-20]/spec/providesApis/0` value cannot be empty. - Expected Pattern: `api:[/]` e.g. **api:default/appointment-manager-service**, **api:appointment-manager-service** -- Doc 20, Line 254, `Component[content-mfe-20]/spec/providesApis/1` value **content-management-db** is invalid. +- Doc 20, Line 259, `Component[content-mfe-20]/spec/providesApis/1` value **content-management-db** is invalid. - Expected Pattern: `api:[/]` e.g. **api:default/appointment-manager-service**, **api:appointment-manager-service** -- Doc 20, Line 254, `Component[content-mfe-20]/spec/providesApis/2` value **resource:default/content-management-db** is invalid. +- Doc 20, Line 259, `Component[content-mfe-20]/spec/providesApis/2` value **resource:default/content-management-db** is invalid. - Expected Pattern: `api:[/]` e.g. **api:default/appointment-manager-service**, **api:appointment-manager-service** -- Doc 21, Line 269, `Component[content-mfe-21]/spec/consumesApis` is an array that cannot be empty. It should contain at least one list item or be removed completely if not required. -- Doc 22, Line 282, `Component[content-mfe-22]/spec/consumesApis/0` value cannot be empty. +- Doc 21, Line 274, `Component[content-mfe-21]/spec/consumesApis` is an array that cannot be empty. It should contain at least one list item or be removed completely if not required. +- Doc 22, Line 287, `Component[content-mfe-22]/spec/consumesApis/0` value cannot be empty. - Expected Pattern: `api:[/]` e.g. **api:default/appointment-manager-service**, **api:appointment-manager-service** -- Doc 22, Line 282, `Component[content-mfe-22]/spec/consumesApis/1` value **content-management-db** is invalid. +- Doc 22, Line 287, `Component[content-mfe-22]/spec/consumesApis/1` value **content-management-db** is invalid. - Expected Pattern: `api:[/]` e.g. **api:default/appointment-manager-service**, **api:appointment-manager-service** -- Doc 22, Line 282, `Component[content-mfe-22]/spec/consumesApis/2` value **resource:default/content-management-db** is invalid. +- Doc 22, Line 287, `Component[content-mfe-22]/spec/consumesApis/2` value **resource:default/content-management-db** is invalid. - Expected Pattern: `api:[/]` e.g. **api:default/appointment-manager-service**, **api:appointment-manager-service** -- Doc 23, Line 297, `Component[content-mfe-23]/spec/dependsOn` is an array that cannot be empty. It should contain at least one list item or be removed completely if not required. -- Doc 24, Line 310, `Component[content-mfe-24]/spec/dependsOn/0` value cannot be empty. +- Doc 23, Line 302, `Component[content-mfe-23]/spec/dependsOn` is an array that cannot be empty. It should contain at least one list item or be removed completely if not required. +- Doc 24, Line 315, `Component[content-mfe-24]/spec/dependsOn/0` value cannot be empty. - Expected Pattern: `:[/]` e.g. **resource:default/launchdarkly**, **component:front-end-tooling-mfe** -- Doc 24, Line 310, `Component[content-mfe-24]/spec/dependsOn/1` value **content-management-db** is invalid. +- Doc 24, Line 315, `Component[content-mfe-24]/spec/dependsOn/1` value **content-management-db** is invalid. - Expected Pattern: `:[/]` e.g. **resource:default/launchdarkly**, **component:front-end-tooling-mfe** -- Doc 24, Line 310, `Component[content-mfe-24]/spec/dependsOn/2` value **group:default/customization** is invalid. +- Doc 24, Line 315, `Component[content-mfe-24]/spec/dependsOn/2` value **group:default/customization** is invalid. - Expected Pattern: `:[/]` e.g. **resource:default/launchdarkly**, **component:front-end-tooling-mfe** -- Doc 25, Line 317, `Component[content-mfe-25]/metadata/addresses` is an object that cannot be empty. Addresses should be have one or more domains as the property name and a corresponding list of address objects as the value for each domain property. -- Doc 26, Line 330, `Component[content-mfe-26]/metadata/addresses/mktp.io` is an array that cannot be empty. It should contain at least one list item or be removed completely if not required. -- Doc 27, Line 344, `Component[content-mfe-27]/metadata/addresses/mktp.io/0/subdomain` is a string that cannot be empty. It should be populated or be removed completely if not required. -- Doc 27, Line 344, `Component[content-mfe-27]/metadata/addresses/mktp.io/1/path` is a string that cannot be empty. It should be populated or be removed completely if not required. -- Doc 27, Line 344, `Component[content-mfe-27]/metadata/addresses/mktp.io/2/envs` is a string that cannot be empty. It should be populated or be removed completely if not required. -- Doc 27, Line 344, `Component[content-mfe-27]/metadata/addresses/mktp.io/3/subdomain` cannot be empty if provided. -- Doc 27, Line 344, `Component[content-mfe-27]/metadata/addresses/mktp.io/4/path` cannot be empty if provided. -- Doc 27, Line 344, `Component[content-mfe-27]/metadata/addresses/mktp.io/5/envs` cannot be empty if provided. +- Doc 25, Line 327, `Component[content-mfe-25]/metadata/addresses` is an object that cannot be empty. Addresses should be have one or more domains as the property name and a corresponding list of address objects as the value for each domain property. +- Doc 26, Line 335, `Component[content-mfe-26]/metadata/addresses/mktp.io` is an array that cannot be empty. It should contain at least one list item or be removed completely if not required. +- Doc 27, Line 349, `Component[content-mfe-27]/metadata/addresses/mktp.io/0/subdomain` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 27, Line 349, `Component[content-mfe-27]/metadata/addresses/mktp.io/1/path` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 27, Line 349, `Component[content-mfe-27]/metadata/addresses/mktp.io/2/envs` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 27, Line 349, `Component[content-mfe-27]/metadata/addresses/mktp.io/3/subdomain` cannot be empty if provided. +- Doc 27, Line 349, `Component[content-mfe-27]/metadata/addresses/mktp.io/4/path` cannot be empty if provided. +- Doc 27, Line 349, `Component[content-mfe-27]/metadata/addresses/mktp.io/5/envs` cannot be empty if provided. From 7778bf8ba6a846cb9cf5253a5a8036aad5ce5b34 Mon Sep 17 00:00:00 2001 From: Danielle Adams Date: Tue, 23 Jul 2024 10:35:48 -0600 Subject: [PATCH 3/6] ARCH-2126 - Update domain schema, test and results --- dist/index.js | 135 +++++++++++++-- schema/Domain.v1alpha1.schema.json | 93 ++++++++++- src/main.js | 6 +- src/validate.js | 54 +++++- test/catalog-infos/invalid-domains.yml | 193 ++++++++++++++++++++++ test/expected-markdown/invalid-domains.md | 28 +++- 6 files changed, 479 insertions(+), 30 deletions(-) diff --git a/dist/index.js b/dist/index.js index 33f2851..b14bf6c 100644 --- a/dist/index.js +++ b/dist/index.js @@ -29413,7 +29413,15 @@ var require_Domain_v1alpha1_schema = __commonJS({ kind: 'Domain', metadata: { name: 'front-end-tooling', - description: 'Tools and components to unify and streamline front-end development, browser performance, and consistency.' + description: 'Tools and components to unify and streamline front-end development, browser performance, and consistency.', + needs: { + 'print-vendor': 'to send printed materials', + telephony: 'to notify when there are calls in the queue' + }, + annotations: { + 'mktp.io/notes': 'Tools and components to unify and streamline front-end development.', + 'mktp.io/owners': 'Any additional info about ownership' + } }, spec: { owner: 'group:default/customization' @@ -29426,11 +29434,84 @@ var require_Domain_v1alpha1_schema = __commonJS({ }, { type: 'object', - required: ['spec'], + required: ['spec', 'metadata'], properties: { kind: { enum: ['Domain'] }, + metadata: { + type: 'object', + required: ['annotations'], + properties: { + needs: { + type: 'object', + description: + "A collection of key-value pairs of other domains and what this domain needs from them. \nKeys be up to 63 alphanumeric characters including '[-_.]'. Values are a string and markdown is supported.", + propertyNames: { + minLength: 1, + maxLength: 63, + pattern: '^([a-z0-9A-Z\\-\\_\\.]+)$', + $comment: "Expected Pattern: '[a-z0-9A-Z-_.]'", + examples: ['print-vendor', 'telephony'] + }, + additionalProperties: { + type: 'string', + minLength: 1, + description: + "Each entry should have a Domain key which represents the other domain that is needed and a string value that describes what is needed from the other domain. Markdown is supported.\nThe value should be worded to fill in a sentence like: 'This Domain needs the Other Domain to ___.'", + examples: [ + { + 'print-vendor': 'to send printed materials', + telephony: 'to notify when there are calls in the queue' + } + ] + }, + examples: [ + { + 'print-vendor': 'to send printed materials', + telephony: 'to notify when there are calls in the queue' + } + ], + $comment: + "Needs is a map of key-value pairs where the key is the string name of the domain that is needed and the value is a string that describes what is needed from that domain. The key cannot exceed 63 characters and can only contain alphanumeric values including '-', '_', and '.'. The value is a string and markdown is supported." + }, + annotations: { + type: 'object', + description: 'A collection of key-value pairs of non-identifying auxiliary information attached to the entity.', + required: ['mktp.io/notes'], + properties: { + 'mktp.io/notes': { + type: 'string', + description: + 'Long form notes about the responsibilities, scope, and other important details about the bounded context. Markdown is supported.', + examples: [ + 'Tools and components to unify and streamline front-end development.', + '\nThe source of truth for allocating time to handle customer appts.' + ], + minLength: 1 + }, + 'mktp.io/owners': { + type: 'string', + description: + 'Information regarding Domain ownership. Generally used only when ownership is unsettled. Markdown is supported.', + examples: [ + '## Unsettled Ownership\nOwnership is NOT settled. The apps that this context should own are currently stewarded by many teams.' + ], + minLength: 1 + } + }, + additionalProperties: true, + patternProperties: { + '^.+$': { + type: 'string' + } + }, + $comment: + "Annotations is a map of key-value pairs containing auxiliary information attached to the entity. For Domains, the 'mktp.io/notes' annotation is required and any other annotations are optional." + } + }, + $comment: 'Metadata is required and should contain the required annotations property and an optional needs property.' + }, spec: { type: 'object', required: ['type', 'owner'], @@ -29800,9 +29881,23 @@ var require_validate2 = __commonJS({ } const objArrayRegex = /\/\d{1,3}\/*.*/i; const errorObj = errorPath.replace(objArrayRegex, ''); - const propName = errorObj.substring(1, errorPath.length).replace(/\//gi, '_').replace(/-/gi, '_').toLowerCase(); - const lineNumber = jsonDoc.validationMetadata[propName] || jsonDoc.validationMetadata.doc; - return lineNumber; + const propName = errorObj.substring(1, errorPath.length).replace(/\//gi, '_').replace(/-/gi, '_').replace(/\./gi, '_').toLowerCase(); + const lineNumber = jsonDoc.validationMetadata[propName]; + if (lineNumber) { + return lineNumber; + } + let lineNum; + if (propName.includes('metadata_addresses')) { + lineNum = jsonDoc.validationMetadata['metadata_addresses']; + } else if (propName.includes('metadata_needs')) { + lineNum = jsonDoc.validationMetadata['metadata_needs']; + } else if (propName.includes('metadata_annotations')) { + lineNum = jsonDoc.validationMetadata['metadata_annotations']; + } + if (lineNum) { + return lineNum; + } + return jsonDoc.validationMetadata.doc; } function removeDuplicateishErrorFromList(errorsList, baseMsg) { const errorToRemove = errorsList.find(e => e.message.startsWith(baseMsg)); @@ -29831,8 +29926,9 @@ var require_validate2 = __commonJS({ const isValidAccordingToAjv = await validateWithAjvFunc(doc); if (isValidAccordingToAjv) return []; for (const ajvError of validateWithAjvFunc.errors) { - const lineNumber = getYamlLineNumberOfError(ajvError.instancePath, doc); - const itemId = `Doc ${docCount}, Line ${lineNumber}, \`${docId}${ajvError.instancePath}\``; + const instancePath = ajvError.instancePath.replace('mktp.io~1', 'mktp.io/'); + const lineNumber = getYamlLineNumberOfError(instancePath, doc); + const itemId = `Doc ${docCount}, Line ${lineNumber}, \`${docId}${instancePath}\``; const schemaComment = ajvError.parentSchema && ajvError.parentSchema.$comment ? ajvError.parentSchema.$comment : null; const hasData = isErrorDataPresent(ajvError.data); switch (ajvError.keyword) { @@ -29901,8 +29997,25 @@ ${schemaComment} e.g. '${examples}'`; const additionalMsg = `${itemId} cannot be extended with additional properties. '${ajvError.params.additionalProperty}' should be removed.`; errorsList.push({ line: lineNumber, message: additionalMsg }); break; + case 'propertyNames': + const maxLengthMsg = `${itemId} value '${ajvError.params.propertyName}' must NOT have more than`; + if (errorsList.find(e => e.line == lineNumber && e.message.startsWith(maxLengthMsg))) { + break; + } + const invalidValueMsg = `${itemId} value '${ajvError.params.propertyName}' is invalid.`; + if (errorsList.find(e => e.line == lineNumber && e.message.startsWith(invalidValueMsg))) { + errorsList = removeDuplicateishErrorFromList(errorsList, invalidValueMsg); + } + const propExamples = ajvError.schema.examples.join(`', '`); + const propertyNameMsg = `${itemId.slice(0, itemId.length - 1)}/${ajvError.params.propertyName}\` is invalid. +${ajvError.schema.$comment} e.g. '${propExamples}'`; + errorsList.push({ line: lineNumber, message: propertyNameMsg }); + break; default: - errorsList.push({ line: lineNumber, message: `Unhandled keyword - ${itemId} | ${ajvError.data} | ${ajvError.message}` }); + errorsList.push({ + line: lineNumber, + message: `Unhandled keyword (${ajvError.keyword}) - ${itemId} | ${ajvError.data} | ${ajvError.message}` + }); break; } } @@ -30040,7 +30153,7 @@ async function readFileAndPreserveLineNumbers(filename2) { const NEW_DOC = '---'; const METADATA = 'metadata:'; const SPEC = 'spec:'; - const API_VERSION = 'apiVersion:'; + const API_VERSION = 'apiversion:'; const KIND = 'kind:'; let i = 0; let lines = ['doc: 0']; @@ -30096,9 +30209,9 @@ validationMetadata: } else if (formattedLine.startsWith('addresses:')) { lines.push(`metadata_addresses: ${i}`); } else if (formattedLine.startsWith('mktp.io/notes:')) { - lines.push(`metadata_mktp_io_notes: ${i}`); + lines.push(`metadata_annotations_mktp_io_notes: ${i}`); } else if (formattedLine.startsWith('mktp.io/owners:')) { - lines.push(`metadata_mktp_io_owners: ${i}`); + lines.push(`metadata_annotations_mktp_io_owners: ${i}`); } else if (formattedLine.startsWith('needs:')) { lines.push(`metadata_needs: ${i}`); } diff --git a/schema/Domain.v1alpha1.schema.json b/schema/Domain.v1alpha1.schema.json index d25849a..e2a46af 100644 --- a/schema/Domain.v1alpha1.schema.json +++ b/schema/Domain.v1alpha1.schema.json @@ -9,7 +9,15 @@ "kind": "Domain", "metadata": { "name": "front-end-tooling", - "description": "Tools and components to unify and streamline front-end development, browser performance, and consistency." + "description": "Tools and components to unify and streamline front-end development, browser performance, and consistency.", + "needs": { + "print-vendor": "to send printed materials", + "telephony": "to notify when there are calls in the queue" + }, + "annotations": { + "mktp.io/notes": "Tools and components to unify and streamline front-end development.", + "mktp.io/owners": "Any additional info about ownership" + } }, "spec": { "owner": "group:default/customization" @@ -22,10 +30,89 @@ }, { "type": "object", - "required": ["spec"], + "required": [ + "spec", + "metadata" + ], "properties": { "kind": { - "enum": ["Domain"] + "enum": [ + "Domain" + ] + }, + "metadata": { + "type": "object", + "required": [ + "annotations" + ], + "properties": { + "needs": { + "type": "object", + "description": "A collection of key-value pairs of other domains and what this domain needs from them. \nKeys be up to 63 alphanumeric characters including '[-_.]'. Values are a string and markdown is supported.", + "propertyNames": { + "minLength": 1, + "maxLength": 63, + "pattern": "^([a-z0-9A-Z\\-\\_\\.]+)$", + "$comment": "Expected Pattern: '[a-z0-9A-Z-_.]'", + "examples": [ + "print-vendor", + "telephony" + ] + }, + "additionalProperties": { + "type": "string", + "minLength": 1, + "description": "Each entry should have a Domain key which represents the other domain that is needed and a string value that describes what is needed from the other domain. Markdown is supported.\nThe value should be worded to fill in a sentence like: 'This Domain needs the Other Domain to ___.'", + "examples": [ + { + "print-vendor": "to send printed materials", + "telephony": "to notify when there are calls in the queue" + } + ] + }, + "examples": [ + { + "print-vendor": "to send printed materials", + "telephony": "to notify when there are calls in the queue" + } + ], + "$comment": "Needs is a map of key-value pairs where the key is the string name of the domain that is needed and the value is a string that describes what is needed from that domain. The key cannot exceed 63 characters and can only contain alphanumeric values including '-', '_', and '.'. The value is a string and markdown is supported." + }, + "annotations": { + "type": "object", + "description": "A collection of key-value pairs of non-identifying auxiliary information attached to the entity.", + "required": [ + "mktp.io/notes" + ], + "properties": { + "mktp.io/notes": { + "type": "string", + "description": "Long form notes about the responsibilities, scope, and other important details about the bounded context. Markdown is supported.", + "examples": [ + "Tools and components to unify and streamline front-end development.", + "\nThe source of truth for allocating time to handle customer appts." + ], + "minLength": 1 + }, + "mktp.io/owners": { + "type": "string", + "description": "Information regarding Domain ownership. Generally used only when ownership is unsettled. Markdown is supported.", + "examples": [ + "## Unsettled Ownership\nOwnership is NOT settled. The apps that this context should own are currently stewarded by many teams." + ], + "minLength": 1 + } + }, + "additionalProperties": true, + "patternProperties": { + "^.+$": { + "type": "string" + } + }, + "$comment": "Annotations is a map of key-value pairs containing auxiliary information attached to the entity. For Domains, the 'mktp.io/notes' annotation is required and any other annotations are optional." + } + }, + "$comment": "Metadata is required and should contain the required annotations property and an optional needs property." }, "spec": { "type": "object", diff --git a/src/main.js b/src/main.js index ddc41b1..7ac1869 100644 --- a/src/main.js +++ b/src/main.js @@ -96,7 +96,7 @@ async function readFileAndPreserveLineNumbers(filename) { const NEW_DOC = '---'; const METADATA = 'metadata:'; const SPEC = 'spec:'; - const API_VERSION = 'apiVersion:'; + const API_VERSION = 'apiversion:'; const KIND = 'kind:'; let i = 0; @@ -168,9 +168,9 @@ validationMetadata: } else if (formattedLine.startsWith('addresses:')) { lines.push(`metadata_addresses: ${i}`); } else if (formattedLine.startsWith('mktp.io/notes:')) { - lines.push(`metadata_mktp_io_notes: ${i}`); + lines.push(`metadata_annotations_mktp_io_notes: ${i}`); } else if (formattedLine.startsWith('mktp.io/owners:')) { - lines.push(`metadata_mktp_io_owners: ${i}`); + lines.push(`metadata_annotations_mktp_io_owners: ${i}`); } else if (formattedLine.startsWith('needs:')) { lines.push(`metadata_needs: ${i}`); } diff --git a/src/validate.js b/src/validate.js index 724d5e5..68431d4 100644 --- a/src/validate.js +++ b/src/validate.js @@ -71,13 +71,32 @@ function getYamlLineNumberOfError(errorPath, jsonDoc) { .substring(1, errorPath.length) // Remove the leading / .replace(/\//gi, '_') // Change all / to _ .replace(/-/gi, '_') // Change - to _ + .replace(/\./gi, '_') // Change all . to _ .toLowerCase(); // Change everything to lower (just in case) - // If we process it and can't find the right line, default to using the line number + // See if we can find an exact match for the propName in the validationMetadata + const lineNumber = jsonDoc.validationMetadata[propName]; + if (lineNumber) { + return lineNumber; + } + + // Since there wasn't an exact line match see if we can find a match for the parent. + let lineNum; + if (propName.includes('metadata_addresses')) { + lineNum = jsonDoc.validationMetadata['metadata_addresses']; + } else if (propName.includes('metadata_needs')) { + lineNum = jsonDoc.validationMetadata['metadata_needs']; + } else if (propName.includes('metadata_annotations')) { + lineNum = jsonDoc.validationMetadata['metadata_annotations']; + } + if (lineNum) { + return lineNum; + } + + // If we process it and can't find the line or parent, default to using the line number // of the doc. This may happen if new items are added to the schema but the intial // loading function that preserves line numbers from the yaml file hasn't been updated. - const lineNumber = jsonDoc.validationMetadata[propName] || jsonDoc.validationMetadata.doc; - return lineNumber; + return jsonDoc.validationMetadata.doc; } function removeDuplicateishErrorFromList(errorsList, baseMsg) { @@ -112,8 +131,9 @@ async function validateSingleDoc(doc, docId, docCount, ajv) { if (isValidAccordingToAjv) return []; for (const ajvError of validateWithAjvFunc.errors) { - const lineNumber = getYamlLineNumberOfError(ajvError.instancePath, doc); - const itemId = `Doc ${docCount}, Line ${lineNumber}, \`${docId}${ajvError.instancePath}\``; + const instancePath = ajvError.instancePath.replace('mktp.io~1', 'mktp.io/'); // Happens when key is something like 'mktp.io/notes:' + const lineNumber = getYamlLineNumberOfError(instancePath, doc); + const itemId = `Doc ${docCount}, Line ${lineNumber}, \`${docId}${instancePath}\``; const schemaComment = ajvError.parentSchema && ajvError.parentSchema.$comment ? ajvError.parentSchema.$comment : null; const hasData = isErrorDataPresent(ajvError.data); @@ -191,8 +211,30 @@ async function validateSingleDoc(doc, docId, docCount, ajv) { const additionalMsg = `${itemId} cannot be extended with additional properties. '${ajvError.params.additionalProperty}' should be removed.`; errorsList.push({ line: lineNumber, message: additionalMsg }); break; + case 'propertyNames': + // If a maxLength was already created for this path, skip adding this + // propertynames message because it's less informative than that one. + const maxLengthMsg = `${itemId} value '${ajvError.params.propertyName}' must NOT have more than`; + if (errorsList.find(e => e.line == lineNumber && e.message.startsWith(maxLengthMsg))) { + break; + } + + // If there is already a generic-ish invalid value error message for this path, + // remove it. The message on this one is slightly better. + const invalidValueMsg = `${itemId} value '${ajvError.params.propertyName}' is invalid.`; + if (errorsList.find(e => e.line == lineNumber && e.message.startsWith(invalidValueMsg))) { + errorsList = removeDuplicateishErrorFromList(errorsList, invalidValueMsg); + } + + const propExamples = ajvError.schema.examples.join(`', '`); + const propertyNameMsg = `${itemId.slice(0, itemId.length - 1)}/${ajvError.params.propertyName}\` is invalid.\n${ajvError.schema.$comment} e.g. '${propExamples}'`; + errorsList.push({ line: lineNumber, message: propertyNameMsg }); + break; default: - errorsList.push({ line: lineNumber, message: `Unhandled keyword - ${itemId} | ${ajvError.data} | ${ajvError.message}` }); + errorsList.push({ + line: lineNumber, + message: `Unhandled keyword (${ajvError.keyword}) - ${itemId} | ${ajvError.data} | ${ajvError.message}` + }); break; } } diff --git a/test/catalog-infos/invalid-domains.yml b/test/catalog-infos/invalid-domains.yml index ab7d44d..4c2e1ee 100644 --- a/test/catalog-infos/invalid-domains.yml +++ b/test/catalog-infos/invalid-domains.yml @@ -6,6 +6,12 @@ apiVersion: backstage.io/v1alpha1 kind: Domain metadata: name: cm-domain + needs: + print-vendor: to send printed materials + telephony: to notify when there are calls in the queue + annotations: + mktp.io/notes: Tools and components to unify and streamline front-end development. + mktp.io/owners: Additional info about ownership of this domain. spec: type: Core owner: group:default/customization @@ -23,6 +29,8 @@ apiVersion: backstage.io/v1alpha1 kind: Domain metadata: name: cm-domain-3 + annotations: + mktp.io/notes: Managing content for all the domains spec: ... --- @@ -32,6 +40,8 @@ apiVersion: backstage.io/v1alpha1 kind: Domain metadata: name: cm-domain-4 + annotations: + mktp.io/notes: Managing content for all the domains spec: type: External ... @@ -41,6 +51,8 @@ apiVersion: backstage.io/v1alpha1 kind: Domain metadata: name: cm-domain-5 + annotations: + mktp.io/notes: Managing content for all the domains spec: owner: type: External @@ -51,6 +63,8 @@ apiVersion: backstage.io/v1alpha1 kind: Domain metadata: name: cm-domain-6 + annotations: + mktp.io/notes: Managing content for all the domains spec: owner: content-management type: Generic @@ -62,6 +76,8 @@ apiVersion: backstage.io/v1alpha1 kind: Domain metadata: name: cm-domain-7 + annotations: + mktp.io/notes: Managing content for all the domains spec: owner: group:default/content-management ... @@ -72,6 +88,8 @@ apiVersion: backstage.io/v1alpha1 kind: Domain metadata: name: cm-domain-8 + annotations: + mktp.io/notes: Managing content for all the domains spec: owner: group:default/content-management type: @@ -83,9 +101,184 @@ apiVersion: backstage.io/v1alpha1 kind: Domain metadata: name: cm-domain-9 + annotations: + mktp.io/notes: Managing content for all the domains spec: owner: group:default/content-management type: invalidThing ... --- +# Doc 10 - Missing metadata +apiVersion: backstage.io/v1alpha1 +kind: Domain +spec: + owner: group:default/content-management + type: Core +... +--- + +# Doc 11 - Empty metadata +apiVersion: backstage.io/v1alpha1 +kind: Domain +metadata: +spec: + owner: group:default/content-management + type: Core +... +--- + +# Doc 12 - Empty metadata.annotations +apiVersion: backstage.io/v1alpha1 +kind: Domain +metadata: + name: cm-domain-12 + annotations: +spec: + owner: group:default/content-management + type: Core +... +--- + +# Doc 13 - Missing metadata.annotations.mktp.io/notes +apiVersion: backstage.io/v1alpha1 +kind: Domain +metadata: + name: cm-domain-13 + annotations: + mktp.io/notes: +spec: + owner: group:default/content-management + type: Core +... +--- + +# Doc 14 - Empty metadata.annotations.mktp.io/notes +apiVersion: backstage.io/v1alpha1 +kind: Domain +metadata: + name: cm-domain-14 + annotations: + mktp.io/notes: '' +spec: + owner: group:default/content-management + type: Core +... +--- + +# Doc 15 - Missing metadata.annotations.mktp.io/owners +apiVersion: backstage.io/v1alpha1 +kind: Domain +metadata: + name: cm-domain-15 + annotations: + mktp.io/notes: >- + Notes for the domain. + mktp.io/owners: +spec: + owner: group:default/content-management + type: Core +... +--- + +# Doc 16 - Empty metadata.annotations.mktp.io/owners +apiVersion: backstage.io/v1alpha1 +kind: Domain +metadata: + name: cm-domain-16 + annotations: + mktp.io/notes: |- + *Notes* for the domain. + mktp.io/owners: '' +spec: + owner: group:default/content-management + type: Core +... +--- + +# Doc 17 - Empty metadata.needs +apiVersion: backstage.io/v1alpha1 +kind: Domain +metadata: + name: cm-domain-17 + annotations: + mktp.io/notes: '## Notes or the domain.' + needs: +spec: + owner: group:default/content-management + type: Core +... +--- + +# Doc 18 - metadata.needs key too long +apiVersion: backstage.io/v1alpha1 +kind: Domain +metadata: + name: cm-domain-18 + annotations: + mktp.io/notes: '## Notes or the domain.' + needs: + entity-names-can-only-be-63-characters-long-and-this-one-has--64: to send small content back +spec: + owner: group:default/content-management + type: Core +... +--- + +# Doc 19 - metadata.needs key with invalid characters +apiVersion: backstage.io/v1alpha1 +kind: Domain +metadata: + name: cm-domain-19 + annotations: + mktp.io/notes: '## Notes or the domain.' + needs: + domain-with-inv@lid-ch@rs: to send valid content back +spec: + owner: group:default/content-management + type: Core +... +--- + +# Doc 20 - metadata.needs value with missing value +apiVersion: backstage.io/v1alpha1 +kind: Domain +metadata: + name: cm-domain-20 + annotations: + mktp.io/notes: '## Notes or the domain.' + needs: + print-vendor: +spec: + owner: group:default/content-management + type: Core +... +--- +# Doc 21 - metadata.needs value with empty value +apiVersion: backstage.io/v1alpha1 +kind: Domain +metadata: + name: cm-domain-21 + annotations: + mktp.io/notes: '## Notes or the domain.' + needs: + print-vendor: '' +spec: + owner: group:default/content-management + type: Core +... +--- + +# Doc 22 - metadata.needs value with invalid type +apiVersion: backstage.io/v1alpha1 +kind: Domain +metadata: + name: cm-domain-22 + annotations: + mktp.io/notes: '## Notes or the domain.' + needs: + print-vendor: 123 +spec: + owner: group:default/content-management + type: Core +... diff --git a/test/expected-markdown/invalid-domains.md b/test/expected-markdown/invalid-domains.md index a44bbaf..e0a7ebe 100644 --- a/test/expected-markdown/invalid-domains.md +++ b/test/expected-markdown/invalid-domains.md @@ -2,13 +2,27 @@ `./test/catalog-infos/invalid-domains.yml` contains the following validation errors: -- Doc 3, Line 26, `Domain[cm-domain-3]/spec` is an object that cannot be empty. It should contain both owner and type properties. -- Doc 4, Line 35, `Domain[cm-domain-4]/spec` must have required property **owner**. -- Doc 5, Line 45, `Domain[cm-domain-5]/spec/owner` is a string that cannot be empty. It should be populated or be removed completely if not required. -- Doc 6, Line 55, `Domain[cm-domain-6]/spec/owner` value **content-management** is invalid. +- Doc 3, Line 34, `Domain[cm-domain-3]/spec` is an object that cannot be empty. It should contain both owner and type properties. +- Doc 4, Line 45, `Domain[cm-domain-4]/spec` must have required property **owner**. +- Doc 5, Line 57, `Domain[cm-domain-5]/spec/owner` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 6, Line 69, `Domain[cm-domain-6]/spec/owner` value **content-management** is invalid. - Expected Pattern: `:[/]` e.g. **group:default/customization**, **group:customization**, **user:RyanHauert**, **user:default/RyanHauert** -- Doc 7, Line 65, `Domain[cm-domain-7]/spec` must have required property **type**. -- Doc 8, Line 77, `Domain[cm-domain-8]/spec/type` value cannot be empty +- Doc 7, Line 81, `Domain[cm-domain-7]/spec` must have required property **type**. +- Doc 8, Line 95, `Domain[cm-domain-8]/spec/type` value cannot be empty - Allowed values: *Core, External, Generic, Supporting* -- Doc 9, Line 88, `Domain[cm-domain-9]/spec/type` value **invalidThing** is invalid +- Doc 9, Line 108, `Domain[cm-domain-9]/spec/type` value **invalidThing** is invalid - Allowed values: *Core, External, Generic, Supporting* +- Doc 10, Line 111, `Domain[Doc10]` must have required property **metadata**. +- Doc 11, Line 124, `Domain[Doc11]/metadata` is an object that cannot be empty. Metadata is required and should contain the required annotations property and an optional needs property. +- Doc 12, Line 136, `Domain[cm-domain-12]/metadata/annotations` is an object that cannot be empty. Annotations is a map of key-value pairs containing auxiliary information attached to the entity. For Domains, the **mktp.io/notes** annotation is required and any other annotations are optional. +- Doc 13, Line 149, `Domain[cm-domain-13]/metadata/annotations/mktp.io/notes` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 14, Line 162, `Domain[cm-domain-14]/metadata/annotations/mktp.io/notes` cannot be empty if provided. +- Doc 15, Line 177, `Domain[cm-domain-15]/metadata/annotations/mktp.io/owners` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 16, Line 192, `Domain[cm-domain-16]/metadata/annotations/mktp.io/owners` cannot be empty if provided. +- Doc 17, Line 206, `Domain[cm-domain-17]/metadata/needs` is an object that cannot be empty. Needs is a map of key-value pairs where the key is the string name of the domain that is needed and the value is a string that describes what is needed from that domain. The key cannot exceed 63 characters and can only contain alphanumeric values including **-**, **_**, and **.**. The value is a string and markdown is supported. +- Doc 18, Line 220, `Domain[cm-domain-18]/metadata/needs` value **entity-names-can-only-be-63-characters-long-and-this-one-has--64** must NOT have more than 63 characters. +- Doc 19, Line 235, `Domain[cm-domain-19]/metadata/needs/domain-with-inv@lid-ch@rs` is invalid. + - Expected Pattern: `[a-z0-9A-Z-_.]` e.g. **print-vendor**, **telephony** +- Doc 20, Line 250, `Domain[cm-domain-20]/metadata/needs/print-vendor` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 21, Line 264, `Domain[cm-domain-21]/metadata/needs/print-vendor` cannot be empty if provided. +- Doc 22, Line 279, `Domain[cm-domain-22]/metadata/needs/print-vendor` is a string that cannot be empty. It should be populated or be removed completely if not required. From 68a7c8572af8a3c772fc4ede4c070abcffb6e06b Mon Sep 17 00:00:00 2001 From: Danielle Adams Date: Tue, 23 Jul 2024 11:43:33 -0600 Subject: [PATCH 4/6] ARCH-2126 - Clean up other test files after validation changes --- .github/workflows/build-and-review-pr.yml | 1 + test/catalog-infos/valid-entities.yml | 16 ++++++++++++++++ test/catalog-infos/valid-entity.yml | 6 ++++++ test/expected-markdown/invalid-apis.md | 14 +++++++------- test/expected-markdown/invalid-components.md | 14 +++++++------- 5 files changed, 37 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build-and-review-pr.yml b/.github/workflows/build-and-review-pr.yml index 6c33d3c..774d1f3 100644 --- a/.github/workflows/build-and-review-pr.yml +++ b/.github/workflows/build-and-review-pr.yml @@ -34,6 +34,7 @@ env: jobs: build-and-review-pr: + if: 1 == 2 # This reusable workflow will check to see if an action's source code has changed based on # whether the PR includes files that match the files-with-code arg or are in one of the # dirs-with-code directories. If there are source code changes, this reusable workflow diff --git a/test/catalog-infos/valid-entities.yml b/test/catalog-infos/valid-entities.yml index 5bddbde..eb71331 100644 --- a/test/catalog-infos/valid-entities.yml +++ b/test/catalog-infos/valid-entities.yml @@ -3,6 +3,12 @@ apiVersion: backstage.io/v1alpha1 kind: Domain metadata: name: management-domain + needs: + print-vendor: to send printed materials + telephony: to notify when there are calls in the queue + annotations: + mktp.io/notes: Tools and components to unify and streamline front-end development. + mktp.io/owners: Additional info about ownership of this domain. spec: type: Core owner: group:default/customization @@ -27,6 +33,11 @@ metadata: - Dev - QA - Prod + addresses: + mktp.io: + - subdomain: api + path: / + envs: dev qa stage prod spec: type: service lifecycle: maintaining @@ -46,6 +57,11 @@ apiVersion: backstage.io/v1alpha1 kind: API metadata: name: content-mgmt-api + addresses: + mktp.io: + - subdomain: api + path: / + envs: dev qa stage prod spec: type: openapi lifecycle: maintaining diff --git a/test/catalog-infos/valid-entity.yml b/test/catalog-infos/valid-entity.yml index 918a6f6..4061044 100644 --- a/test/catalog-infos/valid-entity.yml +++ b/test/catalog-infos/valid-entity.yml @@ -5,6 +5,12 @@ apiVersion: backstage.io/v1alpha1 kind: Domain metadata: name: management-domain + needs: + print-vendor: to send printed materials + telephony: to notify when there are calls in the queue + annotations: + mktp.io/notes: Tools and components to unify and streamline front-end development. + mktp.io/owners: Additional info about ownership of this domain. spec: type: Core owner: group:default/customization diff --git a/test/expected-markdown/invalid-apis.md b/test/expected-markdown/invalid-apis.md index a2945e9..8726d80 100644 --- a/test/expected-markdown/invalid-apis.md +++ b/test/expected-markdown/invalid-apis.md @@ -24,10 +24,10 @@ - Doc 16, Line 221, `API[content-mgmt-api-16]/spec/definition` Is required and must be a string or an object with a $text, $json, or $yaml property. - See the [catalog info schema](https://github.com/im-open/validate-catalog-info/blob/main/schema/CatalogInfo.schema.json) for details and examples. - Doc 17, Line 230, `API[content-mgmt-api-17]/metadata/addresses` is an object that cannot be empty. Addresses should be have one or more domains as the property name and a corresponding list of address objects as the value for each domain property. -- Doc 18, Line 240, `API[content-mgmt-api-18]/metadata/addresses/mktp.io` is an array that cannot be empty. It should contain at least one list item or be removed completely if not required. -- Doc 19, Line 256, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/0/subdomain` is a string that cannot be empty. It should be populated or be removed completely if not required. -- Doc 19, Line 256, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/1/path` is a string that cannot be empty. It should be populated or be removed completely if not required. -- Doc 19, Line 256, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/2/envs` is a string that cannot be empty. It should be populated or be removed completely if not required. -- Doc 19, Line 256, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/3/subdomain` cannot be empty if provided. -- Doc 19, Line 256, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/4/path` cannot be empty if provided. -- Doc 19, Line 256, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/5/envs` cannot be empty if provided. +- Doc 18, Line 245, `API[content-mgmt-api-18]/metadata/addresses/mktp.io` is an array that cannot be empty. It should contain at least one list item or be removed completely if not required. +- Doc 19, Line 261, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/0/subdomain` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 19, Line 261, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/1/path` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 19, Line 261, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/2/envs` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 19, Line 261, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/3/subdomain` cannot be empty if provided. +- Doc 19, Line 261, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/4/path` cannot be empty if provided. +- Doc 19, Line 261, `API[content-mgmt-api-19]/metadata/addresses/mktp.io/5/envs` cannot be empty if provided. diff --git a/test/expected-markdown/invalid-components.md b/test/expected-markdown/invalid-components.md index f0e627d..8d13405 100644 --- a/test/expected-markdown/invalid-components.md +++ b/test/expected-markdown/invalid-components.md @@ -48,10 +48,10 @@ - Doc 24, Line 315, `Component[content-mfe-24]/spec/dependsOn/2` value **group:default/customization** is invalid. - Expected Pattern: `:[/]` e.g. **resource:default/launchdarkly**, **component:front-end-tooling-mfe** - Doc 25, Line 327, `Component[content-mfe-25]/metadata/addresses` is an object that cannot be empty. Addresses should be have one or more domains as the property name and a corresponding list of address objects as the value for each domain property. -- Doc 26, Line 335, `Component[content-mfe-26]/metadata/addresses/mktp.io` is an array that cannot be empty. It should contain at least one list item or be removed completely if not required. -- Doc 27, Line 349, `Component[content-mfe-27]/metadata/addresses/mktp.io/0/subdomain` is a string that cannot be empty. It should be populated or be removed completely if not required. -- Doc 27, Line 349, `Component[content-mfe-27]/metadata/addresses/mktp.io/1/path` is a string that cannot be empty. It should be populated or be removed completely if not required. -- Doc 27, Line 349, `Component[content-mfe-27]/metadata/addresses/mktp.io/2/envs` is a string that cannot be empty. It should be populated or be removed completely if not required. -- Doc 27, Line 349, `Component[content-mfe-27]/metadata/addresses/mktp.io/3/subdomain` cannot be empty if provided. -- Doc 27, Line 349, `Component[content-mfe-27]/metadata/addresses/mktp.io/4/path` cannot be empty if provided. -- Doc 27, Line 349, `Component[content-mfe-27]/metadata/addresses/mktp.io/5/envs` cannot be empty if provided. +- Doc 26, Line 340, `Component[content-mfe-26]/metadata/addresses/mktp.io` is an array that cannot be empty. It should contain at least one list item or be removed completely if not required. +- Doc 27, Line 354, `Component[content-mfe-27]/metadata/addresses/mktp.io/0/subdomain` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 27, Line 354, `Component[content-mfe-27]/metadata/addresses/mktp.io/1/path` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 27, Line 354, `Component[content-mfe-27]/metadata/addresses/mktp.io/2/envs` is a string that cannot be empty. It should be populated or be removed completely if not required. +- Doc 27, Line 354, `Component[content-mfe-27]/metadata/addresses/mktp.io/3/subdomain` cannot be empty if provided. +- Doc 27, Line 354, `Component[content-mfe-27]/metadata/addresses/mktp.io/4/path` cannot be empty if provided. +- Doc 27, Line 354, `Component[content-mfe-27]/metadata/addresses/mktp.io/5/envs` cannot be empty if provided. From 9b1eb2f6e50cdb8168ac402f408eaeafc2b4d8ff Mon Sep 17 00:00:00 2001 From: Danielle Adams Date: Tue, 23 Jul 2024 11:45:39 -0600 Subject: [PATCH 5/6] Remove the constraint on the build job. --- .github/workflows/build-and-review-pr.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build-and-review-pr.yml b/.github/workflows/build-and-review-pr.yml index 774d1f3..6c33d3c 100644 --- a/.github/workflows/build-and-review-pr.yml +++ b/.github/workflows/build-and-review-pr.yml @@ -34,7 +34,6 @@ env: jobs: build-and-review-pr: - if: 1 == 2 # This reusable workflow will check to see if an action's source code has changed based on # whether the PR includes files that match the files-with-code arg or are in one of the # dirs-with-code directories. If there are source code changes, this reusable workflow From 816e79a54656aff660043739b3ee17263eb1916b Mon Sep 17 00:00:00 2001 From: Danielle Adams Date: Tue, 23 Jul 2024 11:49:59 -0600 Subject: [PATCH 6/6] ARCH-2126 - Tweak readme instructions --- schema/README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/schema/README.md b/schema/README.md index 6b388f8..dd4246d 100644 --- a/schema/README.md +++ b/schema/README.md @@ -24,10 +24,9 @@ If new properties are added, removed, or modified the [catalog-info input files] The corresponding [expected-markdown] output may need to be regenerated as well. This can be done by: -1. Uncommenting the block of code that writes a markdown snippet to file -1. Running the action locally with the filename set to the modified test file -1. Verifying the new markdown looks correct -1. Replacing the contents in the expected markdown file with the newly generated snippet. +1. Running the action locally with the filename input set to the modified test file +1. Verifying the new markdown looks correct, it should be saved in `./errors-markdown.md` +1. Replacing the contents of the expected markdown file with the contents of `./errors-markdown.md` ## When Adding or Updating `object` Types