Skip to content

Commit 262285b

Browse files
milkshakeukandreyyudin
authored andcommitted
feat(spectral): introduce severity overrides and handle pygeoapi
- add overrideSeverity ruleset function and connect a pygeoapi-specific override rule - add may-have-info-x-api-type rule with docs/examples and clearer downgrade messaging - switch jest to swc-backed ts testing and align tsconfig and build outputs - switch jest config to CommonJS/node16 to allow proper imports
1 parent e175b9c commit 262285b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1594
-766
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
.cache
44
coverage/
55
node_modules/
6-
dist/
6+
dist/

.swcrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"jsc": {
3+
"parser": {
4+
"syntax": "typescript"
5+
}
6+
}
7+
}

docs/spectral-rules/index.md

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,67 @@ As well as the rules described herein, the UKHSA ruleset includes the [recommend
1515

1616
Where rules been adopted from from existing open source API rulesets a link is supplied on the relevant rule page.
1717

18+
## Pygeoapi severity overrides
19+
20+
Some definitions (for example, produced by pygeoapi) cannot yet meet every **MUST** requirement in the ruleset. When an OpenAPI document is marked with `info.x-api-type: pygeoapi`, the ruleset automatically downgrades the following error-level rules to `warn`:
21+
22+
- `must-define-a-format-for-integer-types`
23+
- `must-define-a-format-for-number-types`
24+
- `must-define-security-schemes`
25+
- `must-have-info-api-audience`
26+
- `must-have-info-contact-email`
27+
- `must-have-info-value-chain`
28+
- `must-have-info-version`
29+
- `must-specify-default-response`
30+
- `must-use-camel-case-for-property-names`
31+
- `must-use-camel-case-for-query-parameters`
32+
- `must-use-https-protocol-only`
33+
- `must-use-problem-json-as-default-response`
34+
- `must-use-problem-json-for-errors`
35+
- `must-use-valid-version-info-schema`
36+
37+
Other rules continue to run normally, so pygeoapi definitions should still be linted and improved where possible. Rules already at `warn` are not changed.
38+
39+
### `info.x-api-type` values
40+
41+
To make intent explicit, the `info.x-api-type` field can be treated as an enum in API definitions to indicate the API category:
42+
43+
- `standard` – default behavior; no overrides applied.
44+
- `pygeoapi` – pygeoapi-based definitions; error-level rules listed above are downgraded to `warn`.
45+
46+
If you omit `info.x-api-type`, the ruleset assumes the API is `standard`.
47+
48+
See also: [MAY have info.x-api-type][6].
49+
50+
When generating a definition from a local pygeoapi instance, you can inject the `info.x-api-type` flag during export so relaxed severities will be applied. The example below wraps the `pygeoapi openapi generate` command in Docker, binds your local configuration, and uses `yq` to add `info.x-api-type: pygeoapi` before writing the result to `openapi-pygeoapi.yml`.
51+
52+
```sh
53+
docker run --entrypoint= --rm -p 5000:80 \
54+
--mount type=bind,src=./pygeoapi-config.yml,dst=/pygeoapi/config.yml \
55+
-e PYGEOAPI_CONFIG=/pygeoapi/config.yml geopython/pygeoapi:latest \
56+
sh -c 'pygeoapi openapi generate $PYGEOAPI_CONFIG' \
57+
| yq '.info += {"x-api-type": "pygeoapi"}' - > openapi-pygeoapi.yml
58+
```
59+
1860
## How to use the rules
1961

2062
### Install Spectral
2163

22-
[Spectral][6] is a flexible JSON/YAML linter for creating automated style guides, with baked in support for OpenAPI (v3.1, v3.0, and v2.0), Arazzo v1.0, as well as AsyncAPI v2.x.
64+
[Spectral][7] is a flexible JSON/YAML linter for creating automated style guides, with baked in support for OpenAPI (v3.1, v3.0, and v2.0), Arazzo v1.0, as well as AsyncAPI v2.x.
2365

2466
Install Spectral globally or as a dev dependency.
2567

2668
```sh
2769
npm install @stoplight/spectral-cli --save-dev
2870
```
2971

30-
Read the [official spectral documentation][7] for more installation options.
72+
Read the [official spectral documentation][8] for more installation options.
3173

3274
### Run Spectral against your OpenAPI definition
3375

3476
Run Spectral against your OpenAPI definition, referencing the spectral ruleset.
3577

36-
You must install the ruleset as via [npm package][8] and then reference that, bear in mind the UKHSA ruleset npm package is hosted in github so please read Github's documentation [Installing a GitHub npm package][9].
78+
You must install the ruleset as via [npm package][9] and then reference that, bear in mind the UKHSA ruleset npm package is hosted in github so please read Github's documentation [Installing a GitHub npm package][10].
3779

3880
```sh
3981
npm install @ukhsa-collaboration/spectral-rules --save-dev
@@ -104,7 +146,7 @@ jobs:
104146
# npx spectral lint "@(openapi|swagger|*api)*.{json,yml,yaml}" -r ${{ GITHUB.WORKSPACE }}/node_modules/@ukhsa-collaboration/spectral-rules/.spectral.yaml -f github-actions
105147
```
106148
107-
The above example uses [glob syntax][10] to target only OpenAPI specification files.
149+
The above example uses [glob syntax][11] to target only OpenAPI specification files.
108150
109151
The glob pattern `@(openapi|swagger|*api)*.{json,yml,yaml}` matches:
110152

@@ -125,21 +167,22 @@ The global pattern does not match:
125167

126168
| Tool | Description |
127169
| - | - |
128-
| [VS Code Extension][11] | Official spectral VS Code extension provides real time linting / intellisense on your OpenAPI definition. |
129-
| [Github Action][12] | Official spectral Github action provides ability to lint your OpenAPI definition in CI/CD workflows. |
170+
| [VS Code Extension][12] | Official spectral VS Code extension provides real time linting / intellisense on your OpenAPI definition. |
171+
| [Github Action][13] | Official spectral Github action provides ability to lint your OpenAPI definition in CI/CD workflows. |
130172

131-
Read the [official spectral documentation][13] for more development workflows.
173+
Read the [official spectral documentation][14] for more development workflows.
132174

133175
[1]: ../api-guidelines/index.md
134176
[2]: https://docs.stoplight.io/docs/spectral/0a73453054745-recommended-or-all
135177
[3]: https://docs.stoplight.io/docs/spectral/4dec24461f3af-open-api-rules
136178
[4]: https://github.com/stoplightio/spectral-documentation
137179
[5]: https://swagger.io/specification/
138-
[6]: https://docs.stoplight.io/docs/spectral
139-
[7]: https://docs.stoplight.io/docs/spectral/b8391e051b7d8-installation
140-
[8]: https://meta.stoplight.io/docs/spectral/7895ff1196448-sharing-and-distributing-rulesets#npm
141-
[9]: https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry#installing-a-package
142-
[10]: https://github.com/mrmlnc/fast-glob
143-
[11]: https://marketplace.visualstudio.com/items?itemName=stoplight.spectral
144-
[12]: https://github.com/marketplace/actions/spectral-linting
145-
[13]: https://docs.stoplight.io/docs/spectral/ecaa0fd8a950d-workflows
180+
[6]: may/may-have-info-x-api-type.md
181+
[7]: https://docs.stoplight.io/docs/spectral
182+
[8]: https://docs.stoplight.io/docs/spectral/b8391e051b7d8-installation
183+
[9]: https://meta.stoplight.io/docs/spectral/7895ff1196448-sharing-and-distributing-rulesets#npm
184+
[10]: https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry#installing-a-package
185+
[11]: https://github.com/mrmlnc/fast-glob
186+
[12]: https://marketplace.visualstudio.com/items?itemName=stoplight.spectral
187+
[13]: https://github.com/marketplace/actions/spectral-linting
188+
[14]: https://docs.stoplight.io/docs/spectral/ecaa0fd8a950d-workflows

docs/spectral-rules/may/index.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
includeInBreadcrumbs: true
3+
eleventyNavigation:
4+
parent: spectral-rules
5+
key: may
6+
---
7+
8+
# MAY
9+
10+
Spectral rules categorised as **MAY** highlight optional practices. They can be adopted when they add value or context, and teams should weigh them based on preference, consumer needs, or implementation constraints.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# **MAY** have info.x-api-type
2+
3+
APIs **MAY** include an `info.x-api-type` field to indicate the API category. When present, the value **MUST** be either `standard` or `pygeoapi`. If the field is omitted, the ruleset assumes the API is `standard`.
4+
5+
> [!IMPORTANT]
6+
> Using `info.x-api-type: pygeoapi` signals pygeoapi-based definitions and enables conditional severity downgrades for certain rules. See [1].
7+
8+
## Valid Examples
9+
10+
```yaml
11+
info:
12+
title: Test Results API
13+
version: 1.0.0
14+
x-api-type: standard
15+
```
16+
17+
```yaml
18+
info:
19+
title: Geospatial API
20+
version: 1.0.0
21+
x-api-type: pygeoapi
22+
```
23+
24+
## Invalid Example
25+
26+
```yaml
27+
info:
28+
title: Something
29+
version: 1.0.0
30+
x-api-type: experimental-non-pygeoapi
31+
```
32+
33+
[1]: ../index.md#pygeoapi-severity-overrides
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"sectionKey": "spectral-rules",
3+
"layout": "sub-navigation",
4+
"caption": "MAY"
5+
}

docs/spectral-rules/must/must-define-a-format-for-integer-types.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
`integer` properties **MUST** have a format defined (`int32`, `int64`, or `bigint`).
44

5+
> [!IMPORTANT]
6+
> For openapi definitions marked with `info.x-api-type: pygeoapi`, this rule’s severity is automatically set to `warn` by the `override-severity-pygeoapi` rule. See [1].
7+
58
## Invalid Example
69

710
```yaml
@@ -29,6 +32,7 @@ requestBody:
2932
format: int32
3033
```
3134
32-
[Zalando Guideline 171][1]
35+
[Zalando Guideline 171][2]
3336
34-
[1]: https://opensource.zalando.com/restful-api-guidelines/#171
37+
[1]: ../index.md#pygeoapi-severity-overrides
38+
[2]: https://opensource.zalando.com/restful-api-guidelines/#171

docs/spectral-rules/must/must-define-a-format-for-number-types.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
`number` properties **MUST** have a format defined (`float`, `double`, or `decimal`).
44

5+
> [!IMPORTANT]
6+
> For openapi definitions marked with `info.x-api-type: pygeoapi`, this rule’s severity is automatically set to `warn` by the `override-severity-pygeoapi` rule. See [1].
7+
58
## Invalid Example
69

710
```yaml
@@ -29,6 +32,7 @@ requestBody:
2932
format: float
3033
```
3134
32-
[Zalando Guideline 171][1]
35+
[Zalando Guideline 171][2]
3336
34-
[1]: https://opensource.zalando.com/restful-api-guidelines/#171
37+
[1]: ../index.md#pygeoapi-severity-overrides
38+
[2]: https://opensource.zalando.com/restful-api-guidelines/#171

docs/spectral-rules/must/must-define-security-schemes.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
All APIs **MUST** have a security scheme defined.
44

5+
> [!IMPORTANT]
6+
> For openapi definitions marked with `info.x-api-type: pygeoapi`, this rule’s severity is automatically set to `warn` by the `override-severity-pygeoapi` rule. See [1].
7+
58
If an API doesn't have a security scheme defined, it means the entire API is open to the public. That's probably not what you want, even if all the data is read-only. Setting lower rate limits for the public and letting known consumers use more resources is a handy path to monetization, and helps know who your power users are when changes need feedback or migration, even if not just good practice.
69

710
## Valid Example
@@ -22,6 +25,7 @@ components:
2225
tests:write: submit test results
2326
```
2427
25-
[UKHSA Guidelines Security][1]
28+
[UKHSA Guidelines Security][2]
2629
27-
[1]: ../../api-guidelines/security.md#authentication
30+
[1]: ../index.md#pygeoapi-severity-overrides
31+
[2]: ../../api-guidelines/security.md#authentication

docs/spectral-rules/must/must-have-info-api-audience.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
The `info` object **MUST** have an `x-audience` that matches at least one of these values:
44

5+
> [!IMPORTANT]
6+
> For openapi definitions marked with `info.x-api-type: pygeoapi`, this rule’s severity is automatically set to `warn` by the `override-severity-pygeoapi` rule. See [1].
7+
58
| audience | Use case |
69
| - | - |
710
| `company-internal` | for internal use only with UKHSA |
@@ -16,3 +19,5 @@ info:
1619
title: Test Results Api
1720
x-audience: public-external
1821
```
22+
23+
[1]: ../index.md#pygeoapi-severity-overrides

0 commit comments

Comments
 (0)