From 97361e9f5be867d35862a0e0d3b73f08d69fe5ba Mon Sep 17 00:00:00 2001 From: bkioshn <35752733+bkioshn@users.noreply.github.com> Date: Tue, 29 Oct 2024 15:32:15 +0700 Subject: [PATCH] fix: spectral linter (#340) * fix: remove minify json Signed-off-by: bkioshn * fix: replace tab with space Signed-off-by: bkioshn * fix: update spectral linter Signed-off-by: bkioshn * fix: update spectral linter Signed-off-by: bkioshn * fix: move openapi linter Signed-off-by: bkioshn --------- Signed-off-by: bkioshn Co-authored-by: Steven Johnson --- Earthfile | 6 +- earthly/spectral/Earthfile | 27 +- earthly/spectral/minify-json.sh | 22 - .../openapi/.spectral.yml | 0 examples/openapi/Earthfile | 8 + examples/openapi/example.json | 634 +++++++++--------- 6 files changed, 333 insertions(+), 364 deletions(-) delete mode 100644 earthly/spectral/minify-json.sh rename .spectral.yml => examples/openapi/.spectral.yml (100%) create mode 100644 examples/openapi/Earthfile diff --git a/Earthfile b/Earthfile index 45acb573b..5c342f333 100644 --- a/Earthfile +++ b/Earthfile @@ -57,8 +57,4 @@ edit-docs: LOCALLY RUN ./earthly/docs/dev/local.py cat-ci-docs:latest - -# check-lint-openapi - OpenAPI linting from a given directory -check-lint-openapi: - FROM spectral-ci+spectral-base - DO spectral-ci+BUILD_SPECTRAL --dir="./examples/openapi" --file_type="json" \ No newline at end of file + \ No newline at end of file diff --git a/earthly/spectral/Earthfile b/earthly/spectral/Earthfile index 168468658..ed1a90f37 100644 --- a/earthly/spectral/Earthfile +++ b/earthly/spectral/Earthfile @@ -3,29 +3,20 @@ VERSION 0.8 # cspell: words ruleset spectral-base: - FROM stoplight/spectral + FROM stoplight/spectral:6.13.1 WORKDIR /work - COPY . . - RUN chmod +x ./minify-json.sh - SAVE ARTIFACT minify-json.sh -BUILD_SPECTRAL: +LINT: FUNCTION - - # Specify what file type to lint - ARG file_type = "json" + + # FIle type to be linted, default linting only JSON files + ARG file_type = json + # Directory to lint ARG dir = . - ARG src = . # Rule set for spectral - ARG rule_set=.spectral.yml - - COPY $src . - - COPY +spectral-base/minify-json.sh minify-json.sh - # If file type is json, minify the JSON - RUN ./minify-json.sh + ARG rule_set = .spectral.yml RUN spectral \ lint \ - $dir/"**/*.{yml,json}" \ - --ruleset $rule_set \ No newline at end of file + $dir/"**/*.$file_type" \ + --ruleset $rule_set diff --git a/earthly/spectral/minify-json.sh b/earthly/spectral/minify-json.sh deleted file mode 100644 index 7b2515334..000000000 --- a/earthly/spectral/minify-json.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -# Minify all JSON in the directory if the file type is json -# Check if FILE_TYPE and DIR are not empty -if [[ -n "${file_type}" ]] && [[ -n "${dir}" ]]; then - # Minify all JSON in the directory if the file type is json - if [[ "${file_type}" == "json" ]]; then - # Loop through each JSON file in the directory - for json_file in "${dir}"/*.json; do - # Check if the file is a regular file - if [[ -f "${json_file}" ]]; then - # Minify the JSON file using jq and overwrite the original file - jq -c . "${json_file}" > "${json_file}.tmp" && mv "${json_file}.tmp" "${json_file}" - echo "Compacted: ${json_file}" - fi - done - else - echo "File type is not JSON." - fi -else - echo "FILE_TYPE or DIR is empty." -fi diff --git a/.spectral.yml b/examples/openapi/.spectral.yml similarity index 100% rename from .spectral.yml rename to examples/openapi/.spectral.yml diff --git a/examples/openapi/Earthfile b/examples/openapi/Earthfile new file mode 100644 index 000000000..39b63750b --- /dev/null +++ b/examples/openapi/Earthfile @@ -0,0 +1,8 @@ +VERSION 0.8 +IMPORT ../../earthly/spectral AS spectral-ci + +# check-lint-openapi - OpenAPI linting from a given directory +check-lint-openapi: + FROM spectral-ci+spectral-base + COPY . . + DO spectral-ci+LINT --dir=. --rule_set=.spectral.yml diff --git a/examples/openapi/example.json b/examples/openapi/example.json index 6c83323fd..d7fd27a8c 100644 --- a/examples/openapi/example.json +++ b/examples/openapi/example.json @@ -1,321 +1,317 @@ { - "openapi": "3.0.2", - "info": { - "title": "Example API", - "description": "This OpenAPI specification defines an example API with various endpoints for managing user data. It provides detailed information about the API, including contact information and version details.", - "version": "1.0", - "contact": { - "name": "Catalyst-ci", - "url": "https://www.example.com/support", - "email": "support@example.com" - } - }, - "servers": [ - { - "url": "https://api.example.com", - "description": "The primary server for this API, hosted at https://api.example.com. It serves as the main entry point for accessing the provided endpoints." - } - ], - "tags": [ - { - "name": "user", - "description": "Endpoints related to user management, including retrieving user lists and creating new users." - } - ], - "paths": { - "/users": { - "get": { - "tags": ["user"], - "operationId": "getUsers", - "summary": "Get a list of users", - "description": "Retrieves a list of users from the system.", - "responses": { - "200": { - "description": "Successfully retrieved user data. The response includes a list of users with pagination support.", - "headers": { - "RateLimit-Limit": { - "$ref": "#/components/headers/RateLimit-Limit" - }, - "RateLimit-Reset": { - "$ref": "#/components/headers/RateLimit-Reset" - } - }, - "content": { - "application/json": { - "schema": { - "type": "array", - "maxItems": 1000, - "items": { - "$ref": "#/components/schemas/User" - } - } - } - } - }, - "400": { - "description": "Invalid request. Check the request payload.", - "headers": { - "RateLimit-Limit": { - "$ref": "#/components/headers/RateLimit-Limit" - }, - "RateLimit-Reset": { - "$ref": "#/components/headers/RateLimit-Reset" - } - }, - "content": { - "application/json": { - "example": { - "message": "Invalid request payload" - } - } - } - }, - "401": { - "description": "Unauthorized. The request requires user authentication.", - "headers": { - "RateLimit-Limit": { - "$ref": "#/components/headers/RateLimit-Limit" - }, - "RateLimit-Reset": { - "$ref": "#/components/headers/RateLimit-Reset" - } - }, - "content": { - "application/json": { - "example": { - "message": "Invalid request payload" - } - } - } - }, - "429": { - "description": "Rate limit exceeded. Too many requests within a specific time frame.", - "headers": { - "RateLimit-Limit": { - "$ref": "#/components/headers/RateLimit-Limit" - }, - "RateLimit-Reset": { - "$ref": "#/components/headers/RateLimit-Reset" - }, - "Retry-After": { - "$ref": "#/components/headers/Retry-After" - } - }, - "content": { - "application/json": { - "example": { - "message": "Invalid request payload" - } - } - } - }, - "500": { - "description": "Internal server error. Contact system administrator if the issue persists.", - "headers": { - "RateLimit-Limit": { - "$ref": "#/components/headers/RateLimit-Limit" - }, - "RateLimit-Reset": { - "$ref": "#/components/headers/RateLimit-Reset" - } - }, - "content": { - "application/json": { - "example": { - "message": "Invalid request payload" - } - } - } - } - } - }, - "post": { - "tags": ["user"], - "operationId": "createUser", - "summary": "Create a new user", - "description": "Creates a new user with the provided information. Requires valid user data in the request payload.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/User" - } - } - } - }, - "responses": { - "200": { - "description": "User created successfully. Returns the created user details.", - "headers": { - "RateLimit-Limit": { - "$ref": "#/components/headers/RateLimit-Limit" - }, - "RateLimit-Reset": { - "$ref": "#/components/headers/RateLimit-Reset" - } - }, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/User" - } - } - } - }, - "400": { - "description": "Invalid request. Check the request payload.", - "headers": { - "RateLimit-Limit": { - "$ref": "#/components/headers/RateLimit-Limit" - }, - "RateLimit-Reset": { - "$ref": "#/components/headers/RateLimit-Reset" - } - }, - "content": { - "application/json": { - "example": { - "message": "Invalid request payload" - } - } - } - }, - "401": { - "description": "Unauthorized. The request requires user authentication.", - "headers": { - "RateLimit-Limit": { - "$ref": "#/components/headers/RateLimit-Limit" - }, - "RateLimit-Reset": { - "$ref": "#/components/headers/RateLimit-Reset" - } - }, - "content": { - "application/json": { - "example": { - "message": "Invalid request payload" - } - } - } - }, - "429": { - "description": "Rate limit exceeded. Too many requests within a specific time frame.", - "headers": { - "RateLimit-Limit": { - "$ref": "#/components/headers/RateLimit-Limit" - }, - "RateLimit-Reset": { - "$ref": "#/components/headers/RateLimit-Reset" - }, - "Retry-After": { - "$ref": "#/components/headers/Retry-After" - } - }, - "content": { - "application/json": { - "example": { - "message": "Invalid request payload" - } - } - } - }, - "500": { - "description": "Internal server error. Contact system administrator if the issue persists.", - "headers": { - "RateLimit-Limit": { - "$ref": "#/components/headers/RateLimit-Limit" - }, - "RateLimit-Reset": { - "$ref": "#/components/headers/RateLimit-Reset" - } - }, - "content": { - "application/json": { - "example": { - "message": "Invalid request payload" - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "User": { - "description": "Represents a user in the system with details such as user ID, username, password, email, and roles.", - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64", - "minimum": 0, - "maximum": 10000000 - }, - "username": { - "type": "string", - "format": "text", - "maxLength": 10 - }, - "password": { - "type": "string", - "format": "password", - "minLength": 8, - "maxLength": 50 - }, - "email": { - "type": "string", - "format": "email", - "maxLength": 20 - }, - "roles": { - "type": "string", - "enum": ["user", "admin"] - } - } - } - }, - "securitySchemes": { - "apiKey": { - "type": "apiKey", - "in": "header", - "name": "X-API-Key" - } - }, - "headers": { - "RateLimit-Limit": { - "description": "Maximum number of requests allowed within a specific time frame.", - "schema": { - "type": "integer", - "format": "int32", - "minimum": 1, - "maximum": 1000 - } - }, - "RateLimit-Reset": { - "description": "Time in seconds until the rate limit resets.", - "schema": { - "type": "integer", - "format": "int32", - "minimum": 1, - "maximum": 1000 - } - }, - "Retry-After": { - "description": "Time in seconds the client should wait before making another request.", - "schema": { - "type": "integer", - "format": "int32", - "minimum": 1, - "maximum": 1000 - } - } - } - }, - "security": [ - { - "apiKey": ["your-api-key"] - } - ] + "openapi": "3.0.2", + "info": { + "title": "Example API", + "description": "This OpenAPI specification defines an example API with various endpoints for managing user data. It provides detailed information about the API, including contact information and version details.", + "version": "1.0", + "contact": { + "name": "Catalyst-ci", + "url": "https://www.example.com/support", + "email": "support@example.com" + } + }, + "servers": [ + { + "url": "https://api.example.com", + "description": "The primary server for this API, hosted at https://api.example.com. It serves as the main entry point for accessing the provided endpoints." + } + ], + "tags": [ + { + "name": "user", + "description": "Endpoints related to user management, including retrieving user lists and creating new users." + } + ], + "paths": { + "/users": { + "get": { + "tags": ["user"], + "operationId": "getUsers", + "summary": "Get a list of users", + "description": "Retrieves a list of users from the system.", + "responses": { + "200": { + "description": "Successfully retrieved user data. The response includes a list of users with pagination support.", + "headers": { + "RateLimit-Limit": { + "$ref": "#/components/headers/RateLimit-Limit" + }, + "RateLimit-Reset": { + "$ref": "#/components/headers/RateLimit-Reset" + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "maxItems": 1000, + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + }, + "400": { + "description": "Invalid request. Check the request payload.", + "headers": { + "RateLimit-Limit": { + "$ref": "#/components/headers/RateLimit-Limit" + }, + "RateLimit-Reset": { + "$ref": "#/components/headers/RateLimit-Reset" + } + }, + "content": { + "application/json": { + "example": { + "message": "Invalid request payload" + } + } + } + }, + "401": { + "description": "Unauthorized. The request requires user authentication.", + "headers": { + "RateLimit-Limit": { + "$ref": "#/components/headers/RateLimit-Limit" + }, + "RateLimit-Reset": { + "$ref": "#/components/headers/RateLimit-Reset" + } + }, + "content": { + + } + }, + "429": { + "description": "Rate limit exceeded. Too many requests within a specific time frame.", + "headers": { + "RateLimit-Limit": { + "$ref": "#/components/headers/RateLimit-Limit" + }, + "RateLimit-Reset": { + "$ref": "#/components/headers/RateLimit-Reset" + }, + "Retry-After": { + "$ref": "#/components/headers/Retry-After" + } + }, + "content": { + "application/json": { + "example": { + "message": "Invalid request payload" + } + } + } + }, + "500": { + "description": "Internal server error. Contact system administrator if the issue persists.", + "headers": { + "RateLimit-Limit": { + "$ref": "#/components/headers/RateLimit-Limit" + }, + "RateLimit-Reset": { + "$ref": "#/components/headers/RateLimit-Reset" + } + }, + "content": { + "application/json": { + "example": { + "message": "Invalid request payload" + } + } + } + } + } + }, + "post": { + "tags": ["user"], + "operationId": "createUser", + "summary": "Create a new user", + "description": "Creates a new user with the provided information. Requires valid user data in the request payload.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "responses": { + "200": { + "description": "User created successfully. Returns the created user details.", + "headers": { + "RateLimit-Limit": { + "$ref": "#/components/headers/RateLimit-Limit" + }, + "RateLimit-Reset": { + "$ref": "#/components/headers/RateLimit-Reset" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "400": { + "description": "Invalid request. Check the request payload.", + "headers": { + "RateLimit-Limit": { + "$ref": "#/components/headers/RateLimit-Limit" + }, + "RateLimit-Reset": { + "$ref": "#/components/headers/RateLimit-Reset" + } + }, + "content": { + "application/json": { + "example": { + "message": "Invalid request payload" + } + } + } + }, + "401": { + "description": "Unauthorized. The request requires user authentication.", + "headers": { + "RateLimit-Limit": { + "$ref": "#/components/headers/RateLimit-Limit" + }, + "RateLimit-Reset": { + "$ref": "#/components/headers/RateLimit-Reset" + } + }, + "content": { + "application/json": { + "example": { + "message": "Invalid request payload" + } + } + } + }, + "429": { + "description": "Rate limit exceeded. Too many requests within a specific time frame.", + "headers": { + "RateLimit-Limit": { + "$ref": "#/components/headers/RateLimit-Limit" + }, + "RateLimit-Reset": { + "$ref": "#/components/headers/RateLimit-Reset" + }, + "Retry-After": { + "$ref": "#/components/headers/Retry-After" + } + }, + "content": { + "application/json": { + "example": { + "message": "Invalid request payload" + } + } + } + }, + "500": { + "description": "Internal server error. Contact system administrator if the issue persists.", + "headers": { + "RateLimit-Limit": { + "$ref": "#/components/headers/RateLimit-Limit" + }, + "RateLimit-Reset": { + "$ref": "#/components/headers/RateLimit-Reset" + } + }, + "content": { + "application/json": { + "example": { + "message": "Invalid request payload" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "User": { + "description": "Represents a user in the system with details such as user ID, username, password, email, and roles.", + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "minimum": 0, + "maximum": 10000000 + }, + "username": { + "type": "string", + "format": "text", + "maxLength": 10 + }, + "password": { + "type": "string", + "format": "password", + "minLength": 8, + "maxLength": 50 + }, + "email": { + "type": "string", + "format": "email", + "maxLength": 20 + }, + "roles": { + "type": "string", + "enum": ["user", "admin"] + } + } + } + }, + "securitySchemes": { + "apiKey": { + "type": "apiKey", + "in": "header", + "name": "X-API-Key" + } + }, + "headers": { + "RateLimit-Limit": { + "description": "Maximum number of requests allowed within a specific time frame.", + "schema": { + "type": "integer", + "format": "int32", + "minimum": 1, + "maximum": 1000 + } + }, + "RateLimit-Reset": { + "description": "Time in seconds until the rate limit resets.", + "schema": { + "type": "integer", + "format": "int32", + "minimum": 1, + "maximum": 1000 + } + }, + "Retry-After": { + "description": "Time in seconds the client should wait before making another request.", + "schema": { + "type": "integer", + "format": "int32", + "minimum": 1, + "maximum": 1000 + } + } + } + }, + "security": [ + { + "apiKey": ["your-api-key"] + } + ] }