From 1d13d8fbc7e528075b59aa6edb744cce54c9e423 Mon Sep 17 00:00:00 2001 From: Yeliz Henden Date: Fri, 15 Aug 2025 12:03:08 +0100 Subject: [PATCH 01/13] feat(ipa):child path identifiers inherit parent path exceptions --- ...PA102CollectionIdentifierCamelCase.test.js | 16 ++++++++++ .../IPA102CollectionIdentifierPattern.test.js | 16 ++++++++++ ...tesBetweenResourceNameAndPathParam.test.js | 15 ++++++++++ .../IPA102CollectionIdentifierCamelCase.js | 12 ++++++-- .../IPA102CollectionIdentifierPattern.js | 7 ++++- ...ternatesBetweenResourceNameAndPathParam.js | 12 ++++++-- .../rulesets/functions/utils/exceptions.js | 29 +++++++++++++++++++ 7 files changed, 102 insertions(+), 5 deletions(-) diff --git a/tools/spectral/ipa/__tests__/IPA102CollectionIdentifierCamelCase.test.js b/tools/spectral/ipa/__tests__/IPA102CollectionIdentifierCamelCase.test.js index 4c8866c516..73bfe2893a 100644 --- a/tools/spectral/ipa/__tests__/IPA102CollectionIdentifierCamelCase.test.js +++ b/tools/spectral/ipa/__tests__/IPA102CollectionIdentifierCamelCase.test.js @@ -254,4 +254,20 @@ testRule('xgen-IPA-102-collection-identifier-camelCase', [ }, ], }, + { + name: 'child paths inherit parent exceptions', + document: { + paths: { + '/resource_groups': { + 'x-xgen-IPA-exception': { + 'xgen-IPA-102-collection-identifier-camelCase': 'Legacy API path that cannot be changed', + }, + }, + '/resource_groups/{id}': {}, + '/resource_groups/{id}/User-Profiles': {}, + '/resource_groups/{id}/User-Profiles/{profileId}': {}, + }, + }, + errors: [], + }, ]); diff --git a/tools/spectral/ipa/__tests__/IPA102CollectionIdentifierPattern.test.js b/tools/spectral/ipa/__tests__/IPA102CollectionIdentifierPattern.test.js index 8b9e7e8f0d..eb62131a16 100644 --- a/tools/spectral/ipa/__tests__/IPA102CollectionIdentifierPattern.test.js +++ b/tools/spectral/ipa/__tests__/IPA102CollectionIdentifierPattern.test.js @@ -89,4 +89,20 @@ testRule('xgen-IPA-102-collection-identifier-pattern', [ }, errors: [], }, + { + name: 'child paths inherit parent exceptions', + document: { + paths: { + '/resource-groups': { + 'x-xgen-IPA-exception': { + 'xgen-IPA-102-collection-identifier-pattern': 'Legacy API path that cannot be changed', + }, + }, + '/resource-groups/{id}': {}, + '/resource-groups/{id}/sub_resources': {}, + '/resource-groups/{id}/sub_resources/{subId}': {}, + }, + }, + errors: [], + }, ]); diff --git a/tools/spectral/ipa/__tests__/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.test.js b/tools/spectral/ipa/__tests__/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.test.js index 41a6e0cfbf..6cc8b32fbd 100644 --- a/tools/spectral/ipa/__tests__/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.test.js +++ b/tools/spectral/ipa/__tests__/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.test.js @@ -152,4 +152,19 @@ testRule('xgen-IPA-102-path-alternate-resource-name-path-param', [ }, errors: [], }, + { + name: 'child paths inherit parent exceptions', + document: { + paths: { + '/api/atlas/v2/resourceName1/resourceName2': { + 'x-xgen-IPA-exception': { + 'xgen-IPA-102-path-alternate-resource-name-path-param': 'parent exception reason', + }, + }, + '/api/atlas/v2/resourceName1/resourceName2/child': {}, + '/api/atlas/v2/resourceName1/resourceName2/child/{id}': {}, + }, + }, + errors: [], + }, ]); diff --git a/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js b/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js index ce1f039277..374a6f2f99 100644 --- a/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js +++ b/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js @@ -1,6 +1,10 @@ -import { evaluateAndCollectAdoptionStatus, handleInternalError } from './utils/collectionUtils.js'; +import { + evaluateAndCollectAdoptionStatus, + handleInternalError, +} from './utils/collectionUtils.js'; import { isPathParam } from './utils/componentUtils.js'; import { casing } from '@stoplight/spectral-functions'; +import { findExceptionInPathHierarchy } from './utils/exceptions.js'; const RULE_NAME = 'xgen-IPA-102-collection-identifier-camelCase'; const ERROR_MESSAGE = 'Collection identifiers must be in camelCase.'; @@ -21,7 +25,11 @@ export default (input, options, { path, documentInventory }) => { const violations = checkViolations(pathKey, path, ignoredValues); - return evaluateAndCollectAdoptionStatus(violations, RULE_NAME, oas.paths[input], path); + // Check for exceptions in path hierarchy + const pathWithException = findExceptionInPathHierarchy(oas, pathKey, RULE_NAME); + const objectToCheck = pathWithException ? oas.paths[pathWithException] : oas.paths[input]; + + return evaluateAndCollectAdoptionStatus(violations, RULE_NAME, objectToCheck, path); }; function checkViolations(pathKey, path, ignoredValues = []) { diff --git a/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierPattern.js b/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierPattern.js index 5aa57ee944..95d202e6b3 100644 --- a/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierPattern.js +++ b/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierPattern.js @@ -1,4 +1,5 @@ import { evaluateAndCollectAdoptionStatus } from './utils/collectionUtils.js'; +import { findExceptionInPathHierarchy } from './utils/exceptions.js'; const RULE_NAME = 'xgen-IPA-102-collection-identifier-pattern'; const ERROR_MESSAGE = @@ -17,7 +18,11 @@ export default (input, _, { path, documentInventory }) => { const violations = checkViolations(input, path); - return evaluateAndCollectAdoptionStatus(violations, RULE_NAME, oas.paths[input], path); + // Check for exceptions in path hierarchy + const pathWithException = findExceptionInPathHierarchy(oas, input, RULE_NAME); + const objectToCheck = pathWithException ? oas.paths[pathWithException] : oas.paths[input]; + + return evaluateAndCollectAdoptionStatus(violations, RULE_NAME, objectToCheck, path); }; function checkViolations(pathKey, path) { diff --git a/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js b/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js index 5d49b27023..5071c06eb7 100644 --- a/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js +++ b/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js @@ -1,6 +1,10 @@ import { isPathParam } from './utils/componentUtils.js'; -import { evaluateAndCollectAdoptionStatus, handleInternalError } from './utils/collectionUtils.js'; +import { + evaluateAndCollectAdoptionStatus, + handleInternalError, +} from './utils/collectionUtils.js'; import { AUTH_PREFIX, UNAUTH_PREFIX } from './utils/resourceEvaluation.js'; +import { findExceptionInPathHierarchy } from './utils/exceptions.js'; const RULE_NAME = 'xgen-IPA-102-path-alternate-resource-name-path-param'; const ERROR_MESSAGE = 'API paths must alternate between resource name and path params.'; @@ -37,7 +41,11 @@ export default (input, _, { path, documentInventory }) => { const errors = checkViolationsAndReturnErrors(suffixWithLeadingSlash, path); - return evaluateAndCollectAdoptionStatus(errors, RULE_NAME, oas.paths[input], path); + // Check for exceptions in path hierarchy + const pathWithException = findExceptionInPathHierarchy(oas, input, RULE_NAME); + const objectToCheck = pathWithException ? oas.paths[pathWithException] : oas.paths[input]; + + return evaluateAndCollectAdoptionStatus(errors, RULE_NAME, objectToCheck, path); }; function checkViolationsAndReturnErrors(suffixWithLeadingSlash, path) { diff --git a/tools/spectral/ipa/rulesets/functions/utils/exceptions.js b/tools/spectral/ipa/rulesets/functions/utils/exceptions.js index 256cab89dc..f87b38016b 100644 --- a/tools/spectral/ipa/rulesets/functions/utils/exceptions.js +++ b/tools/spectral/ipa/rulesets/functions/utils/exceptions.js @@ -13,3 +13,32 @@ export function hasException(object, ruleName) { } return false; } + +/** + * Finds an exception in the path hierarchy of an OpenAPI Specification (OAS) document + * for a specific rule name, starting from the current path and traversing up to parent paths. + * + * @param {object} oas - OpenAPI Specification document containing the paths. + * @param {string} currentPath - Current path to check for exceptions. + * @param {string} ruleName - Name of the rule for which the exception is being checked. + * @return {string|null} Returns the path where the exception is found, + * or null if no exception is found in the current path or its hierarchy. + */ +export function findExceptionInPathHierarchy(oas, currentPath, ruleName) { + // Check current path first + if (hasException(oas.paths[currentPath], ruleName)) { + return currentPath; + } + + // Check parent paths by removing segments from the end + const pathSegments = currentPath.split('/').filter(segment => segment !== ''); + + for (let i = pathSegments.length - 1; i > 0; i--) { + const parentPath = '/' + pathSegments.slice(0, i).join('/'); + if (oas.paths[parentPath] && hasException(oas.paths[parentPath], ruleName)) { + return parentPath; + } + } + + return null; +} \ No newline at end of file From dce329d70ee9cd5a60b8b4a1d65d6f73c637250d Mon Sep 17 00:00:00 2001 From: Yeliz Henden Date: Fri, 15 Aug 2025 12:19:06 +0100 Subject: [PATCH 02/13] prettier fix --- .../functions/IPA102CollectionIdentifierCamelCase.js | 5 +---- ...PA102EachPathAlternatesBetweenResourceNameAndPathParam.js | 5 +---- tools/spectral/ipa/rulesets/functions/utils/exceptions.js | 4 ++-- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js b/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js index 374a6f2f99..3b14917923 100644 --- a/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js +++ b/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js @@ -1,7 +1,4 @@ -import { - evaluateAndCollectAdoptionStatus, - handleInternalError, -} from './utils/collectionUtils.js'; +import { evaluateAndCollectAdoptionStatus, handleInternalError } from './utils/collectionUtils.js'; import { isPathParam } from './utils/componentUtils.js'; import { casing } from '@stoplight/spectral-functions'; import { findExceptionInPathHierarchy } from './utils/exceptions.js'; diff --git a/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js b/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js index 5071c06eb7..9b89c4ce55 100644 --- a/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js +++ b/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js @@ -1,8 +1,5 @@ import { isPathParam } from './utils/componentUtils.js'; -import { - evaluateAndCollectAdoptionStatus, - handleInternalError, -} from './utils/collectionUtils.js'; +import { evaluateAndCollectAdoptionStatus, handleInternalError } from './utils/collectionUtils.js'; import { AUTH_PREFIX, UNAUTH_PREFIX } from './utils/resourceEvaluation.js'; import { findExceptionInPathHierarchy } from './utils/exceptions.js'; diff --git a/tools/spectral/ipa/rulesets/functions/utils/exceptions.js b/tools/spectral/ipa/rulesets/functions/utils/exceptions.js index f87b38016b..38bba19502 100644 --- a/tools/spectral/ipa/rulesets/functions/utils/exceptions.js +++ b/tools/spectral/ipa/rulesets/functions/utils/exceptions.js @@ -31,7 +31,7 @@ export function findExceptionInPathHierarchy(oas, currentPath, ruleName) { } // Check parent paths by removing segments from the end - const pathSegments = currentPath.split('/').filter(segment => segment !== ''); + const pathSegments = currentPath.split('/').filter((segment) => segment !== ''); for (let i = pathSegments.length - 1; i > 0; i--) { const parentPath = '/' + pathSegments.slice(0, i).join('/'); @@ -41,4 +41,4 @@ export function findExceptionInPathHierarchy(oas, currentPath, ruleName) { } return null; -} \ No newline at end of file +} From 911bd0cf0935c4d8424940f5211594fee2b56b39 Mon Sep 17 00:00:00 2001 From: Yeliz Henden Date: Fri, 15 Aug 2025 15:00:10 +0100 Subject: [PATCH 03/13] address the comments --- ...PA102CollectionIdentifierCamelCase.test.js | 65 +++++++++++++++++++ .../IPA102CollectionIdentifierPattern.test.js | 60 +++++++++++++++++ ...tesBetweenResourceNameAndPathParam.test.js | 48 ++++++++++++++ .../__tests__/utils/collectionUtils.test.js | 2 - .../IPA102CollectionIdentifierCamelCase.js | 9 ++- .../IPA102CollectionIdentifierPattern.js | 11 +++- ...ternatesBetweenResourceNameAndPathParam.js | 17 ++++- .../functions/utils/collectionUtils.js | 13 ++-- .../rulesets/functions/utils/exceptions.js | 33 ++++++---- 9 files changed, 231 insertions(+), 27 deletions(-) diff --git a/tools/spectral/ipa/__tests__/IPA102CollectionIdentifierCamelCase.test.js b/tools/spectral/ipa/__tests__/IPA102CollectionIdentifierCamelCase.test.js index 73bfe2893a..3f62a10a6e 100644 --- a/tools/spectral/ipa/__tests__/IPA102CollectionIdentifierCamelCase.test.js +++ b/tools/spectral/ipa/__tests__/IPA102CollectionIdentifierCamelCase.test.js @@ -270,4 +270,69 @@ testRule('xgen-IPA-102-collection-identifier-camelCase', [ }, errors: [], }, + { + name: 'child paths have exceptions along with parent exceptions', + document: { + paths: { + '/resource_groups': { + 'x-xgen-IPA-exception': { + 'xgen-IPA-102-collection-identifier-camelCase': 'Legacy API path that cannot be changed', + }, + }, + '/resource_groups/{id}': { + 'x-xgen-IPA-exception': { + 'xgen-IPA-102-collection-identifier-camelCase': 'Legacy API path that cannot be changed', + }, + }, + '/resource_groups/{id}/User-Profiles': { + 'x-xgen-IPA-exception': { + 'xgen-IPA-102-collection-identifier-camelCase': 'Legacy API path that cannot be changed', + }, + }, + '/resource_groups/{id}/User-Profiles/{profileId}': { + 'x-xgen-IPA-exception': { + 'xgen-IPA-102-collection-identifier-camelCase': 'Legacy API path that cannot be changed', + }, + }, + }, + }, + errors: [ + { + code: 'xgen-IPA-102-collection-identifier-camelCase', + message: + 'This component adopts the rule and does not need an exception. Please remove the exception. https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-102-collection-identifier-camelCase', + path: [ + 'paths', + '/resource_groups/{id}', + 'x-xgen-IPA-exception', + 'xgen-IPA-102-collection-identifier-camelCase', + ], + severity: DiagnosticSeverity.Error, + }, + { + code: 'xgen-IPA-102-collection-identifier-camelCase', + message: + 'This component adopts the rule and does not need an exception. Please remove the exception. https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-102-collection-identifier-camelCase', + path: [ + 'paths', + '/resource_groups/{id}/User-Profiles', + 'x-xgen-IPA-exception', + 'xgen-IPA-102-collection-identifier-camelCase', + ], + severity: DiagnosticSeverity.Error, + }, + { + code: 'xgen-IPA-102-collection-identifier-camelCase', + message: + 'This component adopts the rule and does not need an exception. Please remove the exception. https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-102-collection-identifier-camelCase', + path: [ + 'paths', + '/resource_groups/{id}/User-Profiles/{profileId}', + 'x-xgen-IPA-exception', + 'xgen-IPA-102-collection-identifier-camelCase', + ], + severity: DiagnosticSeverity.Error, + }, + ], + }, ]); diff --git a/tools/spectral/ipa/__tests__/IPA102CollectionIdentifierPattern.test.js b/tools/spectral/ipa/__tests__/IPA102CollectionIdentifierPattern.test.js index eb62131a16..74b950692d 100644 --- a/tools/spectral/ipa/__tests__/IPA102CollectionIdentifierPattern.test.js +++ b/tools/spectral/ipa/__tests__/IPA102CollectionIdentifierPattern.test.js @@ -105,4 +105,64 @@ testRule('xgen-IPA-102-collection-identifier-pattern', [ }, errors: [], }, + { + name: 'child paths have exceptions along with parent exceptions', + document: { + paths: { + '/resource-groups': { + 'x-xgen-IPA-exception': { + 'xgen-IPA-102-collection-identifier-pattern': 'Legacy API path that cannot be changed', + }, + }, + '/resource-groups/{id}': { + 'x-xgen-IPA-exception': { + 'xgen-IPA-102-collection-identifier-pattern': 'Legacy API path that cannot be changed', + }, + }, + '/resource-groups/{id}/sub_resources': { + 'x-xgen-IPA-exception': { + 'xgen-IPA-102-collection-identifier-pattern': 'Legacy API path that cannot be changed', + }, + }, + '/resource-groups/{id}/sub_resources/{subId}': { + 'x-xgen-IPA-exception': { + 'xgen-IPA-102-collection-identifier-pattern': 'Legacy API path that cannot be changed', + }, + }, + }, + }, + errors: [ + { + code: 'xgen-IPA-102-collection-identifier-pattern', + message: + 'This component adopts the rule and does not need an exception. Please remove the exception. https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-102-collection-identifier-pattern', + path: ['paths', '/resource-groups/{id}', 'x-xgen-IPA-exception', 'xgen-IPA-102-collection-identifier-pattern'], + severity: DiagnosticSeverity.Error, + }, + { + code: 'xgen-IPA-102-collection-identifier-pattern', + message: + 'This component adopts the rule and does not need an exception. Please remove the exception. https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-102-collection-identifier-pattern', + path: [ + 'paths', + '/resource-groups/{id}/sub_resources', + 'x-xgen-IPA-exception', + 'xgen-IPA-102-collection-identifier-pattern', + ], + severity: DiagnosticSeverity.Error, + }, + { + code: 'xgen-IPA-102-collection-identifier-pattern', + message: + 'This component adopts the rule and does not need an exception. Please remove the exception. https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-102-collection-identifier-pattern', + path: [ + 'paths', + '/resource-groups/{id}/sub_resources/{subId}', + 'x-xgen-IPA-exception', + 'xgen-IPA-102-collection-identifier-pattern', + ], + severity: DiagnosticSeverity.Error, + }, + ], + }, ]); diff --git a/tools/spectral/ipa/__tests__/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.test.js b/tools/spectral/ipa/__tests__/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.test.js index 6cc8b32fbd..9bb8a2cc91 100644 --- a/tools/spectral/ipa/__tests__/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.test.js +++ b/tools/spectral/ipa/__tests__/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.test.js @@ -167,4 +167,52 @@ testRule('xgen-IPA-102-path-alternate-resource-name-path-param', [ }, errors: [], }, + { + name: 'child paths have exceptions along with parent exceptions', + document: { + paths: { + '/api/atlas/v2/resourceName1/resourceName2': { + 'x-xgen-IPA-exception': { + 'xgen-IPA-102-path-alternate-resource-name-path-param': 'parent exception reason', + }, + }, + '/api/atlas/v2/resourceName1/resourceName2/child': { + 'x-xgen-IPA-exception': { + 'xgen-IPA-102-path-alternate-resource-name-path-param': 'child exception reason', + }, + }, + '/api/atlas/v2/resourceName1/resourceName2/child/{id}': { + 'x-xgen-IPA-exception': { + 'xgen-IPA-102-path-alternate-resource-name-path-param': 'child exception reason', + }, + }, + }, + }, + errors: [ + { + code: 'xgen-IPA-102-path-alternate-resource-name-path-param', + message: + 'This component adopts the rule and does not need an exception. Please remove the exception. https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-102-path-alternate-resource-name-path-param', + path: [ + 'paths', + '/api/atlas/v2/resourceName1/resourceName2/child', + 'x-xgen-IPA-exception', + 'xgen-IPA-102-path-alternate-resource-name-path-param', + ], + severity: DiagnosticSeverity.Error, + }, + { + code: 'xgen-IPA-102-path-alternate-resource-name-path-param', + message: + 'This component adopts the rule and does not need an exception. Please remove the exception. https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-102-path-alternate-resource-name-path-param', + path: [ + 'paths', + '/api/atlas/v2/resourceName1/resourceName2/child/{id}', + 'x-xgen-IPA-exception', + 'xgen-IPA-102-path-alternate-resource-name-path-param', + ], + severity: DiagnosticSeverity.Error, + }, + ], + }, ]); diff --git a/tools/spectral/ipa/__tests__/utils/collectionUtils.test.js b/tools/spectral/ipa/__tests__/utils/collectionUtils.test.js index 7e7b9e516a..6e98fa5042 100644 --- a/tools/spectral/ipa/__tests__/utils/collectionUtils.test.js +++ b/tools/spectral/ipa/__tests__/utils/collectionUtils.test.js @@ -125,8 +125,6 @@ describe('tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js', () => expect(result[0].message).toEqual( 'This component adopts the rule and does not need an exception. Please remove the exception.' ); - expect(collector.add).toHaveBeenCalledTimes(1); - expect(collector.add).toHaveBeenCalledWith(TEST_ENTRY_TYPE.VIOLATION, testPath, testRuleName); }); }); diff --git a/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js b/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js index 3b14917923..14fdb038b3 100644 --- a/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js +++ b/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js @@ -9,6 +9,8 @@ const ERROR_MESSAGE = 'Collection identifiers must be in camelCase.'; /** * Checks if collection identifiers in paths follow camelCase convention * + * The function checks the entire path hierarchy. If any parent path has an exception, the exception will be inherited. + * * @param {object} input - The path key from the OpenAPI spec * @param {object} options - Rule configuration options * @param {object} context - The context object containing the path and documentInventory @@ -23,8 +25,11 @@ export default (input, options, { path, documentInventory }) => { const violations = checkViolations(pathKey, path, ignoredValues); // Check for exceptions in path hierarchy - const pathWithException = findExceptionInPathHierarchy(oas, pathKey, RULE_NAME); - const objectToCheck = pathWithException ? oas.paths[pathWithException] : oas.paths[input]; + const result = findExceptionInPathHierarchy(oas, pathKey, RULE_NAME, path); + if (result?.error) { + return result.error; + } + const objectToCheck = result ? oas.paths[result.parentPath] : oas.paths[input]; return evaluateAndCollectAdoptionStatus(violations, RULE_NAME, objectToCheck, path); }; diff --git a/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierPattern.js b/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierPattern.js index 95d202e6b3..701ba4fe93 100644 --- a/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierPattern.js +++ b/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierPattern.js @@ -9,9 +9,11 @@ const VALID_IDENTIFIER_PATTERN = /^[a-z][a-zA-Z0-9]*$/; /** * Checks if collection identifiers in paths begin with a lowercase letter and contain only ASCII letters and numbers * + * The function checks the entire path hierarchy. If any parent path has an exception, the exception will be inherited. + * * @param {object} input - The paths object from the OpenAPI spec * @param {object} _ - Unused - * @param {object} context - The context object containing the path + * @param {object} context - The context object containing the path and documentInventory */ export default (input, _, { path, documentInventory }) => { const oas = documentInventory.resolved; @@ -19,8 +21,11 @@ export default (input, _, { path, documentInventory }) => { const violations = checkViolations(input, path); // Check for exceptions in path hierarchy - const pathWithException = findExceptionInPathHierarchy(oas, input, RULE_NAME); - const objectToCheck = pathWithException ? oas.paths[pathWithException] : oas.paths[input]; + const result = findExceptionInPathHierarchy(oas, input, RULE_NAME, path); + if (result?.error) { + return result.error; + } + const objectToCheck = result ? oas.paths[result.parentPath] : oas.paths[input]; return evaluateAndCollectAdoptionStatus(violations, RULE_NAME, objectToCheck, path); }; diff --git a/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js b/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js index 9b89c4ce55..119a2bc29c 100644 --- a/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js +++ b/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js @@ -23,6 +23,15 @@ const validatePathStructure = (elements) => { }); }; +/** + * Checks if the resource identifier components alternate between collection identifiers and resourceIDs + * + * The function checks the entire path hierarchy. If any parent path has an exception, the exception will be inherited. + * + * @param {object} input - The path key from the OpenAPI spec + * @param {object} _ - Unused + * @param {object} context - The context object containing the path and documentInventory + */ export default (input, _, { path, documentInventory }) => { const oas = documentInventory.resolved; @@ -39,8 +48,12 @@ export default (input, _, { path, documentInventory }) => { const errors = checkViolationsAndReturnErrors(suffixWithLeadingSlash, path); // Check for exceptions in path hierarchy - const pathWithException = findExceptionInPathHierarchy(oas, input, RULE_NAME); - const objectToCheck = pathWithException ? oas.paths[pathWithException] : oas.paths[input]; + const result = findExceptionInPathHierarchy(oas, input, RULE_NAME, path); + if (result?.error) { + return result.error; + } + + const objectToCheck = result ? oas.paths[result.parentPath] : oas.paths[input]; return evaluateAndCollectAdoptionStatus(errors, RULE_NAME, objectToCheck, path); }; diff --git a/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js b/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js index c55ad9689c..d02d9e3ae0 100644 --- a/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js +++ b/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js @@ -1,5 +1,5 @@ import collector, { EntryType } from '../../../metrics/collector.js'; -import { EXCEPTION_EXTENSION, hasException } from './exceptions.js'; +import { EXCEPTION_EXTENSION, getUnnecessaryExceptionError, hasException } from './exceptions.js'; /** * Evaluates and collects adoptions, exceptions and violations based on the rule, evaluated object and the validation errors. @@ -21,12 +21,7 @@ export function evaluateAndCollectAdoptionStatus(validationErrors, ruleName, obj return collectAndReturnViolation(objectPath, ruleName, validationErrors); } if (hasException(object, ruleName)) { - return collectAndReturnViolation(objectPath, ruleName, [ - { - path: [...objectPath, EXCEPTION_EXTENSION, ruleName], - message: 'This component adopts the rule and does not need an exception. Please remove the exception.', - }, - ]); + return returnViolation(getUnnecessaryExceptionError(objectPath, ruleName)); } collectAdoption(objectPath, ruleName); } @@ -60,6 +55,10 @@ export function evaluateAndCollectAdoptionStatusWithoutExceptions(validationErro function collectAndReturnViolation(jsonPath, ruleName, errorData) { collector.add(EntryType.VIOLATION, jsonPath, ruleName); + return returnViolation(errorData); +} + +export function returnViolation(errorData) { if (typeof errorData === 'string') { return [{ message: errorData }]; } else if (Array.isArray(errorData)) { diff --git a/tools/spectral/ipa/rulesets/functions/utils/exceptions.js b/tools/spectral/ipa/rulesets/functions/utils/exceptions.js index 38bba19502..1edf519735 100644 --- a/tools/spectral/ipa/rulesets/functions/utils/exceptions.js +++ b/tools/spectral/ipa/rulesets/functions/utils/exceptions.js @@ -14,20 +14,28 @@ export function hasException(object, ruleName) { return false; } +export function getUnnecessaryExceptionError(objectPath, ruleName) { + return [ + { + path: [...objectPath, EXCEPTION_EXTENSION, ruleName], + message: 'This component adopts the rule and does not need an exception. Please remove the exception.', + }, + ]; +} + /** - * Finds an exception in the path hierarchy of an OpenAPI Specification (OAS) document - * for a specific rule name, starting from the current path and traversing up to parent paths. + * Finds an exception for a specified rule name in the current path or its parent paths within the given OpenAPI Specification (OAS) object. * - * @param {object} oas - OpenAPI Specification document containing the paths. - * @param {string} currentPath - Current path to check for exceptions. - * @param {string} ruleName - Name of the rule for which the exception is being checked. - * @return {string|null} Returns the path where the exception is found, - * or null if no exception is found in the current path or its hierarchy. + * @param {Object} oas - The OpenAPI Specification object containing path definitions. + * @param {string} currentPath - The path to start searching for exceptions. + * @param {string} ruleName - The name of the rule to check for exceptions. + * @param {string} jsonPath - The JSON path to the current operation or entity being checked. + * @return {string|null|Object} The parent path with the rule exception if found, or null if no exceptions exist. */ -export function findExceptionInPathHierarchy(oas, currentPath, ruleName) { - // Check current path first +export function findExceptionInPathHierarchy(oas, currentPath, ruleName, jsonPath) { + let currentPathHasException = false; if (hasException(oas.paths[currentPath], ruleName)) { - return currentPath; + currentPathHasException = true; } // Check parent paths by removing segments from the end @@ -36,7 +44,10 @@ export function findExceptionInPathHierarchy(oas, currentPath, ruleName) { for (let i = pathSegments.length - 1; i > 0; i--) { const parentPath = '/' + pathSegments.slice(0, i).join('/'); if (oas.paths[parentPath] && hasException(oas.paths[parentPath], ruleName)) { - return parentPath; + if (currentPathHasException) { + return { error: getUnnecessaryExceptionError(jsonPath, ruleName) }; + } + return { parentPath: parentPath }; } } From e2b25a041c4f0d9d15a32fac2d0927f707484cf4 Mon Sep 17 00:00:00 2001 From: Yeliz Henden Date: Fri, 15 Aug 2025 15:08:01 +0100 Subject: [PATCH 04/13] address the comments --- .../spectral/ipa/rulesets/functions/utils/collectionUtils.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js b/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js index d02d9e3ae0..eba0e27625 100644 --- a/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js +++ b/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js @@ -4,7 +4,7 @@ import { EXCEPTION_EXTENSION, getUnnecessaryExceptionError, hasException } from /** * Evaluates and collects adoptions, exceptions and violations based on the rule, evaluated object and the validation errors. * If the object is violating the rule, but has an exception, the validation error is ignored - * If the object is adopting the rule, but has an exception, a validation error will be returned + * If the object is adopting the rule, but has an exception, an unnecessary exception error is returned, but the object is counted as adopting the rule * * @param {Array<{path: Array, message: string}>} validationErrors the error results from the rule * @param {string} ruleName the name of the rule @@ -20,10 +20,11 @@ export function evaluateAndCollectAdoptionStatus(validationErrors, ruleName, obj } return collectAndReturnViolation(objectPath, ruleName, validationErrors); } + collectAdoption(objectPath, ruleName); + if (hasException(object, ruleName)) { return returnViolation(getUnnecessaryExceptionError(objectPath, ruleName)); } - collectAdoption(objectPath, ruleName); } /** From c632cd64bb49965971bd451cd2de2ecf469c0804 Mon Sep 17 00:00:00 2001 From: Yeliz Henden Date: Fri, 15 Aug 2025 15:10:21 +0100 Subject: [PATCH 05/13] address the comments --- .../functions/IPA102CollectionIdentifierCamelCase.js | 9 ++++++--- .../functions/IPA102CollectionIdentifierPattern.js | 4 ++-- ...2EachPathAlternatesBetweenResourceNameAndPathParam.js | 9 ++++++--- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js b/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js index 14fdb038b3..08a5fcf444 100644 --- a/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js +++ b/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js @@ -1,4 +1,7 @@ -import { evaluateAndCollectAdoptionStatus, handleInternalError } from './utils/collectionUtils.js'; +import { + evaluateAndCollectAdoptionStatus, + handleInternalError, +} from './utils/collectionUtils.js'; import { isPathParam } from './utils/componentUtils.js'; import { casing } from '@stoplight/spectral-functions'; import { findExceptionInPathHierarchy } from './utils/exceptions.js'; @@ -29,9 +32,9 @@ export default (input, options, { path, documentInventory }) => { if (result?.error) { return result.error; } - const objectToCheck = result ? oas.paths[result.parentPath] : oas.paths[input]; + const objectToCheckForException = result ? oas.paths[result.parentPath] : oas.paths[input]; - return evaluateAndCollectAdoptionStatus(violations, RULE_NAME, objectToCheck, path); + return evaluateAndCollectAdoptionStatus(violations, RULE_NAME, objectToCheckForException, path); }; function checkViolations(pathKey, path, ignoredValues = []) { diff --git a/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierPattern.js b/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierPattern.js index 701ba4fe93..40bba90d2e 100644 --- a/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierPattern.js +++ b/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierPattern.js @@ -25,9 +25,9 @@ export default (input, _, { path, documentInventory }) => { if (result?.error) { return result.error; } - const objectToCheck = result ? oas.paths[result.parentPath] : oas.paths[input]; + const objectToCheckForException = result ? oas.paths[result.parentPath] : oas.paths[input]; - return evaluateAndCollectAdoptionStatus(violations, RULE_NAME, objectToCheck, path); + return evaluateAndCollectAdoptionStatus(violations, RULE_NAME, objectToCheckForException, path); }; function checkViolations(pathKey, path) { diff --git a/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js b/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js index 119a2bc29c..260eddb3bb 100644 --- a/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js +++ b/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js @@ -1,5 +1,8 @@ import { isPathParam } from './utils/componentUtils.js'; -import { evaluateAndCollectAdoptionStatus, handleInternalError } from './utils/collectionUtils.js'; +import { + evaluateAndCollectAdoptionStatus, + handleInternalError, +} from './utils/collectionUtils.js'; import { AUTH_PREFIX, UNAUTH_PREFIX } from './utils/resourceEvaluation.js'; import { findExceptionInPathHierarchy } from './utils/exceptions.js'; @@ -53,9 +56,9 @@ export default (input, _, { path, documentInventory }) => { return result.error; } - const objectToCheck = result ? oas.paths[result.parentPath] : oas.paths[input]; + const objectToCheckForException = result ? oas.paths[result.parentPath] : oas.paths[input]; - return evaluateAndCollectAdoptionStatus(errors, RULE_NAME, objectToCheck, path); + return evaluateAndCollectAdoptionStatus(errors, RULE_NAME, objectToCheckForException, path); }; function checkViolationsAndReturnErrors(suffixWithLeadingSlash, path) { From b9d5607f39e8048da8d67d7210518dec00d63108 Mon Sep 17 00:00:00 2001 From: Yeliz Henden Date: Fri, 15 Aug 2025 15:15:01 +0100 Subject: [PATCH 06/13] address the comments --- tools/spectral/ipa/rulesets/IPA-102.yaml | 4 ++++ tools/spectral/ipa/rulesets/README.md | 3 +++ 2 files changed, 7 insertions(+) diff --git a/tools/spectral/ipa/rulesets/IPA-102.yaml b/tools/spectral/ipa/rulesets/IPA-102.yaml index 82cb3ab0e1..d573295097 100644 --- a/tools/spectral/ipa/rulesets/IPA-102.yaml +++ b/tools/spectral/ipa/rulesets/IPA-102.yaml @@ -16,6 +16,7 @@ rules: argument to the rule - Paths with `x-xgen-IPA-exception` for this rule are excluded from validation - Double slashes (//) are not allowed in paths + - If any parent path has an exception for this rule, the exception will be inherited. message: '{{error}} https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-102-collection-identifier-camelCase' severity: error @@ -38,6 +39,8 @@ rules: - Even-indexed path segments should be resource names (not path parameters) - Odd-indexed path segments should be path parameters - Paths with `x-xgen-IPA-exception` for this rule are excluded from validation + - If any parent path has an exception for this rule, the exception will be inherited. + message: '{{error}} https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-102-path-alternate-resource-name-path-param' severity: error given: '$.paths' @@ -57,6 +60,7 @@ rules: - Custom methods (segments containing colons) are excluded from validation - Paths with `x-xgen-IPA-exception` for this rule are excluded from validation - Each non-parameter path segment must start with a lowercase letter followed by any combination of ASCII letters and numbers + - If any parent path has an exception for this rule, the exception will be inherited. message: '{{error}} https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-102-collection-identifier-pattern' severity: error diff --git a/tools/spectral/ipa/rulesets/README.md b/tools/spectral/ipa/rulesets/README.md index 0f58a44dd1..91273ff0cc 100644 --- a/tools/spectral/ipa/rulesets/README.md +++ b/tools/spectral/ipa/rulesets/README.md @@ -44,6 +44,7 @@ Collection identifiers must be in camelCase. argument to the rule - Paths with `x-xgen-IPA-exception` for this rule are excluded from validation - Double slashes (//) are not allowed in paths + - If any parent path has an exception for this rule, the exception will be inherited. #### xgen-IPA-102-path-alternate-resource-name-path-param @@ -57,6 +58,7 @@ Rule checks for the following conditions: - Even-indexed path segments should be resource names (not path parameters) - Odd-indexed path segments should be path parameters - Paths with `x-xgen-IPA-exception` for this rule are excluded from validation + - If any parent path has an exception for this rule, the exception will be inherited. #### xgen-IPA-102-collection-identifier-pattern @@ -71,6 +73,7 @@ Rule checks for the following conditions: - Custom methods (segments containing colons) are excluded from validation - Paths with `x-xgen-IPA-exception` for this rule are excluded from validation - Each non-parameter path segment must start with a lowercase letter followed by any combination of ASCII letters and numbers + - If any parent path has an exception for this rule, the exception will be inherited. From 6baf7064a3c6267eab0587fd9d3fff07315428b9 Mon Sep 17 00:00:00 2001 From: Yeliz Henden Date: Fri, 15 Aug 2025 15:57:08 +0100 Subject: [PATCH 07/13] ci fixes --- tools/spectral/ipa/ipa-spectral.yaml | 13 ++++++++++++- .../IPA102CollectionIdentifierCamelCase.js | 5 +---- ...PathAlternatesBetweenResourceNameAndPathParam.js | 5 +---- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/tools/spectral/ipa/ipa-spectral.yaml b/tools/spectral/ipa/ipa-spectral.yaml index 6dd8bde3a4..84d648d075 100644 --- a/tools/spectral/ipa/ipa-spectral.yaml +++ b/tools/spectral/ipa/ipa-spectral.yaml @@ -58,7 +58,7 @@ overrides: - '**#/paths/~1rest~1unauth~1version' # external reference, to be covered by CLOUDP-309694 rules: xgen-IPA-114-error-responses-refer-to-api-error: 'off' - - files: + - files: # To be removed in CLOUDP-338425 - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1%7BclusterView%7D~1%7BdatabaseName%7D~1%7BcollectionName%7D~1collStats~1measurements' # reference to support future investigation - CLOUDP-310775 - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1processes~1%7BprocessId%7D~1%7BdatabaseName%7D~1%7BcollectionName%7D~1collStats~1measurements' # reference to support future investigation - CLOUDP-310775 - '**#/components/schemas/HostMetricValue' # reference to support future investigation - CLOUDP-310775 @@ -177,3 +177,14 @@ overrides: - '**#/components/schemas/NewRelic' rules: xgen-IPA-117-description-must-not-use-html: 'off' + - files: # To be removed in CLOUDP-338425 + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1backup~1exportBuckets~1%7BexportBucketId%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1exports~1%7BexportId%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1restoreJobs~1%7BrestoreJobId%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1snapshots~1%7BsnapshotId%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1snapshots~1shardedCluster~1%7BsnapshotId%7D" + - "**#/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1snapshots~1shardedClusters" + - "**#/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1tenant~1restores~1%7BrestoreId%7D" + - "**#/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1tenant~1snapshots~1%7BsnapshotId%7D" + rules: + xgen-IPA-102-path-alternate-resource-name-path-param: 'off' diff --git a/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js b/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js index 08a5fcf444..1a9e1930d8 100644 --- a/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js +++ b/tools/spectral/ipa/rulesets/functions/IPA102CollectionIdentifierCamelCase.js @@ -1,7 +1,4 @@ -import { - evaluateAndCollectAdoptionStatus, - handleInternalError, -} from './utils/collectionUtils.js'; +import { evaluateAndCollectAdoptionStatus, handleInternalError } from './utils/collectionUtils.js'; import { isPathParam } from './utils/componentUtils.js'; import { casing } from '@stoplight/spectral-functions'; import { findExceptionInPathHierarchy } from './utils/exceptions.js'; diff --git a/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js b/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js index 260eddb3bb..85891cce38 100644 --- a/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js +++ b/tools/spectral/ipa/rulesets/functions/IPA102EachPathAlternatesBetweenResourceNameAndPathParam.js @@ -1,8 +1,5 @@ import { isPathParam } from './utils/componentUtils.js'; -import { - evaluateAndCollectAdoptionStatus, - handleInternalError, -} from './utils/collectionUtils.js'; +import { evaluateAndCollectAdoptionStatus, handleInternalError } from './utils/collectionUtils.js'; import { AUTH_PREFIX, UNAUTH_PREFIX } from './utils/resourceEvaluation.js'; import { findExceptionInPathHierarchy } from './utils/exceptions.js'; From ebee416cc156c2571d8ecbe8bd74a268fb01b981 Mon Sep 17 00:00:00 2001 From: Yeliz Henden Date: Fri, 15 Aug 2025 15:59:00 +0100 Subject: [PATCH 08/13] ci fixes --- tools/spectral/ipa/ipa-spectral.yaml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/spectral/ipa/ipa-spectral.yaml b/tools/spectral/ipa/ipa-spectral.yaml index 84d648d075..7055009900 100644 --- a/tools/spectral/ipa/ipa-spectral.yaml +++ b/tools/spectral/ipa/ipa-spectral.yaml @@ -178,13 +178,13 @@ overrides: rules: xgen-IPA-117-description-must-not-use-html: 'off' - files: # To be removed in CLOUDP-338425 - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1backup~1exportBuckets~1%7BexportBucketId%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1exports~1%7BexportId%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1restoreJobs~1%7BrestoreJobId%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1snapshots~1%7BsnapshotId%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1snapshots~1shardedCluster~1%7BsnapshotId%7D" - - "**#/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1snapshots~1shardedClusters" - - "**#/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1tenant~1restores~1%7BrestoreId%7D" - - "**#/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1tenant~1snapshots~1%7BsnapshotId%7D" + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1backup~1exportBuckets~1%7BexportBucketId%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1exports~1%7BexportId%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1restoreJobs~1%7BrestoreJobId%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1snapshots~1%7BsnapshotId%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1snapshots~1shardedCluster~1%7BsnapshotId%7D' + - '**#/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1snapshots~1shardedClusters' + - '**#/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1tenant~1restores~1%7BrestoreId%7D' + - '**#/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1tenant~1snapshots~1%7BsnapshotId%7D' rules: xgen-IPA-102-path-alternate-resource-name-path-param: 'off' From 8f69c7ae39640cb2ae5e71c18a92a784047a6742 Mon Sep 17 00:00:00 2001 From: Yeliz Henden Date: Fri, 15 Aug 2025 16:04:41 +0100 Subject: [PATCH 09/13] ci fixes --- tools/spectral/ipa/ipa-spectral.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/spectral/ipa/ipa-spectral.yaml b/tools/spectral/ipa/ipa-spectral.yaml index 7055009900..8cf627bd99 100644 --- a/tools/spectral/ipa/ipa-spectral.yaml +++ b/tools/spectral/ipa/ipa-spectral.yaml @@ -183,8 +183,8 @@ overrides: - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1restoreJobs~1%7BrestoreJobId%7D' - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1snapshots~1%7BsnapshotId%7D' - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1snapshots~1shardedCluster~1%7BsnapshotId%7D' - - '**#/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1snapshots~1shardedClusters' - - '**#/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1tenant~1restores~1%7BrestoreId%7D' - - '**#/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1tenant~1snapshots~1%7BsnapshotId%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1snapshots~1shardedClusters' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1tenant~1restores~1%7BrestoreId%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1tenant~1snapshots~1%7BsnapshotId%7D' rules: xgen-IPA-102-path-alternate-resource-name-path-param: 'off' From ba48a6d7d922e4f9e61df96f23e9d910a6b2eb51 Mon Sep 17 00:00:00 2001 From: Yeliz Henden Date: Fri, 15 Aug 2025 16:29:20 +0100 Subject: [PATCH 10/13] ci fixes --- tools/spectral/ipa/ipa-spectral.yaml | 27 +++++++++++++++++++++++++++ tools/spectral/ipa/package.json | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/tools/spectral/ipa/ipa-spectral.yaml b/tools/spectral/ipa/ipa-spectral.yaml index 8cf627bd99..88a47919cb 100644 --- a/tools/spectral/ipa/ipa-spectral.yaml +++ b/tools/spectral/ipa/ipa-spectral.yaml @@ -186,5 +186,32 @@ overrides: - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1snapshots~1shardedClusters' - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1tenant~1restores~1%7BrestoreId%7D' - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1tenant~1snapshots~1%7BsnapshotId%7D' + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1fts~1indexes~1%7BdatabaseName%7D~1%7BcollectionName%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1fts~1indexes~1%7BindexId%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1search~1indexes~1%7BdatabaseName%7D~1%7BcollectionName%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1search~1indexes~1%7BdatabaseName%7D~1%7BcollectionName%7D~1%7BindexName%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1search~1indexes~1%7BindexId%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1customDBRoles~1roles~1%7BroleName%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1flexClusters~1%7Bname%7D~1backup~1restoreJobs~1%7BrestoreJobId%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1flexClusters~1%7Bname%7D~1backup~1snapshots~1%7BsnapshotId%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1hosts~1%7BprocessId%7D~1fts~1metrics~1measurements" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1privateEndpoint~1serverless~1instance~1%7BinstanceName%7D~1endpoint~1%7BendpointId%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1privateNetworkSettings~1endpointIds~1%7BendpointId%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1serverless~1%7BclusterName%7D~1backup~1restoreJobs~1%7BrestoreJobId%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1serverless~1%7BclusterName%7D~1backup~1snapshots~1%7BsnapshotId%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1streams~1privateLinkConnections~1%7BconnectionId%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1streams~1vpcPeeringConnections~1%7Bid%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1streams~1vpcPeeringConnections~1%7Bid%7D%3Aaccept" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1streams~1vpcPeeringConnections~1%7Bid%7D%3Areject" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1userSecurity~1ldap~1verify~1%7BrequestId%7D" + - "**#/paths/~1api~1atlas~1v2~1orgs~1%7BorgId%7D~1billing~1costExplorer~1usage~1%7Btoken%7D" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1hosts~1%7BprocessId%7D~1fts~1metrics~1indexes~1%7BdatabaseName%7D~1%7BcollectionName%7D~1measurements" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1hosts~1%7BprocessId%7D~1fts~1metrics~1indexes~1%7BdatabaseName%7D~1%7BcollectionName%7D~1%7BindexName%7D~1measurements" + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1liveMigrations~1validate~1%7BvalidationId%7D" rules: xgen-IPA-102-path-alternate-resource-name-path-param: 'off' + - files: # To be removed in CLOUDP-338425 + - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1customDBRoles~1roles~1%7BroleName%7D" + rules: + xgen-IPA-102-collection-identifier-camelCase: 'off' + diff --git a/tools/spectral/ipa/package.json b/tools/spectral/ipa/package.json index cc60748482..e55e966c7e 100644 --- a/tools/spectral/ipa/package.json +++ b/tools/spectral/ipa/package.json @@ -1,6 +1,6 @@ { "name": "@mongodb-js/ipa-validation-ruleset", - "version": "1.1.0", + "version": "2.0.1", "description": "Custom validation rules for MongoDB API Standards (IPA).", "keywords": [ "mongodb", From 2bb010bd7bf9273f95f07476be5b3f159dcbb316 Mon Sep 17 00:00:00 2001 From: Yeliz Henden Date: Fri, 15 Aug 2025 16:54:04 +0100 Subject: [PATCH 11/13] ci fixes --- tools/spectral/ipa/package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/spectral/ipa/package.json b/tools/spectral/ipa/package.json index e55e966c7e..0df575d6fa 100644 --- a/tools/spectral/ipa/package.json +++ b/tools/spectral/ipa/package.json @@ -1,6 +1,6 @@ { "name": "@mongodb-js/ipa-validation-ruleset", - "version": "2.0.1", + "version": "2.0.0", "description": "Custom validation rules for MongoDB API Standards (IPA).", "keywords": [ "mongodb", @@ -19,8 +19,8 @@ "author": "MongoDB", "main": "ipa-spectral.yaml", "type": "module", - "scripts" : { - "gen-ipa-changelog" : "npx auto-changelog" + "scripts": { + "gen-ipa-changelog": "npx auto-changelog" }, "dependencies": { "@stoplight/spectral-cli": "6.15.0", @@ -36,7 +36,7 @@ "devDependencies": { "auto-changelog": "2.5.0" }, - "auto-changelog" : { + "auto-changelog": { "package": true, "commitPattern": "[a-z]+\\(ipa\\):", "startingVersion": "ipa-validation-ruleset-v1.0.0", @@ -44,7 +44,7 @@ "tagPattern": "ipa-validation-ruleset-v\\d+\\.\\d+\\.\\d+", "tagPrefix": "ipa-validation-ruleset-v", "ignoreCommitPattern": "^ci.*$", - "hideEmptyReleases" : true, + "hideEmptyReleases": true, "contributors": false } } From 22447e8815861492551be7d8f83c904e04bc8043 Mon Sep 17 00:00:00 2001 From: Yeliz Henden Date: Fri, 15 Aug 2025 16:57:00 +0100 Subject: [PATCH 12/13] ci fixes --- tools/spectral/ipa/ipa-spectral.yaml | 47 ++++++++++++++-------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/tools/spectral/ipa/ipa-spectral.yaml b/tools/spectral/ipa/ipa-spectral.yaml index 88a47919cb..a46dedf224 100644 --- a/tools/spectral/ipa/ipa-spectral.yaml +++ b/tools/spectral/ipa/ipa-spectral.yaml @@ -186,32 +186,31 @@ overrides: - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1snapshots~1shardedClusters' - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1tenant~1restores~1%7BrestoreId%7D' - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1backup~1tenant~1snapshots~1%7BsnapshotId%7D' - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1fts~1indexes~1%7BdatabaseName%7D~1%7BcollectionName%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1fts~1indexes~1%7BindexId%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1search~1indexes~1%7BdatabaseName%7D~1%7BcollectionName%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1search~1indexes~1%7BdatabaseName%7D~1%7BcollectionName%7D~1%7BindexName%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1search~1indexes~1%7BindexId%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1customDBRoles~1roles~1%7BroleName%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1flexClusters~1%7Bname%7D~1backup~1restoreJobs~1%7BrestoreJobId%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1flexClusters~1%7Bname%7D~1backup~1snapshots~1%7BsnapshotId%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1hosts~1%7BprocessId%7D~1fts~1metrics~1measurements" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1privateEndpoint~1serverless~1instance~1%7BinstanceName%7D~1endpoint~1%7BendpointId%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1privateNetworkSettings~1endpointIds~1%7BendpointId%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1serverless~1%7BclusterName%7D~1backup~1restoreJobs~1%7BrestoreJobId%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1serverless~1%7BclusterName%7D~1backup~1snapshots~1%7BsnapshotId%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1streams~1privateLinkConnections~1%7BconnectionId%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1streams~1vpcPeeringConnections~1%7Bid%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1streams~1vpcPeeringConnections~1%7Bid%7D%3Aaccept" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1streams~1vpcPeeringConnections~1%7Bid%7D%3Areject" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1userSecurity~1ldap~1verify~1%7BrequestId%7D" - - "**#/paths/~1api~1atlas~1v2~1orgs~1%7BorgId%7D~1billing~1costExplorer~1usage~1%7Btoken%7D" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1hosts~1%7BprocessId%7D~1fts~1metrics~1indexes~1%7BdatabaseName%7D~1%7BcollectionName%7D~1measurements" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1hosts~1%7BprocessId%7D~1fts~1metrics~1indexes~1%7BdatabaseName%7D~1%7BcollectionName%7D~1%7BindexName%7D~1measurements" - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1liveMigrations~1validate~1%7BvalidationId%7D" + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1fts~1indexes~1%7BdatabaseName%7D~1%7BcollectionName%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1fts~1indexes~1%7BindexId%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1search~1indexes~1%7BdatabaseName%7D~1%7BcollectionName%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1search~1indexes~1%7BdatabaseName%7D~1%7BcollectionName%7D~1%7BindexName%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1clusters~1%7BclusterName%7D~1search~1indexes~1%7BindexId%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1customDBRoles~1roles~1%7BroleName%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1flexClusters~1%7Bname%7D~1backup~1restoreJobs~1%7BrestoreJobId%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1flexClusters~1%7Bname%7D~1backup~1snapshots~1%7BsnapshotId%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1hosts~1%7BprocessId%7D~1fts~1metrics~1measurements' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1privateEndpoint~1serverless~1instance~1%7BinstanceName%7D~1endpoint~1%7BendpointId%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1privateNetworkSettings~1endpointIds~1%7BendpointId%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1serverless~1%7BclusterName%7D~1backup~1restoreJobs~1%7BrestoreJobId%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1serverless~1%7BclusterName%7D~1backup~1snapshots~1%7BsnapshotId%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1streams~1privateLinkConnections~1%7BconnectionId%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1streams~1vpcPeeringConnections~1%7Bid%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1streams~1vpcPeeringConnections~1%7Bid%7D%3Aaccept' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1streams~1vpcPeeringConnections~1%7Bid%7D%3Areject' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1userSecurity~1ldap~1verify~1%7BrequestId%7D' + - '**#/paths/~1api~1atlas~1v2~1orgs~1%7BorgId%7D~1billing~1costExplorer~1usage~1%7Btoken%7D' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1hosts~1%7BprocessId%7D~1fts~1metrics~1indexes~1%7BdatabaseName%7D~1%7BcollectionName%7D~1measurements' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1hosts~1%7BprocessId%7D~1fts~1metrics~1indexes~1%7BdatabaseName%7D~1%7BcollectionName%7D~1%7BindexName%7D~1measurements' + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1liveMigrations~1validate~1%7BvalidationId%7D' rules: xgen-IPA-102-path-alternate-resource-name-path-param: 'off' - files: # To be removed in CLOUDP-338425 - - "**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1customDBRoles~1roles~1%7BroleName%7D" + - '**#/paths/~1api~1atlas~1v2~1groups~1%7BgroupId%7D~1customDBRoles~1roles~1%7BroleName%7D' rules: xgen-IPA-102-collection-identifier-camelCase: 'off' - From 0e1fba4123b90c196b1daa7302524a36ae307331 Mon Sep 17 00:00:00 2001 From: Yeliz Henden Date: Fri, 15 Aug 2025 17:01:32 +0100 Subject: [PATCH 13/13] ci fixes --- tools/spectral/ipa/package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/spectral/ipa/package.json b/tools/spectral/ipa/package.json index 0df575d6fa..d0d98176ec 100644 --- a/tools/spectral/ipa/package.json +++ b/tools/spectral/ipa/package.json @@ -19,8 +19,8 @@ "author": "MongoDB", "main": "ipa-spectral.yaml", "type": "module", - "scripts": { - "gen-ipa-changelog": "npx auto-changelog" + "scripts" : { + "gen-ipa-changelog" : "npx auto-changelog" }, "dependencies": { "@stoplight/spectral-cli": "6.15.0", @@ -36,7 +36,7 @@ "devDependencies": { "auto-changelog": "2.5.0" }, - "auto-changelog": { + "auto-changelog" : { "package": true, "commitPattern": "[a-z]+\\(ipa\\):", "startingVersion": "ipa-validation-ruleset-v1.0.0", @@ -44,7 +44,7 @@ "tagPattern": "ipa-validation-ruleset-v\\d+\\.\\d+\\.\\d+", "tagPrefix": "ipa-validation-ruleset-v", "ignoreCommitPattern": "^ci.*$", - "hideEmptyReleases": true, + "hideEmptyReleases" : true, "contributors": false } }