From a5d915707cbaa5f891309a64944376a6db347da4 Mon Sep 17 00:00:00 2001 From: wtrocki Date: Thu, 6 Mar 2025 11:29:29 +0100 Subject: [PATCH 1/8] CLOUDP-271997: IPA 108 - delete method schema --- ...eMethodResponseShouldNotHaveSchema.test.js | 95 +++++++++++++++++++ tools/spectral/ipa/ipa-spectral.yaml | 1 + tools/spectral/ipa/rulesets/IPA-108.yaml | 14 +++ tools/spectral/ipa/rulesets/README.md | 8 ++ ...deleteMethodResponseShouldNotHaveSchema.js | 34 +++++++ 5 files changed, 152 insertions(+) create mode 100644 tools/spectral/ipa/__tests__/deleteMethodResponseShouldNotHaveSchema.test.js create mode 100644 tools/spectral/ipa/rulesets/IPA-108.yaml create mode 100644 tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js diff --git a/tools/spectral/ipa/__tests__/deleteMethodResponseShouldNotHaveSchema.test.js b/tools/spectral/ipa/__tests__/deleteMethodResponseShouldNotHaveSchema.test.js new file mode 100644 index 0000000000..92f9f21e6f --- /dev/null +++ b/tools/spectral/ipa/__tests__/deleteMethodResponseShouldNotHaveSchema.test.js @@ -0,0 +1,95 @@ +import testRule from './__helpers__/testRule'; +import { DiagnosticSeverity } from '@stoplight/types'; + +testRule('xgen-IPA-108-delete-response-should-be-empty', [ + { + name: 'valid DELETE with void 204', + document: { + paths: { + '/resource/{id}': { + delete: { + responses: { + 204: {}, + }, + }, + }, + }, + }, + errors: [], + }, + { + name: 'valid DELETE with void 204', + document: { + paths: { + '/resource/{id}': { + delete: { + responses: { + 204: { + description: 'No Content', + content: { + 'application/vnd.atlas.2023-01-01+json': { + 'x-xgen-version': '2023-01-01', + }, + }, + }, + }, + }, + }, + }, + }, + errors: [], + }, + { + name: 'invalid DELETE with non-void 204', + document: { + paths: { + '/resource/{id}': { + delete: { + responses: { + 204: { + content: { + 'application/vnd.atlas.2023-01-01+json': { + schema: { type: 'object' }, + }, + }, + }, + }, + }, + }, + }, + }, + errors: [ + { + code: 'xgen-IPA-108-delete-response-should-be-empty', + message: + 'DELETE method should return an empty response. The response should not have a schema property and reference to models http://go/ipa/108', + path: ['paths', '/resource/{id}', 'delete'], + severity: DiagnosticSeverity.Warning, + }, + ], + }, + { + name: 'valid with exception', + document: { + paths: { + '/resource/{id}': { + delete: { + 'x-xgen-IPA-exception': { + 'xgen-IPA-108-delete-response-should-be-empty': 'Legacy API', + }, + responses: { + 204: { + content: { + 'application/vnd.atlas.2023-01-01+json': { + schema: { type: 'object' }, + }, + }, + }, + }, + }, + }, + }, + }, + errors: [], + }, +]); diff --git a/tools/spectral/ipa/ipa-spectral.yaml b/tools/spectral/ipa/ipa-spectral.yaml index d9ee29a7e6..0693a5a88e 100644 --- a/tools/spectral/ipa/ipa-spectral.yaml +++ b/tools/spectral/ipa/ipa-spectral.yaml @@ -6,6 +6,7 @@ extends: - ./rulesets/IPA-113.yaml - ./rulesets/IPA-123.yaml - ./rulesets/IPA-106.yaml + - ./rulesets/IPA-108.yaml overrides: - files: diff --git a/tools/spectral/ipa/rulesets/IPA-108.yaml b/tools/spectral/ipa/rulesets/IPA-108.yaml new file mode 100644 index 0000000000..5574e8a321 --- /dev/null +++ b/tools/spectral/ipa/rulesets/IPA-108.yaml @@ -0,0 +1,14 @@ +# IPA-108: Delete +# http://go/ipa/108 + +rules: + xgen-IPA-108-delete-response-should-be-empty: + description: Delete method response should not have schema reference to object http://go/ipa/108 + message: '{{error}} http://go/ipa/108' + severity: warn + given: $.paths[*].delete + then: + function: deleteMethodResponseShouldNotHaveSchema + +functions: + - deleteMethodResponseShouldNotHaveSchema diff --git a/tools/spectral/ipa/rulesets/README.md b/tools/spectral/ipa/rulesets/README.md index 43f9ae370a..7d76387c3d 100644 --- a/tools/spectral/ipa/rulesets/README.md +++ b/tools/spectral/ipa/rulesets/README.md @@ -42,6 +42,14 @@ For rule definitions, see [IPA-106.yaml](https://github.com/mongodb/openapi/blob | ------------------------------------------------------------------ | -------------------------------------------------------------------------------- | -------- | | xgen-IPA-106-create-method-request-body-is-request-suffixed-object | The Create method request should be a Request suffixed object. http://go/ipa/106 | warn | +### IPA-108 + +For rule definitions, see [IPA-108.yaml](https://github.com/mongodb/openapi/blob/main/tools/spectral/ipa/rulesets/IPA-108.yaml). + +| Rule Name | Description | Severity | +| -------------------------------------------- | ----------------------------------------------------------------------------------- | -------- | +| xgen-IPA-108-delete-response-should-be-empty | Delete method response should not have schema reference to object http://go/ipa/108 | warn | + ### IPA-109 For rule definitions, see [IPA-109.yaml](https://github.com/mongodb/openapi/blob/main/tools/spectral/ipa/rulesets/IPA-109.yaml). diff --git a/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js b/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js new file mode 100644 index 0000000000..5e6c28c613 --- /dev/null +++ b/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js @@ -0,0 +1,34 @@ +import { hasException } from './utils/exceptions.js'; +import { collectAdoption, collectAndReturnViolation, collectException } from './utils/collectionUtils.js'; + +const RULE_NAME = 'xgen-IPA-108-delete-response-should-be-empty'; +const ERROR_MESSAGE = + 'DELETE method should return an empty response. The response should not have a schema property and reference to models'; + +/** + * Delete method should return an empty response + * @param {object} input - The delete operation object + * @param {object} _ - Unused + * @param {object} context - The context object containing the path + */ +export default (input, _, { path }) => { + const deleteOp = input; + + if (hasException(deleteOp, RULE_NAME)) { + collectException(deleteOp, RULE_NAME, path); + return; + } + + const responses = deleteOp.responses || {}; + for (const [status, response] of Object.entries(responses)) { + if (status === '204' && response.content) { + for (const contentType of Object.keys(response.content)) { + if (response.content[contentType].schema) { + return collectAndReturnViolation(path, RULE_NAME, ERROR_MESSAGE); + } + } + } + } + + collectAdoption(path, RULE_NAME); +}; From 4c12229c64a1ae3023a4df4876daeec458c1828c Mon Sep 17 00:00:00 2001 From: Wojciech Trocki Date: Thu, 6 Mar 2025 13:35:56 +0100 Subject: [PATCH 2/8] Apply suggestions from code review Co-authored-by: Lovisa Berggren <59226031+lovisaberggren@users.noreply.github.com> --- .../deleteMethodResponseShouldNotHaveSchema.test.js | 4 ++-- tools/spectral/ipa/rulesets/IPA-108.yaml | 2 +- tools/spectral/ipa/rulesets/README.md | 6 +++--- .../functions/deleteMethodResponseShouldNotHaveSchema.js | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/spectral/ipa/__tests__/deleteMethodResponseShouldNotHaveSchema.test.js b/tools/spectral/ipa/__tests__/deleteMethodResponseShouldNotHaveSchema.test.js index 92f9f21e6f..038e6c37d1 100644 --- a/tools/spectral/ipa/__tests__/deleteMethodResponseShouldNotHaveSchema.test.js +++ b/tools/spectral/ipa/__tests__/deleteMethodResponseShouldNotHaveSchema.test.js @@ -18,7 +18,7 @@ testRule('xgen-IPA-108-delete-response-should-be-empty', [ errors: [], }, { - name: 'valid DELETE with void 204', + name: 'valid DELETE with void 204 versioned', document: { paths: { '/resource/{id}': { @@ -62,7 +62,7 @@ testRule('xgen-IPA-108-delete-response-should-be-empty', [ { code: 'xgen-IPA-108-delete-response-should-be-empty', message: - 'DELETE method should return an empty response. The response should not have a schema property and reference to models http://go/ipa/108', + 'DELETE method should return an empty response. The response should not have a schema property and reference to models. http://go/ipa/108', path: ['paths', '/resource/{id}', 'delete'], severity: DiagnosticSeverity.Warning, }, diff --git a/tools/spectral/ipa/rulesets/IPA-108.yaml b/tools/spectral/ipa/rulesets/IPA-108.yaml index 5574e8a321..725294b3bd 100644 --- a/tools/spectral/ipa/rulesets/IPA-108.yaml +++ b/tools/spectral/ipa/rulesets/IPA-108.yaml @@ -3,7 +3,7 @@ rules: xgen-IPA-108-delete-response-should-be-empty: - description: Delete method response should not have schema reference to object http://go/ipa/108 + description: Delete method response should not have schema reference to object. http://go/ipa/108 message: '{{error}} http://go/ipa/108' severity: warn given: $.paths[*].delete diff --git a/tools/spectral/ipa/rulesets/README.md b/tools/spectral/ipa/rulesets/README.md index 7d76387c3d..05df066027 100644 --- a/tools/spectral/ipa/rulesets/README.md +++ b/tools/spectral/ipa/rulesets/README.md @@ -46,9 +46,9 @@ For rule definitions, see [IPA-106.yaml](https://github.com/mongodb/openapi/blob For rule definitions, see [IPA-108.yaml](https://github.com/mongodb/openapi/blob/main/tools/spectral/ipa/rulesets/IPA-108.yaml). -| Rule Name | Description | Severity | -| -------------------------------------------- | ----------------------------------------------------------------------------------- | -------- | -| xgen-IPA-108-delete-response-should-be-empty | Delete method response should not have schema reference to object http://go/ipa/108 | warn | +| Rule Name | Description | Severity | +| -------------------------------------------- | ------------------------------------------------------------------------------------ | -------- | +| xgen-IPA-108-delete-response-should-be-empty | Delete method response should not have schema reference to object. http://go/ipa/108 | warn | ### IPA-109 diff --git a/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js b/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js index 5e6c28c613..c27310f330 100644 --- a/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js +++ b/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js @@ -3,7 +3,7 @@ import { collectAdoption, collectAndReturnViolation, collectException } from './ const RULE_NAME = 'xgen-IPA-108-delete-response-should-be-empty'; const ERROR_MESSAGE = - 'DELETE method should return an empty response. The response should not have a schema property and reference to models'; + 'DELETE method should return an empty response. The response should not have a schema property and reference to models.'; /** * Delete method should return an empty response From c0502df364fa0419e6431bee14b6ffe73d62811c Mon Sep 17 00:00:00 2001 From: Wojciech Trocki Date: Thu, 6 Mar 2025 17:03:03 +0100 Subject: [PATCH 3/8] Apply suggestions from code review Co-authored-by: Yeliz Henden <165907936+yelizhenden-mdb@users.noreply.github.com> --- .../functions/deleteMethodResponseShouldNotHaveSchema.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js b/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js index c27310f330..f89e984a88 100644 --- a/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js +++ b/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js @@ -13,13 +13,15 @@ const ERROR_MESSAGE = */ export default (input, _, { path }) => { const deleteOp = input; - +if(!deleteOp.responses || deleteOp.responses.length === 0) { + return; +} if (hasException(deleteOp, RULE_NAME)) { collectException(deleteOp, RULE_NAME, path); return; } - const responses = deleteOp.responses || {}; + const responses = deleteOp.responses; for (const [status, response] of Object.entries(responses)) { if (status === '204' && response.content) { for (const contentType of Object.keys(response.content)) { From 07d6d7a0b746b48faf8d9875d6396dcf12042750 Mon Sep 17 00:00:00 2001 From: wtrocki Date: Thu, 6 Mar 2025 17:08:20 +0100 Subject: [PATCH 4/8] fix: format source code --- .../functions/deleteMethodResponseShouldNotHaveSchema.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js b/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js index f89e984a88..95597f3925 100644 --- a/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js +++ b/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js @@ -13,9 +13,9 @@ const ERROR_MESSAGE = */ export default (input, _, { path }) => { const deleteOp = input; -if(!deleteOp.responses || deleteOp.responses.length === 0) { - return; -} + if (!deleteOp.responses || deleteOp.responses.length === 0) { + return; + } if (hasException(deleteOp, RULE_NAME)) { collectException(deleteOp, RULE_NAME, path); return; From 3432d848de56d9bfa287bc3a187c6cba12819dcd Mon Sep 17 00:00:00 2001 From: wtrocki Date: Thu, 6 Mar 2025 17:17:44 +0100 Subject: [PATCH 5/8] fix: adoption for 204 only --- .../deleteMethodResponseShouldNotHaveSchema.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js b/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js index 95597f3925..8f612c55b6 100644 --- a/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js +++ b/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js @@ -22,15 +22,16 @@ export default (input, _, { path }) => { } const responses = deleteOp.responses; - for (const [status, response] of Object.entries(responses)) { - if (status === '204' && response.content) { - for (const contentType of Object.keys(response.content)) { - if (response.content[contentType].schema) { + if (responses && responses['204']) { + const successResponse = responses['204']; + if (successResponse.content) { + for (const contentType of Object.keys(successResponse.content)) { + // Check if the response has a schema property + if (successResponse.content[contentType] && successResponse.content[contentType].schema) { return collectAndReturnViolation(path, RULE_NAME, ERROR_MESSAGE); } } } + collectAdoption(path, RULE_NAME); } - - collectAdoption(path, RULE_NAME); }; From ad75fa49faa8d36b2d0e0da5f47e68c5827c7c8c Mon Sep 17 00:00:00 2001 From: wtrocki Date: Fri, 7 Mar 2025 13:54:34 +0100 Subject: [PATCH 6/8] fix: formalize format --- ...eMethodResponseShouldNotHaveSchema.test.js | 5 +- ...deleteMethodResponseShouldNotHaveSchema.js | 48 ++++++++++++++----- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/tools/spectral/ipa/__tests__/deleteMethodResponseShouldNotHaveSchema.test.js b/tools/spectral/ipa/__tests__/deleteMethodResponseShouldNotHaveSchema.test.js index 038e6c37d1..c7f9867b4b 100644 --- a/tools/spectral/ipa/__tests__/deleteMethodResponseShouldNotHaveSchema.test.js +++ b/tools/spectral/ipa/__tests__/deleteMethodResponseShouldNotHaveSchema.test.js @@ -30,6 +30,9 @@ testRule('xgen-IPA-108-delete-response-should-be-empty', [ 'application/vnd.atlas.2023-01-01+json': { 'x-xgen-version': '2023-01-01', }, + 'application/vnd.atlas.2023-03-01+json': { + 'x-xgen-version': '2023-01-01', + }, }, }, }, @@ -62,7 +65,7 @@ testRule('xgen-IPA-108-delete-response-should-be-empty', [ { code: 'xgen-IPA-108-delete-response-should-be-empty', message: - 'DELETE method should return an empty response. The response should not have a schema property and reference to models. http://go/ipa/108', + 'Error found for application/vnd.atlas.2023-01-01+json: DELETE method should return an empty response. The response should not have a schema property. http://go/ipa/108', path: ['paths', '/resource/{id}', 'delete'], severity: DiagnosticSeverity.Warning, }, diff --git a/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js b/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js index 8f612c55b6..468fa6dc01 100644 --- a/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js +++ b/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js @@ -2,8 +2,7 @@ import { hasException } from './utils/exceptions.js'; import { collectAdoption, collectAndReturnViolation, collectException } from './utils/collectionUtils.js'; const RULE_NAME = 'xgen-IPA-108-delete-response-should-be-empty'; -const ERROR_MESSAGE = - 'DELETE method should return an empty response. The response should not have a schema property and reference to models.'; +const ERROR_MESSAGE = 'DELETE method should return an empty response. The response should not have a schema property.'; /** * Delete method should return an empty response @@ -12,26 +11,51 @@ const ERROR_MESSAGE = * @param {object} context - The context object containing the path */ export default (input, _, { path }) => { + // 1. Filter out not relevant use cases that should not lead to adoption. const deleteOp = input; if (!deleteOp.responses || deleteOp.responses.length === 0) { return; } + + // 2. Handle exception on OpenAPI schema if (hasException(deleteOp, RULE_NAME)) { collectException(deleteOp, RULE_NAME, path); return; } - const responses = deleteOp.responses; - if (responses && responses['204']) { - const successResponse = responses['204']; - if (successResponse.content) { - for (const contentType of Object.keys(successResponse.content)) { - // Check if the response has a schema property - if (successResponse.content[contentType] && successResponse.content[contentType].schema) { - return collectAndReturnViolation(path, RULE_NAME, ERROR_MESSAGE); + // 3. Validation + const errors = checkViolations(deleteOp.responses); + if (errors) { + return collectAndReturnViolation(path, RULE_NAME, errors); + } + + collectAdoption(path, RULE_NAME); +}; + +/** + * Check if the operation has validation issues + * @param {object} input - The object to vefify + * @return {Array|undefined} - The content types that have a schema + */ +function checkViolations(input) { + try { + if (input && input['204']) { + const successResponse = input['204']; + if (successResponse.content) { + const errors = []; + for (const contentType of Object.keys(successResponse.content)) { + if (successResponse.content[contentType] && successResponse.content[contentType].schema) { + errors.push({ + message: `Error found for ${contentType}: ${ERROR_MESSAGE}`, + }); + } } + return errors.length > 0 ? errors : undefined; } } - collectAdoption(path, RULE_NAME); + } catch (e) { + return ['Internal Rule Error without reporting violation' + e]; } -}; + // No errors returning undefined + return undefined; +} From a61e37f5713223929c031f315b272a7005ea5ad0 Mon Sep 17 00:00:00 2001 From: wtrocki Date: Fri, 7 Mar 2025 14:07:02 +0100 Subject: [PATCH 7/8] fix: change output format for method --- tools/spectral/CONTRIBUTING.md | 0 .../deleteMethodResponseShouldNotHaveSchema.js | 12 +++++------- 2 files changed, 5 insertions(+), 7 deletions(-) create mode 100644 tools/spectral/CONTRIBUTING.md diff --git a/tools/spectral/CONTRIBUTING.md b/tools/spectral/CONTRIBUTING.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js b/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js index 468fa6dc01..ecd17502de 100644 --- a/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js +++ b/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js @@ -25,7 +25,7 @@ export default (input, _, { path }) => { // 3. Validation const errors = checkViolations(deleteOp.responses); - if (errors) { + if (errors.length > 0) { return collectAndReturnViolation(path, RULE_NAME, errors); } @@ -35,14 +35,14 @@ export default (input, _, { path }) => { /** * Check if the operation has validation issues * @param {object} input - The object to vefify - * @return {Array|undefined} - The content types that have a schema + * @return {Array} - errors array (empty if no errors) */ function checkViolations(input) { + const errors = []; try { if (input && input['204']) { const successResponse = input['204']; if (successResponse.content) { - const errors = []; for (const contentType of Object.keys(successResponse.content)) { if (successResponse.content[contentType] && successResponse.content[contentType].schema) { errors.push({ @@ -50,12 +50,10 @@ function checkViolations(input) { }); } } - return errors.length > 0 ? errors : undefined; } } } catch (e) { - return ['Internal Rule Error without reporting violation' + e]; + return [`${RULE_NAME} Internal Rule Error: ${e} Please report issue in https://github.com/mongodb/openapi/issues`]; } - // No errors returning undefined - return undefined; + return errors; } From ce8c140df1127b29073178846b85104481ecdd30 Mon Sep 17 00:00:00 2001 From: wtrocki Date: Fri, 7 Mar 2025 18:04:09 +0100 Subject: [PATCH 8/8] fix: follow specification for rule creation --- ...eMethodResponseShouldNotHaveSchema.test.js | 12 ++--- tools/spectral/ipa/rulesets/IPA-108.yaml | 2 +- ...deleteMethodResponseShouldNotHaveSchema.js | 47 +++++++++---------- .../functions/utils/collectionUtils.js | 14 ++++++ 4 files changed, 44 insertions(+), 31 deletions(-) diff --git a/tools/spectral/ipa/__tests__/deleteMethodResponseShouldNotHaveSchema.test.js b/tools/spectral/ipa/__tests__/deleteMethodResponseShouldNotHaveSchema.test.js index c7f9867b4b..877d151c59 100644 --- a/tools/spectral/ipa/__tests__/deleteMethodResponseShouldNotHaveSchema.test.js +++ b/tools/spectral/ipa/__tests__/deleteMethodResponseShouldNotHaveSchema.test.js @@ -66,7 +66,7 @@ testRule('xgen-IPA-108-delete-response-should-be-empty', [ code: 'xgen-IPA-108-delete-response-should-be-empty', message: 'Error found for application/vnd.atlas.2023-01-01+json: DELETE method should return an empty response. The response should not have a schema property. http://go/ipa/108', - path: ['paths', '/resource/{id}', 'delete'], + path: ['paths', '/resource/{id}', 'delete', 'responses', '204'], severity: DiagnosticSeverity.Warning, }, ], @@ -77,13 +77,13 @@ testRule('xgen-IPA-108-delete-response-should-be-empty', [ paths: { '/resource/{id}': { delete: { - 'x-xgen-IPA-exception': { - 'xgen-IPA-108-delete-response-should-be-empty': 'Legacy API', - }, responses: { 204: { - content: { - 'application/vnd.atlas.2023-01-01+json': { + 'application/vnd.atlas.2023-01-01+json': { + 'x-xgen-IPA-exception': { + 'xgen-IPA-108-delete-response-should-be-empty': 'Legacy API', + }, + content: { schema: { type: 'object' }, }, }, diff --git a/tools/spectral/ipa/rulesets/IPA-108.yaml b/tools/spectral/ipa/rulesets/IPA-108.yaml index 725294b3bd..7300f624b5 100644 --- a/tools/spectral/ipa/rulesets/IPA-108.yaml +++ b/tools/spectral/ipa/rulesets/IPA-108.yaml @@ -6,7 +6,7 @@ rules: description: Delete method response should not have schema reference to object. http://go/ipa/108 message: '{{error}} http://go/ipa/108' severity: warn - given: $.paths[*].delete + given: $.paths[*].delete.responses[204] then: function: deleteMethodResponseShouldNotHaveSchema diff --git a/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js b/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js index ecd17502de..cc1dcbbe3a 100644 --- a/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js +++ b/tools/spectral/ipa/rulesets/functions/deleteMethodResponseShouldNotHaveSchema.js @@ -1,5 +1,10 @@ import { hasException } from './utils/exceptions.js'; -import { collectAdoption, collectAndReturnViolation, collectException } from './utils/collectionUtils.js'; +import { + collectAdoption, + collectAndReturnViolation, + collectException, + handleInternalError, +} from './utils/collectionUtils.js'; const RULE_NAME = 'xgen-IPA-108-delete-response-should-be-empty'; const ERROR_MESSAGE = 'DELETE method should return an empty response. The response should not have a schema property.'; @@ -11,20 +16,14 @@ const ERROR_MESSAGE = 'DELETE method should return an empty response. The respon * @param {object} context - The context object containing the path */ export default (input, _, { path }) => { - // 1. Filter out not relevant use cases that should not lead to adoption. - const deleteOp = input; - if (!deleteOp.responses || deleteOp.responses.length === 0) { + // 1. Handle exception on OpenAPI schema + if (hasException(input, RULE_NAME)) { + collectException(input, RULE_NAME, path); return; } - // 2. Handle exception on OpenAPI schema - if (hasException(deleteOp, RULE_NAME)) { - collectException(deleteOp, RULE_NAME, path); - return; - } - - // 3. Validation - const errors = checkViolations(deleteOp.responses); + // 2. Validation + const errors = checkViolations(input, path); if (errors.length > 0) { return collectAndReturnViolation(path, RULE_NAME, errors); } @@ -35,25 +34,25 @@ export default (input, _, { path }) => { /** * Check if the operation has validation issues * @param {object} input - The object to vefify - * @return {Array} - errors array (empty if no errors) + * @param {object} jsonPathArray - The jsonPathArray covering location in the OpenAPI schema + * @return {Array} - errors array () */ -function checkViolations(input) { +function checkViolations(input, jsonPathArray) { const errors = []; try { - if (input && input['204']) { - const successResponse = input['204']; - if (successResponse.content) { - for (const contentType of Object.keys(successResponse.content)) { - if (successResponse.content[contentType] && successResponse.content[contentType].schema) { - errors.push({ - message: `Error found for ${contentType}: ${ERROR_MESSAGE}`, - }); - } + const successResponse = input; + if (successResponse.content) { + for (const contentType of Object.keys(successResponse.content)) { + if (successResponse.content[contentType] && successResponse.content[contentType].schema) { + errors.push({ + path: jsonPathArray, + message: `Error found for ${contentType}: ${ERROR_MESSAGE}`, + }); } } } } catch (e) { - return [`${RULE_NAME} Internal Rule Error: ${e} Please report issue in https://github.com/mongodb/openapi/issues`]; + handleInternalError(RULE_NAME, jsonPathArray, e); } return errors; } diff --git a/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js b/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js index 653c632fc6..b02bef5ee0 100644 --- a/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js +++ b/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js @@ -46,3 +46,17 @@ export function collectException(object, ruleName, path) { collector.add(EntryType.EXCEPTION, path, ruleName, exceptionReason); } } + +/** + * Creates internal rule error entry for the collector in order to not fail validation process. + * @param {Array} jsonPathArray - The JSON path for the object where the rule exception occurred. + * @param {string} ruleName - The name of the rule that was adopted. + */ +export function handleInternalError(ruleName, jsonPathArray, error) { + return [ + { + path: jsonPathArray, + message: `${ruleName} Internal Rule Error: ${error} Please report issue in https://github.com/mongodb/openapi/issues`, + }, + ]; +}