diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index f6e0a30..f042a82 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -78,7 +78,10 @@ jobs: run: | export PATH=/root/.local/bin:$PATH sudo apt install -y nodejs npm - sudo npm install -g @stoplight/spectral-cli@6.14.2 + sudo npm install -g \ + @stoplight/spectral-cli@6.14.2 \ + @stoplight/spectral-rulesets@1.22.2 + test "$(node -p "require('/usr/local/lib/node_modules/@stoplight/spectral-rulesets/package.json').version")" = "1.22.2" cd microservices/csitOasValidationApi poetry env use python3.14 poetry install --no-root diff --git a/microservices/csitOasValidationApi/Dockerfile b/microservices/csitOasValidationApi/Dockerfile index 4055042..0d3fe32 100644 --- a/microservices/csitOasValidationApi/Dockerfile +++ b/microservices/csitOasValidationApi/Dockerfile @@ -8,8 +8,16 @@ RUN apk add --no-cache build-base libffi-dev openssl curl git bash nodejs npm RUN python -m pip install --upgrade pip -# Install Spectral CLI (required for validation) -RUN npm install -g @stoplight/spectral-cli@6.14.2 +# Install Spectral CLI (required for validation). Pin the rulesets package +# separately because spectral-cli declares it as ">=1" and newer transitive +# releases can change validation behaviour without changing the CLI version. +ARG SPECTRAL_CLI_VERSION=6.14.2 +ARG SPECTRAL_RULESETS_VERSION=1.22.2 +RUN npm install -g \ + "@stoplight/spectral-cli@${SPECTRAL_CLI_VERSION}" \ + "@stoplight/spectral-rulesets@${SPECTRAL_RULESETS_VERSION}" && \ + test "$(node -p "require('/usr/local/lib/node_modules/@stoplight/spectral-rulesets/package.json').version")" = \ + "${SPECTRAL_RULESETS_VERSION}" # Install Poetry RUN cd /tmp && \ diff --git a/microservices/csitOasValidationApi/README.md b/microservices/csitOasValidationApi/README.md index 06b3ded..c281ecb 100644 --- a/microservices/csitOasValidationApi/README.md +++ b/microservices/csitOasValidationApi/README.md @@ -75,7 +75,9 @@ sudo apt install nodejs npm Install Stoplight Spectral Requires 6.0.0 or greater ```bash -sudo npm install -g @stoplight/spectral-cli@6.14.2 +sudo npm install -g \ + @stoplight/spectral-cli@6.14.2 \ + @stoplight/spectral-rulesets@1.22.2 spectral --version ``` @@ -153,4 +155,4 @@ curl -X POST http://localhost:8080/versions/v0.1.0-test/rulesets/basic-ruleset/v } }' \ | jq . -``` \ No newline at end of file +``` diff --git a/microservices/csitOasValidationApi/tests/unit/test_spectral_runtime.py b/microservices/csitOasValidationApi/tests/unit/test_spectral_runtime.py new file mode 100644 index 0000000..6d415ac --- /dev/null +++ b/microservices/csitOasValidationApi/tests/unit/test_spectral_runtime.py @@ -0,0 +1,48 @@ +"""Regression tests for the external Spectral runtime.""" + +import subprocess +import textwrap +from pathlib import Path + + +def test_null_example_does_not_crash_spectral(): + """duplicated-entry-in-enum must not dereference enum on null nodes.""" + + ruleset = ( + Path(__file__).parent + / "resources" + / "github-cache" + / "tags" + / "ruleset-v1.1.0" + / "spectral" + / "sdx" + / "ruleset.yaml" + ) + openapi_content = textwrap.dedent("""\ + openapi: 3.0.3 + info: + title: Nullable example regression + version: 1.0.0 + paths: + /widgets: + get: + operationId: listWidgets + responses: + '200': + description: Widget list + content: + application/json: + example: + nextCursor: null + """) + + result = subprocess.run( + ["spectral", "lint", "--ruleset", str(ruleset), "-"], + input=openapi_content, + capture_output=True, + text=True, + timeout=30, + check=False, + ) + + assert result.returncode != 2, result.stderr