Merge pull request #85 from adidas/feature/update-spectral-ruleset

Feature/update spectral ruleset
This commit is contained in:
Cesareo
2025-02-13 16:22:47 +01:00
committed by GitHub
9 changed files with 609 additions and 374 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -1,316 +1,275 @@
extends: ["spectral:oas"] extends: [[spectral:oas, all], [spectral:asyncapi, all]]
rules: documentationUrl: https://github.com/adidas/api-guidelines/blob/master/ruleset.md
rules:
# --------------------------------------------------------------------------- operation-tags: off
# General OAS rules operation-operationId: off
# --------------------------------------------------------------------------- operation-success-response: error
operation-operationId: false # ----------------------------#
operation-tags: false # Adidas OAS v2.0, v3.0 rules #
operation-2xx-response: error # ----------------------------#
adidas-paths-kebab-case: adidas-paths-kebab-case:
description: All YAML/JSON paths MUST follow kebab-case description: All YAML/JSON paths MUST follow kebab-case
severity: warn severity: warn
recommended: true recommended: true
message: "{{property}} is not kebab-case: {{error}}" message: "{{property}} is not kebab-case: {{error}}"
given: $.paths[*]~ given: $.paths[*]~
then: then:
function: pattern function: pattern
functionOptions: functionOptions:
match: "^\/([a-z0-9]+(-[a-z0-9]+)*)?(\/[a-z0-9]+(-[a-z0-9]+)*|\/{.+})*$" # doesn't allow /asasd{asdas}sadas pattern or not closed braces match: "^\/([a-z0-9]+(-[a-z0-9]+)*)?(\/[a-z0-9]+(-[a-z0-9]+)*|\/{.+})*$" # doesn't allow /asasd{asdas}sadas pattern or not closed braces
adidas-path-parameters-camelCase-alphanumeric: adidas-path-parameters-camelCase-alphanumeric:
description: Path parameters MUST follow camelCase description: Path parameters MUST follow camelCase
severity: warn severity: warn
recommended: true recommended: true
message: "{{property}} path parameter is not camelCase: {{error}}" message: "{{property}} path parameter is not camelCase: {{error}}"
given: $..parameters[?(@.in == 'path')].name given: $..parameters[?(@.in == 'path')].name
then: then:
function: pattern function: pattern
functionOptions: functionOptions:
match: "^[a-z][a-zA-Z0-9]+$" match: "^[a-z][a-zA-Z0-9]+$"
adidas-definitions-camelCase-alphanumeric: adidas-definitions-camelCase-alphanumeric:
description: All YAML/JSON definitions MUST follow fields-camelCase and be ASCII alphanumeric characters or `_` or `$`. description: All YAML/JSON definitions MUST follow fields-camelCase and be ASCII alphanumeric characters or `_` or `$`.
severity: error severity: error
recommended: true recommended: true
message: "{{property}} MUST follow camelCase and be ASCII alphanumeric characters or `_` or `$`." message: "{{property}} MUST follow camelCase and be ASCII alphanumeric characters or `_` or `$`."
given: $.definitions[*]~ given: $.definitions[*]~
then: then:
function: pattern function: pattern
functionOptions: functionOptions:
match: "/^[a-z$_]{1}[A-Z09$_]*/" match: "/^[a-z$_]{1}[A-Z09$_]*/"
adidas-properties-camelCase-alphanumeric: adidas-properties-camelCase-alphanumeric:
description: All JSON Schema properties MUST follow fields-camelCase and be ASCII alphanumeric characters or `_` or `$`. description: All JSON Schema properties MUST follow fields-camelCase and be ASCII alphanumeric characters or `_` or `$`.
severity: error severity: error
recommended: true recommended: true
message: "{{property}} MUST follow camelCase and be ASCII alphanumeric characters or `_` or `$`." message: "{{property}} MUST follow camelCase and be ASCII alphanumeric characters or `_` or `$`."
given: $.definitions..properties[*]~ given: $.definitions..properties[*]~
then: then:
function: pattern function: pattern
functionOptions: functionOptions:
match: "/^[a-z$_]{1}[A-Z09$_]*/" match: "/^[a-z$_]{1}[A-Z09$_]*/"
adidas-request-GET-no-body: adidas-request-GET-no-body:
description: "A 'GET' request MUST NOT accept a 'body` parameter" description: "A 'GET' request MUST NOT accept a 'body` parameter"
severity: error severity: error
given: $.paths..get.parameters..in given: $.paths..get.parameters..in
then: then:
function: pattern function: pattern
functionOptions: functionOptions:
notMatch: "/^body$/" notMatch: "/^body$/"
adidas-headers-no-x-headers: adidas-headers-no-x-headers:
description: "All 'HTTP' headers SHOULD NOT include 'X-' headers (https://tools.ietf.org/html/rfc6648)." description: "All 'HTTP' headers SHOULD NOT include 'X-' headers (https://tools.ietf.org/html/rfc6648)."
severity: warn severity: warn
given: "$..parameters[?(@.in == 'header')].name" given: "$..parameters[?(@.in == 'header')].name"
message: "HTTP headers SHOULD NOT include 'X-' prefix." message: "HTTP headers SHOULD NOT include 'X-' prefix."
recommended: true recommended: true
type: style type: style
then: then:
function: pattern function: pattern
functionOptions: functionOptions:
notMatch: "/^(x|X)-/" notMatch: "/^(x|X)-/"
adidas-headers-hyphenated-pascal-case: adidas-headers-hyphenated-pascal-case:
description: All `HTTP` headers MUST use `Hyphenated-Pascal-Case` notation description: All `HTTP` headers MUST use `Hyphenated-Pascal-Case` notation
severity: error severity: error
given: "$..parameters[?(@.in == 'header')].name" given: "$..parameters[?(@.in == 'header')].name"
message: "'HTTP' headers MUST follow 'Hyphenated-Pascal-Case' notation" message: "'HTTP' headers MUST follow 'Hyphenated-Pascal-Case' notation"
recommended: true recommended: true
type: style type: style
then: then:
function: pattern function: pattern
functionOptions: functionOptions:
match: "/^([A-Z][a-z0-9]-)*([A-Z][a-z0-9])+/" match: "/^([A-Z][a-z0-9]-)*([A-Z][a-z0-9])+/"
# --------------------------------------------------------------------------- # ----------------------#
# Only OAS2 rules # Adidas OAS v2.0 rules #
# --------------------------------------------------------------------------- # ----------------------#
adidas-oas2-protocol-https-only: adidas-oas2-protocol-https-only:
description: "ALL requests MUST go through `https` protocol only" description: "ALL requests MUST go through `https` protocol only"
formats: formats:
- oas2 - oas2
recommended: true recommended: true
severity: error severity: error
type: "style" type: "style"
message: "Schemes MUST be https and no other value is allowed." message: "Schemes MUST be https and no other value is allowed."
given: $ given: $
then: then:
field: schemes field: schemes
function: schema function: schema
functionOptions: functionOptions:
schema: schema:
type: array type: array
items: items:
type: string type: string
enum: ["https"] enum: ["https"]
maxItems: 1 maxItems: 1
adidas-oas2-request-support-json: adidas-oas2-request-support-json:
description: Every request SHOULD support `application/json` media type description: Every request SHOULD support `application/json` media type
formats: formats:
- oas2 - oas2
severity: warn severity: warn
message: "{{description}}: {{error}}" message: "{{description}}: {{error}}"
recommended: true recommended: true
given: "$..consumes" given: "$..consumes"
then: then:
function: schema function: schema
functionOptions: functionOptions:
schema: schema:
type: array type: array
contains: contains:
type: string type: string
enum: enum:
- application/json - application/json
adidas-oas2-example-exists-in-parameters: adidas-oas2-example-exists-in-parameters:
description: All models MUST have a valid example. description: All models MUST have a valid example.
severity: error severity: error
recommended: true recommended: true
formats: formats:
- oas2 - oas2
message: "{{ property }} MUST have a valid example." message: "{{ property }} MUST have a valid example."
given: "$..parameters..[?(@.in == 'body' && (@.example || @.schema.$ref))]" given: "$..parameters..[?(@.in == 'body' && (@.example || @.schema.$ref))]"
then: then:
function: truthy function: truthy
# example-exists-in-definitions: # example-exists-in-definitions covery by oas2-valid-media-example
# description: All models MUST have a valid example.
# severity: error adidas-oas2-response-success-hal: # schemes and/or produces
# recommended: true description: "All success responses MUST be of media type `application/hal+json`"
# formats: severity: error
# - oas2 given: $.paths..responses[?( @property >= 200 && @property < 300 && @property != 204)]
# message: "{{ property }} MUST have a valid example." recommended: true
# given: "$..definitions..[?(!@.example || !@..$ref)]" type: "style"
# then: formats:
# function: falsy - oas2
# "$..parameters..[?(@.in == 'body')]..[?(@property !== 'properties' && @.example && ( @.type || @.format || @.$ref ))]" message: "Response documents MUST follow application/hal+json: {{error}}"
then:
adidas-oas2-response-success-hal: # schemes and/or produces field: schema
description: "All success responses MUST be of media type `application/hal+json`" function: schema
severity: error functionOptions:
given: $.paths..responses[?( @property >= 200 && @property < 300 && @property != 204)] schema:
recommended: true $ref: "./supermodel/adidas/api/HAL.yaml"
type: "style"
formats: adidas-oas2-response-error-problem: # schemas and/or produces
- oas2 description: All error responses MUST be of media type `application/problem+json`
message: "Response documents MUST follow application/hal+json: {{error}}" severity: error
then: formats:
field: schema - oas2
function: schema given: $.paths..responses[?( @property >= 400 && @property < 600 )]
functionOptions: recommended: true
schema: type: "style"
$ref: "./supermodel/adidas/api/HAL.yaml" message: "Error response document MUST follow application/problem+json: {{error}}"
then:
adidas-oas2-response-error-problem: # schemas and/or produces field: schema.example
description: All error responses MUST be of media type `application/problem+json` function: schema
severity: error functionOptions:
formats: schema:
- oas2 $ref: "./supermodel/adidas/api/ProblemDetail.yaml"
given: $.paths..responses[?( @property >= 400 && @property < 600 )]
recommended: true # ----------------------#
type: "style" # Adidas OAS v3.0 rules #
message: "Error response document MUST follow application/problem+json: {{error}}" # ----------------------#
then:
field: schema.example adidas-oas3-request-support-json:
function: schema description: Every request MUST support `application/json` media type
functionOptions: formats:
schema: - oas3
$ref: "./supermodel/adidas/api/ProblemDetail.yaml" recommended: true
severity: error
# --------------------------------------------------------------------------- message: "{{description}}: {{error}}"
# Only OAS3 rules given: $.paths.[*].requestBody.content[?(@property.indexOf('json') === -1)]^
# --------------------------------------------------------------------------- then:
function: falsy
adidas-oas3-request-support-json:
description: Every request MUST support `application/json` media type # adidas-oas3-valid-example-in-parameters && adidas-oas3-valid-example-in-definitions covered by oas3-valid-media-example
formats:
- oas3 adidas-oas3-protocol-https-only:
recommended: true description: "ALL requests MUST go through `https` protocol only"
severity: error formats:
message: "{{description}}: {{error}}" - oas3
given: $.paths.[*].requestBody.content[?(@property.indexOf('json') === -1)]^ recommended: true
then: severity: error
function: falsy message: "Servers MUST be https and no other protocol is allowed."
given: $.servers..url
adidas-oas3-valid-example-in-parameters: then:
description: Examples must be valid against their defined schema. function: pattern
message: "{{error}}" functionOptions:
recommended: true match: "/^https:/"
formats:
- oas3 adidas-oas3-response-success-hal:
severity: 0 description: "All success responses MUST be of media type `application/hal+json` "
type: validation severity: error
given: "$..parameters..[?(@.in == 'body')]..[?(@property !== 'properties' && @.example given: $.paths..responses[?( @property >= 201 && @property < 300 && @property != 204)].content[*]~
&& ( @.type || @.format || @.$ref ))]" recommended: true
then: formats:
function: schemaPath - oas3
functionOptions: message: "Response documents MUST be of application/hal+json media types: {{error}}"
field: example then:
schemaPath: "$" function: enumeration
functionOptions:
adidas-oas3-valid-example-in-definitions: values:
description: Examples must be valid against their defined schema. - application/hal+json
message: "{{error}}"
recommended: true # sync and async patterns that can return hal OR problem+json
formats: adidas-oas3-response-success-OK:
- oas3 description: "All success responses MUST be of media type `application/hal+json` or `application/problem+json`"
severity: 0 severity: error
type: validation given: $.paths..responses[?( @property == 200 )].content[*]~
given: "$..definitions..[?(@property !== 'properties' && @.example && (@.type || recommended: true
@.format || @.$ref))]" formats:
then: - oas3
function: schemaPath message: "Response documents MUST be of application/hal+json or application/problem+json media types: {{error}}"
functionOptions: then:
field: example function: enumeration
schemaPath: "$" functionOptions:
values:
adidas-oas3-protocol-https-only: # checks how does the servers array values start - application/hal+json
description: "ALL requests MUST go through `https` protocol only" - application/problem+json
formats:
- oas3 adidas-oas3-response-success-hal-body: # schemes and/or produces
recommended: true description: "All success responses MUST follow `application/hal+json` schema"
severity: error severity: error
message: "Servers MUST be https and no other protocol is allowed." given: $.paths..responses[?( @property == 200 && @property < 300 && @property != 204)].content[?(@property === "application/hal+json")]
given: $.servers..url recommended: true
then: type: "style"
function: pattern formats:
functionOptions: - oas3
match: "/^https:/" message: "Response documents MUST follow application/hal+json schema: {{error}}"
then:
adidas-oas3-response-success-hal: field: schema
description: "All success responses MUST be of media type `application/hal+json` " function: schema
severity: error functionOptions:
given: $.paths..responses[?( @property >= 201 && @property < 300 && @property != 204)].content[*]~ schema:
recommended: true $ref: "./supermodel/adidas/api/HAL.yaml"
# type: "style"
formats:
- oas3 # ---------------------------------------------------------------------------
message: "Response documents MUST be of application/hal+json media types: {{error}}" # Not implemented
then: # ---------------------------------------------------------------------------
function: enumeration
functionOptions: # ---------------------------------------------------------------------------
values: # Other rules which are redundant or not feasible
- application/hal+json # ---------------------------------------------------------------------------
# sync and async patterns that can return hal OR problem+json # fields-date-iso8601:
adidas-oas3-response-success-OK: # description: Date and time MUST follow [`ISO 8601` standard](https://www.iso.org/iso-8601-date-and-time-format.html)
description: "All success responses MUST be of media type `application/hal+json` or `application/problem+json`" # severity: error
severity: error # fields-language-iso639:
given: $.paths..responses[?( @property == 200 )].content[*]~ # description: Language codes MUST follow [`ISO 639` standard](https://www.iso.org/iso-639-language-codes.html)
recommended: true # severity: error
formats: # fields-country-iso3166:
- oas3 # description: Country codes MUST follow [`ISO 3166 alpha-2` standard](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)
message: "Response documents MUST be of application/hal+json or application/problem+json media types: {{error}}" # severity: error
then: # fields-currency-iso4217:
function: enumeration # description: Currency codes MUST follow [`ISO 4217` standard](https://en.wikipedia.org/wiki/ISO_4217)
functionOptions: # severity: error
values: # response-303-async-link-header:
- application/hal+json # description: A successful and finished async api request returns `303` response code and sends the target resource location in the `Link` header
- application/problem+json # severity: hint
adidas-oas3-response-success-hal-body: # schemes and/or produces
description: "All success responses MUST follow `application/hal+json` schema"
severity: error
given: $.paths..responses[?( @property == 200 && @property < 300 && @property != 204)].content[?(@property === "application/hal+json")]
recommended: true
type: "style"
formats:
- oas3
message: "Response documents MUST follow application/hal+json schema: {{error}}"
then:
field: schema
function: schema
functionOptions:
schema:
$ref: "./supermodel/adidas/api/HAL.yaml"
# ---------------------------------------------------------------------------
# Not implemented
# ---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# Other rules which are redundant or not feasible
# ---------------------------------------------------------------------------
# fields-date-iso8601:
# description: Date and time MUST follow [`ISO 8601` standard](https://www.iso.org/iso-8601-date-and-time-format.html)
# severity: error
# fields-language-iso639:
# description: Language codes MUST follow [`ISO 639` standard](https://www.iso.org/iso-639-language-codes.html)
# severity: error
# fields-country-iso3166:
# description: Country codes MUST follow [`ISO 3166 alpha-2` standard](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)
# severity: error
# fields-currency-iso4217:
# description: Currency codes MUST follow [`ISO 4217` standard](https://en.wikipedia.org/wiki/ISO_4217)
# severity: error
# response-303-async-link-header:
# description: A successful and finished async api request returns `303` response code and sends the target resource location in the `Link` header
# severity: hint

View File

@@ -1,6 +1,8 @@
# adidas API Guidelines # adidas API Guidelines
![adidas logo](adidaslogo.jpg)
<figure><picture><source srcset=".gitbook/assets/adidas_company_logo_BWr.png" media="(prefers-color-scheme: dark)"><img src=".gitbook/assets/adidas_company_logo_BWp.png" alt=""></picture><figcaption></figcaption></figure>
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -8,7 +10,7 @@
### Motivation ### Motivation
The goal of this document is to facilitate the work and minimize the effort of all API users at adidas while protecting their investment and encouraging API adoption. The goal of this document is to facilitate the work and minimize the effort of all API users at adidas while protecting their investment and encouraging API First adoption.
These guidelines lay down the foundation for collaboration, stability, and extensibility. These guidelines lay down the foundation for collaboration, stability, and extensibility.
@@ -19,13 +21,15 @@ The API Guidelines are split into two main parts:
* [General Guidelines](general-guidelines/general-guidelines.md) * [General Guidelines](general-guidelines/general-guidelines.md)
* API type-specific Guidelines * API type-specific Guidelines
* [REST APIs Guidelines](rest-api-guidelines/rest.md) * [REST APIs Guidelines](rest-api-guidelines/rest.md)
* [Asynchronous APIs Guidelines](asynchronous-api-guidelines/index.md) * [Asynchronous APIs Guidelines](https://github.com/cesareomacias/api-guidelines/blob/master/asynchronous-api-guidelines/index.md)
The general guidelines section discusses the core principles relevant to any kind of API. The API type-specific section further defines the guidelines specific to a given architectural style or API technique (such as REST, Kafka or GraphQL APIs). The general guidelines section discusses the core principles relevant to any kind of API.&#x20;
The API type-specific section further defines the guidelines specific to a given architectural style or API technique (such as REST, Kafka or GraphQL APIs).
### How to read the Guidelines ### How to read the Guidelines
These Guidelines are available for online reading at [GitBook](https://adidas.gitbook.io/api-guidelines/). The source code can be found on [GitHub](https://github.com/adidas/api-guidelines). These guidelines are available for online reading at [GitBook](https://adidas.gitbook.io/api-guidelines/). The source code can be found on [GitHub](https://github.com/adidas/api-guidelines).
The CAPITALIZED words throughout these guidelines have a special meaning: The CAPITALIZED words throughout these guidelines have a special meaning:
@@ -35,41 +39,47 @@ The CAPITALIZED words throughout these guidelines have a special meaning:
> this document are to be interpreted as described in RFC2119. > this document are to be interpreted as described in RFC2119.
> ``` > ```
Refer to [RFC2119](https://www.ietf.org/rfc/rfc2119) for details. Refer to [RFC2119](https://www.rfc-editor.org/rfc/rfc2119) for details.
### Validating your API Guidelines against OpenAPI Specification ### Validating your API Guidelines against OpenAPI Specification
In the `ruleset.md` file you can find a digest of API Guidelines rules which you can use to validate your API description documents. If you are using OpenAPI Specification as the API description format you can also leverage the `.spectral.yaml` ruleset to automatically verify your specification compliance using [Spectral](github.com/stoplightio/spectral/). In the `ruleset.md` file you can find a digest of API Guidelines rules which you can use to validate your API description documents.
To install Spectral you will need Node.js and a package manager (npm or yarn). If you are using OpenAPI or AsyncAPI specification as API description format, you can also leverage the `adidas-spectral.yaml` ruleset to automatically lint your specification compliance using [Spectral](https://meta.stoplight.io/docs/spectral/674b27b261c3c-overview).
Note: The version used with the spectral specifications was 5.3.0 > To install Spectral, you will need Node.js and a package manager (npm or yarn).
``` ```bash
npm install -g @stoplight/spectral@5.3.0 npm install -g @stoplight/spectral-cli
# OR # OR
yarn global add @stoplight/spectral@5.3.0 yarn global add @stoplight/spectral-cli
``` ```
Once installed, to verify your OAS file with spectral execute `spectral lint <oas-file> -r <adidas-api-guidelines-folder>/.spectral.yaml` where `<adidas-api-guidelines-folder>/.spectral.yaml` indicated the location `.spectral.yaml` file. Once installed, to verify your _oas_ or _async_ file with spectral execute:
For further documentation on Spectral refer to their [documentation](https://stoplight.io/p/docs/gh/stoplightio/spectral/README.md). ```bash
spectral lint <api-specification-file> --ruleset adidas-spectral.yaml
```
### Questions & Comments ### Contact Us
_Please contact_ [_jesusjavier.dediego@adidas.com_](mailto:jesusjavier.dediego@adidas.com) _in case of questions._ In case you have any questions or comments, please utilize the appropriate GitHub collaboration tools, such as issues, pull requests, and discussions.
If you want to contact adidas API Team regarding these guidelines, you can mail us at
&#x20;_**api-team@adidas.com**_
## Intended Use Cases ## Intended Use Cases
This project is intended to provide the guidelines for design & development of APIs at adidas. This project is intended to provide the guidelines for design & development of APIs at adidas.
adidas is not responsible for the usage of this software for different purposes that the ones described in the use cases. Adidas is not responsible for the usage of this software for different purposes that the ones described in the use cases.
## Last Review ## Last Review
May 2024 February 2025
## License and Software Information ## License and Software Information
@@ -77,12 +87,6 @@ May 2024
adidas AG publishes this software and accompanied documentation (if any) subject to the terms of the MIT license with the aim of helping the community with our tools and libraries which we think can be also useful for other people. You will find a copy of the MIT license in the root folder of this package. All rights not explicitly granted to you under the MIT license remain the sole and exclusive property of adidas AG. adidas AG publishes this software and accompanied documentation (if any) subject to the terms of the MIT license with the aim of helping the community with our tools and libraries which we think can be also useful for other people. You will find a copy of the MIT license in the root folder of this package. All rights not explicitly granted to you under the MIT license remain the sole and exclusive property of adidas AG.
NOTICE: The software has been designed solely for the purpose of providing API design and development guidelines. The software is NOT designed, tested or verified for productive use whatsoever, nor or for any use related to high risk environments, such as health care, highly or fully autonomous driving, power plants, or other critical infrastructures or services. NOTICE: The software has been designed solely for the purpose of providing API design and development guidelines. The software is NOT designed, tested or verified for productive use whatsoever, nor or for any use related to high-risk environments, such as health care, highly or fully autonomous driving, power plants, or other critical infrastructures or services.
If you want to contact adidas regarding the software, you can mail us at _software.engineering@adidas.com_.
For further information open the [adidas terms and conditions](https://github.com/adidas/adidas-contribution-guidelines/wiki/Terms-and-conditions) page. For further information open the [adidas terms and conditions](https://github.com/adidas/adidas-contribution-guidelines/wiki/Terms-and-conditions) page.
### License
[MIT](https://github.com/adidas/api-guidelines/blob/master/LICENSE)

275
adidas-spectral.yaml Normal file
View File

@@ -0,0 +1,275 @@
extends: [[spectral:oas, all], [spectral:asyncapi, all]]
documentationUrl: https://github.com/adidas/api-guidelines/blob/master/ruleset.md
rules:
operation-tags: off
operation-operationId: off
operation-success-response: error
# ----------------------------#
# Adidas OAS v2.0, v3.0 rules #
# ----------------------------#
adidas-paths-kebab-case:
description: All YAML/JSON paths MUST follow kebab-case
severity: warn
recommended: true
message: "{{property}} is not kebab-case: {{error}}"
given: $.paths[*]~
then:
function: pattern
functionOptions:
match: "^\/([a-z0-9]+(-[a-z0-9]+)*)?(\/[a-z0-9]+(-[a-z0-9]+)*|\/{.+})*$" # doesn't allow /asasd{asdas}sadas pattern or not closed braces
adidas-path-parameters-camelCase-alphanumeric:
description: Path parameters MUST follow camelCase
severity: warn
recommended: true
message: "{{property}} path parameter is not camelCase: {{error}}"
given: $..parameters[?(@.in == 'path')].name
then:
function: pattern
functionOptions:
match: "^[a-z][a-zA-Z0-9]+$"
adidas-definitions-camelCase-alphanumeric:
description: All YAML/JSON definitions MUST follow fields-camelCase and be ASCII alphanumeric characters or `_` or `$`.
severity: error
recommended: true
message: "{{property}} MUST follow camelCase and be ASCII alphanumeric characters or `_` or `$`."
given: $.definitions[*]~
then:
function: pattern
functionOptions:
match: "/^[a-z$_]{1}[A-Z09$_]*/"
adidas-properties-camelCase-alphanumeric:
description: All JSON Schema properties MUST follow fields-camelCase and be ASCII alphanumeric characters or `_` or `$`.
severity: error
recommended: true
message: "{{property}} MUST follow camelCase and be ASCII alphanumeric characters or `_` or `$`."
given: $.definitions..properties[*]~
then:
function: pattern
functionOptions:
match: "/^[a-z$_]{1}[A-Z09$_]*/"
adidas-request-GET-no-body:
description: "A 'GET' request MUST NOT accept a 'body` parameter"
severity: error
given: $.paths..get.parameters..in
then:
function: pattern
functionOptions:
notMatch: "/^body$/"
adidas-headers-no-x-headers:
description: "All 'HTTP' headers SHOULD NOT include 'X-' headers (https://tools.ietf.org/html/rfc6648)."
severity: warn
given: "$..parameters[?(@.in == 'header')].name"
message: "HTTP headers SHOULD NOT include 'X-' prefix."
recommended: true
type: style
then:
function: pattern
functionOptions:
notMatch: "/^(x|X)-/"
adidas-headers-hyphenated-pascal-case:
description: All `HTTP` headers MUST use `Hyphenated-Pascal-Case` notation
severity: error
given: "$..parameters[?(@.in == 'header')].name"
message: "'HTTP' headers MUST follow 'Hyphenated-Pascal-Case' notation"
recommended: true
type: style
then:
function: pattern
functionOptions:
match: "/^([A-Z][a-z0-9]-)*([A-Z][a-z0-9])+/"
# ----------------------#
# Adidas OAS v2.0 rules #
# ----------------------#
adidas-oas2-protocol-https-only:
description: "ALL requests MUST go through `https` protocol only"
formats:
- oas2
recommended: true
severity: error
type: "style"
message: "Schemes MUST be https and no other value is allowed."
given: $
then:
field: schemes
function: schema
functionOptions:
schema:
type: array
items:
type: string
enum: ["https"]
maxItems: 1
adidas-oas2-request-support-json:
description: Every request SHOULD support `application/json` media type
formats:
- oas2
severity: warn
message: "{{description}}: {{error}}"
recommended: true
given: "$..consumes"
then:
function: schema
functionOptions:
schema:
type: array
contains:
type: string
enum:
- application/json
adidas-oas2-example-exists-in-parameters:
description: All models MUST have a valid example.
severity: error
recommended: true
formats:
- oas2
message: "{{ property }} MUST have a valid example."
given: "$..parameters..[?(@.in == 'body' && (@.example || @.schema.$ref))]"
then:
function: truthy
# example-exists-in-definitions covery by oas2-valid-media-example
adidas-oas2-response-success-hal: # schemes and/or produces
description: "All success responses MUST be of media type `application/hal+json`"
severity: error
given: $.paths..responses[?( @property >= 200 && @property < 300 && @property != 204)]
recommended: true
type: "style"
formats:
- oas2
message: "Response documents MUST follow application/hal+json: {{error}}"
then:
field: schema
function: schema
functionOptions:
schema:
$ref: "./supermodel/adidas/api/HAL.yaml"
adidas-oas2-response-error-problem: # schemas and/or produces
description: All error responses MUST be of media type `application/problem+json`
severity: error
formats:
- oas2
given: $.paths..responses[?( @property >= 400 && @property < 600 )]
recommended: true
type: "style"
message: "Error response document MUST follow application/problem+json: {{error}}"
then:
field: schema.example
function: schema
functionOptions:
schema:
$ref: "./supermodel/adidas/api/ProblemDetail.yaml"
# ----------------------#
# Adidas OAS v3.0 rules #
# ----------------------#
adidas-oas3-request-support-json:
description: Every request MUST support `application/json` media type
formats:
- oas3
recommended: true
severity: error
message: "{{description}}: {{error}}"
given: $.paths.[*].requestBody.content[?(@property.indexOf('json') === -1)]^
then:
function: falsy
# adidas-oas3-valid-example-in-parameters && adidas-oas3-valid-example-in-definitions covered by oas3-valid-media-example
adidas-oas3-protocol-https-only:
description: "ALL requests MUST go through `https` protocol only"
formats:
- oas3
recommended: true
severity: error
message: "Servers MUST be https and no other protocol is allowed."
given: $.servers..url
then:
function: pattern
functionOptions:
match: "/^https:/"
adidas-oas3-response-success-hal:
description: "All success responses MUST be of media type `application/hal+json` "
severity: error
given: $.paths..responses[?( @property >= 201 && @property < 300 && @property != 204)].content[*]~
recommended: true
formats:
- oas3
message: "Response documents MUST be of application/hal+json media types: {{error}}"
then:
function: enumeration
functionOptions:
values:
- application/hal+json
# sync and async patterns that can return hal OR problem+json
adidas-oas3-response-success-OK:
description: "All success responses MUST be of media type `application/hal+json` or `application/problem+json`"
severity: error
given: $.paths..responses[?( @property == 200 )].content[*]~
recommended: true
formats:
- oas3
message: "Response documents MUST be of application/hal+json or application/problem+json media types: {{error}}"
then:
function: enumeration
functionOptions:
values:
- application/hal+json
- application/problem+json
adidas-oas3-response-success-hal-body: # schemes and/or produces
description: "All success responses MUST follow `application/hal+json` schema"
severity: error
given: $.paths..responses[?( @property == 200 && @property < 300 && @property != 204)].content[?(@property === "application/hal+json")]
recommended: true
type: "style"
formats:
- oas3
message: "Response documents MUST follow application/hal+json schema: {{error}}"
then:
field: schema
function: schema
functionOptions:
schema:
$ref: "./supermodel/adidas/api/HAL.yaml"
# ---------------------------------------------------------------------------
# Not implemented
# ---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# Other rules which are redundant or not feasible
# ---------------------------------------------------------------------------
# fields-date-iso8601:
# description: Date and time MUST follow [`ISO 8601` standard](https://www.iso.org/iso-8601-date-and-time-format.html)
# severity: error
# fields-language-iso639:
# description: Language codes MUST follow [`ISO 639` standard](https://www.iso.org/iso-639-language-codes.html)
# severity: error
# fields-country-iso3166:
# description: Country codes MUST follow [`ISO 3166 alpha-2` standard](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)
# severity: error
# fields-currency-iso4217:
# description: Currency codes MUST follow [`ISO 4217` standard](https://en.wikipedia.org/wiki/ISO_4217)
# severity: error
# response-303-async-link-header:
# description: A successful and finished async api request returns `303` response code and sends the target resource location in the `Link` header
# severity: hint

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -50,10 +50,9 @@ Spectral can also be used from within JavaScript. For details on how to accompli
## Validating with Adidas API Guidelines ## Validating with Adidas API Guidelines
To check whether your API Specification complies with Adidas API Guidelines you will need the `.spectral.yaml` file from this repository ([here](https://github.com/adidas/api-guidelines/blob/master/.spectral.yml)). To check whether your API Specification complies with Adidas API Guidelines you will need the `adidas-spectral.yaml` file from this repository ([here](https://github.com/adidas/api-guidelines/blob/master/adidas-spectral.yaml)).
``` ```
spectral lint <oas-file> -r <adidas-api-guidelines-folder>/.spectral.yaml spectral lint <oas-file> --ruleset adidas-spectral.yaml
``` ```
### Validation problems ### Validation problems

View File

@@ -1,13 +1,13 @@
{ {
"name": "api-guidelines", "name": "api-guidelines",
"version": "1.0.0", "version": "1.1.0",
"description": "adidas API guidelines", "description": "adidas API guidelines",
"repository": "git@github.com:adidas/api-guidelines.git", "repository": "https://github.com/adidas/api-guidelines",
"author": "software.engineering@adidas.com", "author": "api-team@adidas.com",
"license": "MIT", "license": "MIT",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@stoplight/spectral": "^5.3.0", "@stoplight/spectral": "^6.13.1",
"@supermodel/cli": "^0.46.29" "@supermodel/cli": "^0.46.29"
}, },
"scripts": { "scripts": {

View File

@@ -1,28 +1,27 @@
# API Testing CI Environment # API Testing CI Environment
This guide describes steps necessary for testing an API described in a swagger file with the [Dredd API Testing Framework](https://github.com/apiaryio/dredd) in a CI Environment \(Jenkins, TeamCity\). This guide describes steps necessary for testing an API described in a swagger file with the [Dredd API Testing Framework](https://github.com/apiaryio/dredd) in a CI Environment (Jenkins, TeamCity).
## Environment Prerequisites ## Environment Prerequisites
The following must be available in the CI environment before testing: The following must be available in the CI environment before testing:
1. **Node.js** runtime MUST be available in the CI environment: 1. **Node.js** runtime MUST be available in the CI environment:
```text ```
$ node -v $ node -v
v14.15.5 v14.15.5
``` ```
2. [**Dredd**](https://github.com/apiaryio/dredd) MUST be installed globally in the CI environment:
3. [**Dredd**](https://github.com/apiaryio/dredd) MUST be installed globally in the CI environment: ```
$ npm install -g dredd --no-optional
```
```text ```
$ npm install -g dredd --no-optional $ dredd --version
``` dredd v14.0.0
```
```text
$ dredd --version
dredd v14.0.0
```
## Testing an API ## Testing an API
@@ -30,23 +29,22 @@ The following must be available in the CI environment before testing:
To test an API within the CI environment provisioned as mentioned in the environment prerequisites, you will need the following: To test an API within the CI environment provisioned as mentioned in the environment prerequisites, you will need the following:
1. A `swagger.yaml` file with the description of API being tested 1. A `swagger.yaml` file with the description of API being tested
The OpenAPI Specifciation file should be fetched from [API Design Platform](design-plaform.md). In the case of SwaggerHub API Design Platform, the file can be fetched manually or via their API. Refer to [Integrating with the SwaggerHub API](https://swagger.io/blog/api-development/integrating-with-the-swaggerhub-api/), for details how to use SwaggerHub API. The OpenAPI Specifciation file should be fetched from [API Design Platform](https://github.com/cesareomacias/api-guidelines/blob/master/rest-api-guidelines/guides/design-plaform.md). In the case of SwaggerHub API Design Platform, the file can be fetched manually or via their API. Refer to [Integrating with the SwaggerHub API](https://swagger.io/blog/api-development/integrating-with-the-swaggerhub-api/), for details how to use SwaggerHub API.
Alternativelly this can also be a remote file e.g. SwaggerHub URL, if the API is public its OAS file and reachable from the testing host. Alternativelly this can also be a remote file e.g. SwaggerHub URL, if the API is public its OAS file and reachable from the testing host.
2. The host (address) of the service being tested
2. The host \(address\) of the service being tested ```
$ export API_HOST=http://deheremap7336.emea.adsint.biz:8004`
```text ```
$ export API_HOST=http://deheremap7336.emea.adsint.biz:8004`
```
### Running the Test ### Running the Test
Run: Run:
```text ```
$ dredd swagger.yaml $API_HOST $ dredd swagger.yaml $API_HOST
``` ```
@@ -54,8 +52,8 @@ $ dredd swagger.yaml $API_HOST
The Dredd will perform the tests and exits usually if the tests have passed. You can check the test result as with any other Unix tools with: The Dredd will perform the tests and exits usually if the tests have passed. You can check the test result as with any other Unix tools with:
```text ```
$ echo $? $ echo $?
``` ```
Everything else but `0` should break the build. The test results will be visible in the CLI \(log\) Everything else but `0` should break the build. The test results will be visible in the CLI (log)