Skip to content
Open
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
22 changes: 22 additions & 0 deletions .github/workflows/openapi-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: openapi-ci

on:
pull_request:
# Only run the workflow when OpenAPI definition files in docs/api change
paths:
- 'docs/api/openapi.yaml'
- 'docs/api/*.yaml'

jobs:
build:
name: Run Spectral
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v3

- name: Run Spectral
uses: stoplightio/spectral-action@latest
with:
# Lint all YAML files under docs/api (this repo uses `docs/api/openapi.yaml`)
file_glob: 'docs/api/*.yaml'
1 change: 1 addition & 0 deletions .spectral.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
extends: ["spectral:oas"]
180 changes: 179 additions & 1 deletion docs/api/openapi.yaml
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
openapi: 3.0.3
# yaml-language-server: $schema=https://spec.openapis.org/oas/3.1/schema/2025-02-13
openapi: 3.1.1
info:
title: Lamp Control API
description: |
A simple API for controlling lamps, demonstrating CRUD operations.
version: 1.0.0
contact:
name: API Support
url: https://www.example.com/support

servers:
- url: /v1

tags:
- name: lamps
description: Operations related to lamps

paths:
/lamps:
get:
summary: List all lamps
description: Retrieve a list of all lamps.
tags: [lamps]
operationId: listLamps
parameters:
- in: query
Expand All @@ -37,6 +47,48 @@ paths:
nullable: true
hasMore:
type: boolean
examples:
lamps_list:
summary: List of lamps
description: Example response showing multiple lamps with pagination
value:
data:
- id: "046b6c7f-0b8a-43b9-b35d-6489e6daee91"
status: true
createdAt: "2024-01-15T09:30:00Z"
updatedAt: "2024-01-15T14:22:30Z"
- id: "7c9e2a5b-8f1d-4e3c-9b2a-1d5f8c7e4b6a"
status: false
createdAt: "2024-01-15T10:15:45Z"
updatedAt: "2024-01-15T10:15:45Z"
nextCursor: "eyJpZCI6IjdjOWUyYTViLThmMWQtNGUzYy05YjJhLTFkNWY4YzdlNGI2YSJ9"
hasMore: true
empty_list:
summary: Empty list of lamps
description: Example response when no lamps exist
value:
data: []
nextCursor: null
hasMore: false
links:
GetLampById:
operationId: getLamp
parameters:
lampId: '$response.body#/data/0/id'
description: >
The `id` value of any lamp in the list can be used as the `lampId` parameter in `GET /lamps/{lampId}`.
UpdateLamp:
operationId: updateLamp
parameters:
lampId: '$response.body#/data/0/id'
description: >
The `id` value of any lamp in the list can be used as the `lampId` parameter in `PUT /lamps/{lampId}`.
DeleteLamp:
operationId: deleteLamp
parameters:
lampId: '$response.body#/data/0/id'
description: >
The `id` value of any lamp in the list can be used as the `lampId` parameter in `DELETE /lamps/{lampId}`.
'304':
description: Not Modified
'400':
Expand All @@ -50,20 +102,69 @@ paths:
message: "Invalid query parameter 'pageSize'"
post:
summary: Create a new lamp
description: Create a new lamp.
tags: [lamps]
operationId: createLamp
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LampCreate'
examples:
Copy link

Copilot AI Aug 17, 2025

Choose a reason for hiding this comment

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

The examples are placed at the wrong level in the YAML structure. They should be nested under the media type (application/json) rather than at the requestBody level.

Copilot uses AI. Check for mistakes.
create_lamp_on:
summary: Create lamp that is turned on
description: Create a new lamp with status set to on/true
value:
status: true
create_lamp_off:
summary: Create lamp that is turned off
description: Create a new lamp with status set to off/false
value:
status: false
responses:
'201':
description: Lamp created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Lamp'
examples:
created_lamp_on:
summary: Created lamp turned on
description: Successfully created lamp with status on
value:
id: "046b6c7f-0b8a-43b9-b35d-6489e6daee91"
status: true
createdAt: "2024-01-15T09:30:00Z"
updatedAt: "2024-01-15T09:30:00Z"
created_lamp_off:
summary: Created lamp turned off
description: Successfully created lamp with status off
value:
id: "7c9e2a5b-8f1d-4e3c-9b2a-1d5f8c7e4b6a"
status: false
createdAt: "2024-01-15T10:15:45Z"
updatedAt: "2024-01-15T10:15:45Z"
links:
Copy link

Copilot AI Aug 17, 2025

Choose a reason for hiding this comment

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

The links section is incorrectly indented. It should be at the same level as the response content, not nested within the 201 response.

Copilot uses AI. Check for mistakes.
GetLampById:
operationId: getLamp
parameters:
lampId: '$response.body#/id'
description: >
The `id` value returned in the response can be used as the `lampId` parameter in `GET /lamps/{lampId}`.
UpdateLamp:
operationId: updateLamp
parameters:
lampId: '$response.body#/id'
description: >
The `id` value returned in the response can be used as the `lampId` parameter in `PUT /lamps/{lampId}`.
DeleteLamp:
operationId: deleteLamp
parameters:
lampId: '$response.body#/id'
description: >
The `id` value returned in the response can be used as the `lampId` parameter in `DELETE /lamps/{lampId}`.
'400':
description: Invalid request data
content:
Expand All @@ -78,6 +179,8 @@ paths:
/lamps/{lampId}:
get:
summary: Get a specific lamp
description: Retrieve a specific lamp.
tags: [lamps]
operationId: getLamp
parameters:
- name: lampId
Expand All @@ -92,6 +195,36 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Lamp'
examples:
lamp_on:
summary: Lamp that is turned on
description: Example of a lamp with status on/true
value:
id: "046b6c7f-0b8a-43b9-b35d-6489e6daee91"
status: true
createdAt: "2024-01-15T09:30:00Z"
updatedAt: "2024-01-15T14:22:30Z"
lamp_off:
summary: Lamp that is turned off
description: Example of a lamp with status off/false
value:
id: "7c9e2a5b-8f1d-4e3c-9b2a-1d5f8c7e4b6a"
status: false
createdAt: "2024-01-15T10:15:45Z"
updatedAt: "2024-01-15T10:15:45Z"
links:
UpdateLamp:
operationId: updateLamp
parameters:
lampId: '$response.body#/id'
description: >
The `id` value returned in the response can be used to update the lamp using `PUT /lamps/{lampId}`.
DeleteLamp:
operationId: deleteLamp
parameters:
lampId: '$response.body#/id'
description: >
The `id` value returned in the response can be used to delete the lamp using `DELETE /lamps/{lampId}`.
'304':
description: Not Modified
'400':
Expand All @@ -108,6 +241,8 @@ paths:
description: Lamp not found
put:
summary: Update a lamp's status
description: Update a lamp's status.
tags: [lamps]
operationId: updateLamp
parameters:
- name: lampId
Expand All @@ -121,13 +256,54 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/LampUpdate'
examples:
turn_on:
summary: Turn lamp on
description: Update lamp status to on/true
value:
status: true
turn_off:
summary: Turn lamp off
description: Update lamp status to off/false
value:
status: false
responses:
'200':
description: Lamp updated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Lamp'
examples:
updated_to_on:
summary: Lamp turned on
description: Lamp successfully updated to on status
value:
id: "046b6c7f-0b8a-43b9-b35d-6489e6daee91"
status: true
createdAt: "2024-01-15T09:30:00Z"
updatedAt: "2024-01-15T16:45:20Z"
updated_to_off:
summary: Lamp turned off
description: Lamp successfully updated to off status
value:
id: "046b6c7f-0b8a-43b9-b35d-6489e6daee91"
status: false
createdAt: "2024-01-15T09:30:00Z"
updatedAt: "2024-01-15T16:45:20Z"
links:
GetLampById:
operationId: getLamp
parameters:
lampId: '$response.body#/id'
description: >
The `id` value returned in the response can be used to get the updated lamp details using `GET /lamps/{lampId}`.
DeleteLamp:
operationId: deleteLamp
parameters:
lampId: '$response.body#/id'
description: >
The `id` value returned in the response can be used to delete the lamp using `DELETE /lamps/{lampId}`.
'400':
description: Invalid request data or lamp ID format
content:
Expand All @@ -142,6 +318,8 @@ paths:
description: Lamp not found
delete:
summary: Delete a lamp
description: Delete a lamp.
tags: [lamps]
operationId: deleteLamp
parameters:
- name: lampId
Expand Down
Loading