Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -254,4 +254,85 @@ 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: [],
},
{
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,
},
],
},
]);
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,80 @@ 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: [],
},
{
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,
},
],
},
]);
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,67 @@ 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: [],
},
{
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,
},
],
},
]);
2 changes: 0 additions & 2 deletions tools/spectral/ipa/__tests__/utils/collectionUtils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});

Expand Down
4 changes: 4 additions & 0 deletions tools/spectral/ipa/rulesets/IPA-102.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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'
Expand All @@ -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
Expand Down
3 changes: 3 additions & 0 deletions tools/spectral/ipa/rulesets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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

Expand All @@ -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.



Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
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.';

/**
* 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
Expand All @@ -21,7 +27,14 @@ 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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you update the rule descriptions for these to clarify the exception behaviour?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rule documentation updated 👍

const result = findExceptionInPathHierarchy(oas, pathKey, RULE_NAME, path);
if (result?.error) {
return result.error;
}
const objectToCheckForException = result ? oas.paths[result.parentPath] : oas.paths[input];

return evaluateAndCollectAdoptionStatus(violations, RULE_NAME, objectToCheckForException, path);
};

function checkViolations(pathKey, path, ignoredValues = []) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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 =
Expand All @@ -8,16 +9,25 @@ 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;

const violations = checkViolations(input, path);

return evaluateAndCollectAdoptionStatus(violations, RULE_NAME, oas.paths[input], path);
// Check for exceptions in path hierarchy
const result = findExceptionInPathHierarchy(oas, input, RULE_NAME, path);
if (result?.error) {
return result.error;
}
const objectToCheckForException = result ? oas.paths[result.parentPath] : oas.paths[input];

return evaluateAndCollectAdoptionStatus(violations, RULE_NAME, objectToCheckForException, path);
};

function checkViolations(pathKey, path) {
Expand Down
Loading
Loading