Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/microcks/microcks-spectral-ruleset

A set of rules for Spectral that allows linting OpenAPI and AsyncAPI spec for Microcks conventions
https://github.com/microcks/microcks-spectral-ruleset

api asyncapi contract-testing linting-rules microcks mocking openapi spectral

Last synced: about 4 hours ago
JSON representation

A set of rules for Spectral that allows linting OpenAPI and AsyncAPI spec for Microcks conventions

Awesome Lists containing this project

README

        

# Microcks Spectral ruleset

A set of rules for [Spectral](https://github.com/stoplightio/spectral) that allows linting OpenAPI and AsyncAPI spec for Microcks conventions.

Microcks conventions for [OpenAPI](https://microcks.io/documentation/using/openapi/) and [AsyncAPI](https://microcks.io/documentation/using/asyncapi/) specification files can be sometime a little boring to apply and debug. This set of rules allows you to use your favorite linter to detect if some of the conventions are missing or are incomplete so that Microcks will be able to import comprehensive mocks 😉

This ruleset is initially targeting the [Spectral](https://github.com/stoplightio/spectral) linter but we also added a compatibility layer for [Vacuum](https://github.com/daveshanley/vacuum). As this is not our primary focus, we'll see what it means to support this layer in the long-term...

[![License](https://img.shields.io/github/license/microcks/microcks-testcontainers-java?style=for-the-badge&logo=apache)](https://www.apache.org/licenses/LICENSE-2.0)
[![Project Chat](https://img.shields.io/badge/discord-microcks-pink.svg?color=7289da&style=for-the-badge&logo=discord)](https://microcks.io/discord-invite/)
[![CNCF Landscape](https://img.shields.io/badge/CNCF%20Landscape-5699C6?style=for-the-badge&logo=cncf)](https://landscape.cncf.io/?item=app-definition-and-development--application-definition-image-build--microcks)

## Build Status

Latest released version is `0.0.5`.

Current development version is `0.0.6`.

#### Fossa license and security scans

[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fmicrocks%2Fmicrocks-spectral-ruleset.svg?type=shield&issueType=license)](https://app.fossa.com/projects/git%2Bgithub.com%2Fmicrocks%2Fmicrocks-spectral-ruleset?ref=badge_shield&issueType=license)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fmicrocks%2Fmicrocks-spectral-ruleset.svg?type=shield&issueType=security)](https://app.fossa.com/projects/git%2Bgithub.com%2Fmicrocks%2Fmicrocks-spectral-ruleset?ref=badge_shield&issueType=security)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fmicrocks%2Fmicrocks-spectral-ruleset.svg?type=small)](https://app.fossa.com/projects/git%2Bgithub.com%2Fmicrocks%2Fmicrocks-spectral-ruleset?ref=badge_small)

#### OpenSSF best practices on Microcks core

[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/7513/badge)](https://bestpractices.coreinfrastructure.org/projects/7513)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/microcks/microcks/badge)](https://securityscorecards.dev/viewer/?uri=github.com/microcks/microcks)

## Community

* [Documentation](https://microcks.io/documentation/tutorials/getting-started/)
* [Microcks Community](https://github.com/microcks/community) and community meeting
* Join us on [Discord](https://microcks.io/discord-invite/), on [GitHub Discussions](https://github.com/orgs/microcks/discussions) or [CNCF Slack #microcks channel](https://cloud-native.slack.com/archives/C05BYHW1TNJ)

To get involved with our community, please make sure you are familiar with the project's [Code of Conduct](./CODE_OF_CONDUCT.md).

## How to use it?

Developers wanting to pull the ruleset can just install the package using `yarn` or `npm` and reference the module name in `extends`:

```yaml
extends:
- "@microcks/spectral-ruleset"
```

Locking a ruleset on a given version is possible through `package.json`:

```json
{
"dependencies": {
"@microcks/spectral-ruleset": "0.0.5"
}
}
```

If you use Spectral in a browser or don't want to install the package, you can also reference that package through the use of CDNs for npm repositories, such as `unpkg.com`. You can then put directly in your own rules our `.spectral.yaml` file, the following directive:

```yaml
extends:
- "https://unpkg.com/@microcks/[email protected]"
```

## What results to expect?

To illustrate the results of applying the ruleset, let's have a look at the [Weather Forecast API](./resources/weather-forecast-openapi-bad.yaml) OpenAPI specification. Eventhough everything looks nice at a first look, some issues will prevent Microcks to collect and build comprhensive mocks from the spec elements:

1. [L39](./resources/weather-forecast-openapi-bad.yamlL39): `unknown` is an expected response (see L96) but no value has been defined for this parameter. Microcks will not be able to associate response with parameter value,
2. [L54](./resources/weather-forecast-openapi-bad.yamlL54): `apiKey` parameter is required but no examples are provided. The mock will not be representative of expected API behavior,
3. [L95](./resources/weather-forecast-openapi-bad.yamlL95): `temp` has been defined as a number in the schema but we provided a string. The mock will not be consistent with the API types definition,
3. [L115](./resources/weather-forecast-openapi-bad.yamlL115): the `SetForecast` operation request define an example called `north` but no response has this name. Microcks will not be able to associate response with body value,
4. [L125](./resources/weather-forecast-openapi-bad.yamlL125): the `SetForecast` operation defines no examples for both the response. Microcks will not be able to guess mock values for these one,
5. [L140](./resources/weather-forecast-openapi-bad.yamlL140): the `DeleteForecast` operation defines an example for a region `center` and there's no response for this region. Microcks will not be able to find a suitable response,
6. [L146](./resources/weather-forecast-openapi-bad.yamlL146): the `DeleteForecast` operation is a no-content response so it uses `x-microcks-refs` to tell to what response elements it should bind the response. However, the `center-south` value has not be defined as a valid parameter value... Microcks will not be able to bind to a matching request,
7. [L18](./resources/weather-forecast-openapi-bad.yamlL18): `team` label used in `x-microcks` extension is not well-formed as it should just be a `string`,
8. [L30](./resources/weather-forecast-openapi-bad.yamlL30): `delay` information used in `x-microcks-operation` extension is not well-formed as it must be an `integer`.

Debugging everything by hand can be tedious... So here's how to detect those issues and get some hints on what's going wrong. ✨

### Using Spectral

We'll use the `microcks-rules.yaml` ruleset definition file here. If you followed the above instruction on how to use it via `unpkg`, you don't need to include the `-r microcks-rules.yaml` part of the command:

```shell
$ spectral --version
6.11.1

$ spectral lint -r microcks-rules.yaml resources/weather-forecast-openapi-bad.yaml

/Users/laurent/Development/github/microcks-spectral-ruleset/resources/weather-forecast-openapi-bad.yaml
18:12 warning microcks-info-extension-valid x-microcks extension must be valid info.x-microcks.labels.team
30:16 warning microcks-operation-extension-valid x-microcks-operation extension must be valid paths./forecast/{region}.get.x-microcks-operation.delay
49:11 warning microcks-examples-in-required-parameter Required param must have examples paths./forecast/{region}.get.parameters[1]
55:17 warning microcks-examples-fragments-to-complete-mocks 🚨 Response example 'unknown' is incomplete, it has no matching input example. It requires at least one requestBody or parameter example with same name to be considered as valid mock for Microcks. paths./forecast/{region}.get.responses
95:27 error oas3-valid-media-example "temp" property type must be number paths./forecast/{region}.get.responses[200].content.application/json.examples.south.value.temp
121:17 warning microcks-examples-fragments-to-complete-mocks ℹī¸ Request body example 'north' is not used in any response. It requires to have a matching response example or a x-microcks-refs to be considered as valid mock for Microcks. paths./forecast/{region}.put.responses
125:30 warning microcks-examples-in-response-content Response with content must have examples paths./forecast/{region}.put.responses[200].content.application/json
142:17 warning microcks-examples-fragments-to-complete-mocks 🔗 Response has x-microcks-refs 'center-south' but it doesn't match input example. It requires at least one requestBody or parameter example with same name to be considered as valid mock for Microcks. paths./forecast/{region}.delete.responses
142:17 warning microcks-examples-fragments-to-complete-mocks ℹī¸ Path parameter example 'center' is not used in any response. It requires to have a matching response example or a x-microcks-refs to be considered as valid mock for Microcks. paths./forecast/{region}.delete.responses

✖ 9 problems (1 error, 8 warnings, 0 infos, 0 hints)
```

If you'd like a more human-readable output of Microcks hints for a complete document, you can set the `MICROCKS_HINTS` environment variable to `true` when running spectral:

```shell
$ MICROCKS_HINTS=true spectral lint -r microcks-rules.yaml resources/weather-forecast-openapi-bad.yaml

🚨 Response example 'unknown' for 'paths./forecast/{region}.get' is incomplete, it has no matching input example.
It requires at least one requestBody or parameter example with same name to be considered as valid mock for Microcks.

ℹī¸ Request body example 'north' for 'paths./forecast/{region}.put' is not used in any response.
It requires to have a matching response example or a x-microcks-refs to be considered as valid mock for Microcks.

🔗 Response has x-microcks-refs 'center-south' for 'paths./forecast/{region}.delete' but it doesn't match input example.
It requires at least one requestBody or parameter example with same name to be considered as valid mock for Microcks.

ℹī¸ Path parameter example 'center' for 'paths./forecast/{region}.delete' is not used in any response.
It requires to have a matching response example or a x-microcks-refs to be considered as valid mock for Microcks.

/Users/laurent/Development/github/microcks-spectral-ruleset/resources/weather-forecast-openapi-bad.yaml
18:12 warning microcks-info-extension-valid x-microcks extension must be valid info.x-microcks.labels.team

[...]
```

### Using Vacuum

We'll use the `microcks-vacuum-rules.yaml` ruleset definition file here:

```shell
$ vacuum lint -r microcks-vacuum-rules.yaml -f ./functions resources/weather-forecast-openapi-bad.yaml -d

██╗ ██╗ █████╗ ██████╗██╗ ██╗██╗ ██╗███╗ ███╗
██║ ██║██╔══██╗██╔════╝██║ ██║██║ ██║████╗ ████║
██║ ██║███████║██║ ██║ ██║██║ ██║██╔████╔██║
╚██╗ ██╔╝██╔══██║██║ ██║ ██║██║ ██║██║╚██╔╝██║
╚████╔╝ ██║ ██║╚██████╗╚██████╔╝╚██████╔╝██║ ╚═╝ ██║
╚═══╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝

version: 0.9.16 | compiled: Thu, 09 May 2024 19:57:46 UTC
🔗 https://quobix.com/vacuum | https://github.com/daveshanley/vacuum

INFO Located custom javascript function: 'aas-verify-mocks'
ERROR Failed to load function 'aas-verify-mocks': SyntaxError: SyntaxError: (anonymous): Line 16:1 Unexpected reserved word (and 8 more errors)
INFO Located custom javascript function: 'oas-verify-mocks-vacuum'
INFO Located custom javascript function: 'oas-verify-mocks'
ERROR Failed to load function 'oas-verify-mocks': SyntaxError: SyntaxError: (anonymous): Line 16:1 Unexpected reserved word (and 20 more errors)
INFO Loaded 3 custom function(s) successfully.
INFO Linting file 'resources/weather-forecast-openapi-bad.yaml' against 7 rules: https://quobix.com/vacuum/rulesets/no-rules

2024/05/21 14:17:56
2024/05/21 14:17:56 🚨 Response example 'unknown' for 'GetForecast' is incomplete, it has no matching input example.
2024/05/21 14:17:56 It requires at least one requestBody or parameter example with same name to be considered as valid mock for Microcks.
2024/05/21 14:17:56
2024/05/21 14:17:56 ℹī¸ Request body example 'north' for 'SetForecast' is not used in any response.
2024/05/21 14:17:56 It requires to have a matching response example or a x-microcks-refs to be considered as valid mock for Microcks.
2024/05/21 14:17:56
2024/05/21 14:17:56 🔗 Response has x-microcks-refs 'center-south' for 'DeleteForecast' but it doesn't match input example.
2024/05/21 14:17:56 It requires at least one requestBody or parameter example with same name to be considered as valid mock for Microcks.
2024/05/21 14:17:56
2024/05/21 14:17:56 ℹī¸ Path parameter example 'center' for 'DeleteForecast' is not used in any response.
2024/05/21 14:17:56 It requires to have a matching response example or a x-microcks-refs to be considered as valid mock for Microcks.

/Users/laurent/Development/github/microcks-spectral-ruleset/resources/weather-forecast-openapi-bad.yaml
-------------------------------------------------------------------------------------------------------
Location | Severity | Message | Rule | Category | Path
resources/weather-forecast-openapi-bad.yaml:15:5 | warning | x-microcks extension must be valid | microcks-info-extension-valid | Validation | $.info[0]
resources/weather-forecast-openapi-bad.yaml:24:7 | warning | Response example 'unknown' is incomplete, it has no matching input example | microcks-examples-fragments-to-complete-mocks | Validation | $.paths.*.*
resources/weather-forecast-openapi-bad.yaml:30:9 | warning | x-microcks-operation extension must be valid | microcks-operation-extension-valid | Validation | $.paths.*.*[0]
resources/weather-forecast-openapi-bad.yaml:49:11 | info | Parameters should have examples | microcks-examples-in-parameter | Validation | $..parameters[0][1]
resources/weather-forecast-openapi-bad.yaml:92:17 | warning | expected number, but got string | oas3-valid-schema-example | Examples | $.paths['/forecast/{region}'].get.responses['200'].content['...
resources/weather-forecast-openapi-bad.yaml:108:7 | warning | Request body example 'north' is not used in any response | microcks-examples-fragments-to-complete-mocks | Validation | $.paths.*.*
resources/weather-forecast-openapi-bad.yaml:126:15 | warning | Response with content must have examples | microcks-examples-in-response-content | Validation | $.paths..responses..content.*
resources/weather-forecast-openapi-bad.yaml:129:7 | warning | Response has x-microcks-refs 'center-south' but it doesn't match input example | microcks-examples-fragments-to-complete-mocks | Validation | $.paths.*.*
resources/weather-forecast-openapi-bad.yaml:129:7 | warning | Path parameter example 'center' is not used in any response | microcks-examples-fragments-to-complete-mocks | Validation | $.paths.*.*

Category | Errors | Warnings | Info
Validation | 0 | 7 | 1
Examples | 0 | 1 | 0


Linting passed, but with 8 warnings and 1 informs

```

## Rules reference

### Microcks extensions

#### microcks-info-extension-valid

This rule will check that `info.x-microcks` is well-formed according to its schema information.

`x-microcks` OpenAPI and AsyncAPI extension allows you to provide `labels` for organizing your API and Services in Microcks. Labels are simple key/value pairs where keys and values are string.

**Severity:** `warn`

#### microcks-operation-extension-valid

This rule will check that `x-microcks-operation` provided for operation is well-formed according to its schema information.

`x-microcks-operation` OpenAPI and AsyncAPI extension allows you to provide custom dispatching rules and delays for your mocks. We'll check that attributes are known from Microcks to guarantee their application.

**Severity:** `warn`

### OpenAPI v3

#### Reused external rules

The Microcks ruleset imports the `oas3-valid-media-example` and `oas3-valid-schema-example` rules from the [Spectral OpenAPI Rules](https://meta.stoplight.io/docs/spectral/4dec24461f3af-open-api-rules).

These rules check that the `examples` definitions are conformant to the schema definition with the API specification. Having incorrect values or types will not prevent Microcks to produce mocks but these ones will be totally useless for people wanted to have a high-fidelity simulation of the API.

**Severity:** `error`

#### microcks-examples-in-required-parameter

This rule will ask you to provide named `examples` for parameters marqued as required.

Putting named `examples` in parameters allows you to explicit values of parameters depending on different situation and then to later bind them with corresponding request body or response. This provide a better overview of the expected behavior of your API for people who will discover it. Not providing these examples prevents Microcks from producing correct and representative mocks.

**Severity:** `warn`

#### microcks-examples-in-optional-parameter

This rule will recommend you to provide named `examples` for parameters marqued as optional.

Putting named `examples` in parameters allows you to explicit values of parameters depending on different situation and then to later bind them with corresponding request body or response. This provide a better overview of the expected behavior of your API for people who will discover it.

**Severity:** `info`

#### microcks-examples-in-request-content

This rule will ask you to provide named `examples` within `requestBody.content.*`.

Putting named `examples` in request content allows you to explicit payload depending on different situation and then to later bind them with corresponding response. This provide a better overview of the expected behavior of your API for people who will discover it. Not providing these examples prevents Microcks from producing mocks.

**Severity:** `warn`

#### microcks-examples-in-response-content

This rule will ask you to provide named `examples` within `responses.*.content.*`.

Putting named `examples` in response content allows you to explicit payload depending on different situation and then to later bind them with corresponding request body or parameter values. This provide a better overview of the expected behavior of your API for people who will discover it. Not providing these examples prevents Microcks from producing mocks.

**Severity:** `warn`

#### microcks-examples-fragments-to-complete-mocks

This rule will check the coherence of different response, request and parameter examples to detect incomplete combination.

**Severity:** `warn`

### AsyncAPI v2.x

#### Reused external rules

The Microcks ruleset imports the `asyncapi-message-examples` from the [Spectral AsyncAPI Rules](https://docs.stoplight.io/docs/spectral/1e63ffd0220f3-async-api-rules).

This rule checks that the `examples` definitions are conformant to the schema definition with the API specification. Having incorrect values or types will not prevent Microcks to produce mocks but these ones will be totally useless for people wanted to have a high-fidelity simulation of the API.

**Severity:** `error`

#### microcks-aas-examples-in-message

This rule will ask you to provide named `examples` within `$.channels.*.[publish,subscribe].message`.

Putting named `examples` in message allows you to explicit payload depending on different situation and then optionally to later bind them with corresponding parameter values. This provide a better overview of the expected behavior of your API for people who will discover it. Not providing these examples prevents Microcks from producing mocks.

**Severity:** `warn`

#### microcks-aas-examples-in-parameter

This rule will ask you to provide named `examples` within `$.channels.*.parameters.*.schema`.

Putting named `examples` in channel parameters allows you to explicit values of parameters depending on different situation and then to later bind them with corresponding message content. This provide a better overview of the expected behavior of your API for people who will discover it. Not providing these examples prevents Microcks from producing correct and representative mocks.

**Severity:** `warn`

#### microcks-aas-examples-fragments-to-complete-mocks

This rule will check the coherence of different messages and parameter examples to detect incomplete combination.

**Severity:** `warn`