Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
@@ -0,0 +1,93 @@
import testRule from './__helpers__/testRule';
import { DiagnosticSeverity } from '@stoplight/types';

testRule('xgen-IPA-117-create-operation-summary-starts-with', [
{
name: 'valid summary',
document: {
paths: {
'/resource': {
post: {
summary: 'Create One Resource',
},
},
'/projects/{id}/users': {
post: {
summary: 'Add One User to One Project',
},
},
'/projects/{id}/users:invite': {
// Ignores custom method
post: {
summary: 'Invite One User to One Project',
},
},
'/projects/{id}/users/invite': {
// Ignores legacy custom method
post: {
summary: 'Invite One User to One Project',
'x-xgen-method-verb-override': {
customMethod: true,
},
},
},
},
},
errors: [],
},
{
name: 'invalid summaries',
document: {
paths: {
'/resource': {
post: {
summary: 'Creating One Resource',
},
},
'/projects/{id}/users': {
post: {
summary: 'Adds One User to One Project',
},
},
},
},
errors: [
{
code: 'xgen-IPA-117-create-operation-summary-starts-with',
message: 'Operation summary must start with one of the words [Create,Add].',
path: ['paths', '/resource', 'post'],
severity: DiagnosticSeverity.Warning,
},
{
code: 'xgen-IPA-117-create-operation-summary-starts-with',
message: 'Operation summary must start with one of the words [Create,Add].',
path: ['paths', '/projects/{id}/users', 'post'],
severity: DiagnosticSeverity.Warning,
},
],
},
{
name: 'invalid summary with exceptions',
document: {
paths: {
'/resource': {
post: {
summary: 'Creating One Resource',
'x-xgen-IPA-exception': {
'xgen-IPA-117-create-operation-summary-starts-with': 'reason',
},
},
},
'/projects/{id}/users': {
post: {
summary: 'Adds One User to One Project',
'x-xgen-IPA-exception': {
'xgen-IPA-117-create-operation-summary-starts-with': 'reason',
},
},
},
},
},
errors: [],
},
]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import testRule from './__helpers__/testRule';
import { DiagnosticSeverity } from '@stoplight/types';

testRule('xgen-IPA-117-delete-operation-summary-starts-with', [
{
name: 'valid summary',
document: {
paths: {
'/resource': {
delete: {
summary: 'Delete One Resource',
},
},
'/projects/{id}/users': {
delete: {
summary: 'Remove One User from One Project',
},
},
},
},
errors: [],
},
{
name: 'invalid summaries',
document: {
paths: {
'/resource': {
delete: {
summary: 'Destroy One Resource',
},
},
'/projects/{id}/users': {
delete: {
summary: 'Deletes One User from One Project',
},
},
},
},
errors: [
{
code: 'xgen-IPA-117-delete-operation-summary-starts-with',
message: 'Operation summary must start with one of the words [Delete,Remove].',
path: ['paths', '/resource', 'delete'],
severity: DiagnosticSeverity.Warning,
},
{
code: 'xgen-IPA-117-delete-operation-summary-starts-with',
message: 'Operation summary must start with one of the words [Delete,Remove].',
path: ['paths', '/projects/{id}/users', 'delete'],
severity: DiagnosticSeverity.Warning,
},
],
},
{
name: 'invalid summary with exceptions',
document: {
paths: {
'/resource': {
delete: {
summary: 'Destroy One Resource',
'x-xgen-IPA-exception': {
'xgen-IPA-117-delete-operation-summary-starts-with': 'reason',
},
},
},
'/projects/{id}/users': {
delete: {
summary: 'Deletes One User from One Project',
'x-xgen-IPA-exception': {
'xgen-IPA-117-delete-operation-summary-starts-with': 'reason',
},
},
},
},
},
errors: [],
},
]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import testRule from './__helpers__/testRule';
import { DiagnosticSeverity } from '@stoplight/types';

testRule('xgen-IPA-117-update-operation-summary-starts-with', [
{
name: 'valid summary',
document: {
paths: {
'/resource': {
patch: {
summary: 'Update One Resource',
},
},
'/projects/{id}/users': {
put: {
summary: 'Update One User in One Project',
},
},
},
},
errors: [],
},
{
name: 'invalid summaries',
document: {
paths: {
'/resource': {
patch: {
summary: 'Modify One Resource',
},
},
'/projects/{id}/users': {
put: {
summary: 'Change One User to One Project',
},
},
},
},
errors: [
{
code: 'xgen-IPA-117-update-operation-summary-starts-with',
message: 'Operation summary must start with the word "Update".',
path: ['paths', '/resource', 'patch'],
severity: DiagnosticSeverity.Warning,
},
{
code: 'xgen-IPA-117-update-operation-summary-starts-with',
message: 'Operation summary must start with the word "Update".',
path: ['paths', '/projects/{id}/users', 'put'],
severity: DiagnosticSeverity.Warning,
},
],
},
{
name: 'invalid summary with exceptions',
document: {
paths: {
'/resource': {
patch: {
summary: 'Modify One Resource',
'x-xgen-IPA-exception': {
'xgen-IPA-117-update-operation-summary-starts-with': 'reason',
},
},
},
'/projects/{id}/users': {
put: {
summary: 'Change One User to One Project',
'x-xgen-IPA-exception': {
'xgen-IPA-117-update-operation-summary-starts-with': 'reason',
},
},
},
},
},
errors: [],
},
]);
63 changes: 61 additions & 2 deletions tools/spectral/ipa/rulesets/IPA-117.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ functions:
- IPA117ObjectsMustBeWellDefined
- IPA117ParameterHasExamplesOrSchema
- IPA117OperationSummaryFormat
- IPA117OperationSummaryGetStartsWith
- IPA117OperationSummaryStartsWith

aliases:
OperationObject:
Expand Down Expand Up @@ -298,7 +298,66 @@ rules:
given:
- '$.paths[*][get].summary'
then:
function: 'IPA117OperationSummaryGetStartsWith'
function: 'IPA117OperationSummaryStartsWith'
Copy link
Collaborator

Choose a reason for hiding this comment

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

💯

functionOptions:
allowedStartVerbs:
- Return
xgen-IPA-117-update-operation-summary-starts-with:
description: |
In operation summaries, use 'Update' instead of 'Modify' or 'Change'. For example "Update One Identity Provider".

##### Implementation details
- The rule checks that the `summary` property of update operations use the word 'Update' as the first word.
- The rule only applies to update methods and ignores custom methods
##### Configuration
This rule includes a configuration option:
- `allowedStartVerbs`: Allow list of verb that the operation summary can start with, defaults to `['Update']`
message: '{{error}} https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-117-update-operation-summary-starts-with'
severity: warn
given:
- '$.paths[*][put,patch].summary'
then:
function: 'IPA117OperationSummaryStartsWith'
functionOptions:
allowedStartVerbs:
- Update
xgen-IPA-117-create-operation-summary-starts-with:
description: |
In operation summaries, use 'Create' when the operation is creating a resource, and use 'Add' when the resource itself isn't being created. For example "Create One Identity Provider" or "Add One MongoDB Cloud User to One Project".

##### Implementation details
- The rule checks that the `summary` property of create operations use the word 'Create' or 'Add' as the first word.
- The rule only applies to create methods and ignores custom methods
##### Configuration
This rule includes a configuration option:
- `allowedStartVerbs`: Allow list of verb that the operation summary can start with, defaults to `['Create', 'Add']`
message: '{{error}} https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-117-create-operation-summary-starts-with'
severity: warn
given:
- '$.paths[*][post].summary'
then:
function: 'IPA117OperationSummaryStartsWith'
functionOptions:
allowedStartVerbs:
- Create
- Add
xgen-IPA-117-delete-operation-summary-starts-with:
description: |
In operation summaries, use 'Delete' when the operation is destroying a resource, and use 'Remove' when the resource itself isn't being destroyed. For example "Delete One Identity Provider" or "Remove One MongoDB Cloud User from One Project".

##### Implementation details
- The rule checks that the `summary` property of delete operations use the word 'Delete' or 'Remove' as the first word.
- The rule only applies to delete methods and ignores custom methods
##### Configuration
This rule includes a configuration option:
- `allowedStartVerbs`: Allow list of verb that the operation summary can start with, defaults to `['Delete', 'Remove']`
message: '{{error}} https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-117-delete-operation-summary-starts-with'
severity: warn
given:
- '$.paths[*][delete].summary'
then:
function: 'IPA117OperationSummaryStartsWith'
functionOptions:
allowedStartVerbs:
- Delete
- Remove
36 changes: 36 additions & 0 deletions tools/spectral/ipa/rulesets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,42 @@ In operation summaries, use 'Return' instead of 'Get' or 'List'. For example "Re
This rule includes a configuration option:
- `allowedStartVerbs`: Allow list of verb that the operation summary can start with, defaults to `['Return']`

#### xgen-IPA-117-update-operation-summary-starts-with

![warn](https://img.shields.io/badge/warning-yellow)
In operation summaries, use 'Update' instead of 'Modify' or 'Change'. For example "Update One Identity Provider".

##### Implementation details
- The rule checks that the `summary` property of update operations use the word 'Update' as the first word.
- The rule only applies to update methods and ignores custom methods
##### Configuration
This rule includes a configuration option:
- `allowedStartVerbs`: Allow list of verb that the operation summary can start with, defaults to `['Update']`

#### xgen-IPA-117-create-operation-summary-starts-with

![warn](https://img.shields.io/badge/warning-yellow)
In operation summaries, use 'Create' when the operation is creating a resource, and use 'Add' when the resource itself isn't being created. For example "Create One Identity Provider" or "Add One MongoDB Cloud User to One Project".

##### Implementation details
- The rule checks that the `summary` property of create operations use the word 'Create' or 'Add' as the first word.
- The rule only applies to create methods and ignores custom methods
##### Configuration
This rule includes a configuration option:
- `allowedStartVerbs`: Allow list of verb that the operation summary can start with, defaults to `['Create', 'Add']`

#### xgen-IPA-117-delete-operation-summary-starts-with

![warn](https://img.shields.io/badge/warning-yellow)
In operation summaries, use 'Delete' when the operation is destroying a resource, and use 'Remove' when the resource itself isn't being destroyed. For example "Delete One Identity Provider" or "Remove One MongoDB Cloud User from One Project".

##### Implementation details
- The rule checks that the `summary` property of delete operations use the word 'Delete' or 'Remove' as the first word.
- The rule only applies to delete methods and ignores custom methods
##### Configuration
This rule includes a configuration option:
- `allowedStartVerbs`: Allow list of verb that the operation summary can start with, defaults to `['Delete', 'Remove']`



### IPA-118
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ import { resolveObject } from './utils/componentUtils.js';
import { isCustomMethodIdentifier } from './utils/resourceEvaluation.js';
import { hasCustomMethodOverride } from './utils/extensions.js';

/**
* Checks if the operation summary starts with one of the allowed verbs in the 'allowedStartVerbs' list. The rule ignores custom methods.
* Note: This function is used by multiple rules evaluating get/list, update, delete and create.
* @param input the operation summary to evaluate
* @param allowedStartVerbs the list of allowed verbs that the operation summary must start with
* @param path the path to the operation object summary in the document
* @param rule the rule object containing the rule name and other metadata
* @param documentInventory the document inventory containing the resolved OAS document
* @returns {Array<{path: Array<string>, message: string}>|undefined} error if the summary does not start with one of the allowed verbs, or undefined if there are no errors
*/
export default (input, { allowedStartVerbs }, { path, rule, documentInventory }) => {
const resourcePath = path[1];
const operationObjectPath = path.slice(0, -1);
Expand Down
Loading