Skip to content
Draft
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
29 changes: 29 additions & 0 deletions .github/workflows/validate-api.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Validate OpenAPI Spec
on:
push:
paths:
- 'api/**'
- '.spectral.yml'
pull_request:
paths:
- 'api/**'
- '.spectral.yml'

jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install Spectral
run: npm install -g @stoplight/spectral-cli

- name: Lint OpenAPI spec
run: spectral lint api/Govstack_scheduler_BB_APIs.json --ruleset .spectral.yml

- name: Check for stale API files
run: |
STALE=$(find spec/.gitbook/assets -name '*scheduler_api*' 2>/dev/null | wc -l)
if [ "$STALE" -gt 0 ]; then
echo "::warning::Found $STALE stale API files in spec/.gitbook/assets/"
fi
77 changes: 77 additions & 0 deletions .spectral.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
extends:
- "spectral:oas"

rules:
# Built-in rules
oas3-api-servers: warn
operation-operationId: error
oas3-valid-schema-example: warn

# Custom: security schemes must be defined
security-schemes-defined:
description: securitySchemes must be defined and not empty
severity: error
given: "$.components"
then:
field: securitySchemes
function: truthy

# Custom: global security must be defined
global-security-defined:
description: Top-level security block must be defined
severity: error
given: "$"
then:
field: security
function: truthy

# Custom: no auth tokens in query string
no-query-string-auth:
description: Auth parameters must not be passed as query strings
severity: error
given: "$.paths.*.*.parameters[?(@.in=='query')]"
then:
field: name
function: pattern
functionOptions:
notMatch: "[Tt]oken|[Aa]uth|[Kk]ey|[Ss]ecret|[Pp]assword"

# Custom: valid media type keys in response content
valid-media-type:
description: Response content-type keys must use standard media types
severity: error
given: "$.paths.*.*.responses.*.content"
then:
function: schema
functionOptions:
schema:
type: object
propertyNames:
pattern: "^(application|text|image|audio|video|multipart|font)/"

# Custom: POST create endpoints should return 201
post-create-returns-201:
description: Non-search POST endpoints should return 201
severity: warn
given: "$.paths[?(!@property.match(/search|availability/))].post.responses"
then:
field: "201"
function: truthy

# Custom: DELETE should return 204
delete-returns-204:
description: DELETE endpoints should return 204
severity: warn
given: "$.paths.*.delete.responses"
then:
field: "204"
function: truthy

# Custom: operations should have 401 response
has-401-response:
description: Operations should define a 401 response
severity: warn
given: "$.paths.*.*.responses"
then:
field: "401"
function: truthy
Loading