From ab184f421f3d369429a6590f9b2a4ba8981e5cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ro=C5=BCek?= Date: Thu, 8 Sep 2022 13:44:05 +0200 Subject: [PATCH 1/2] feat(cli): use Content-Type header to detect ruleset format --- .../cli/src/services/__tests__/linter.test.ts | 41 ++++++++++++++++++- .../src/services/linter/utils/getRuleset.ts | 34 ++++++++++++--- 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/services/__tests__/linter.test.ts b/packages/cli/src/services/__tests__/linter.test.ts index 97f175072..e17a1b77e 100644 --- a/packages/cli/src/services/__tests__/linter.test.ts +++ b/packages/cli/src/services/__tests__/linter.test.ts @@ -313,7 +313,7 @@ describe('Linter service', () => { .persist() .get('/ruleset.json') .replyWithFile(200, join(__dirname, '__fixtures__/ruleset.json'), { - 'Content-Type': 'application/yaml', + 'Content-Type': 'application/json', }); const output = await run(`lint ${validOas3SpecPath} -r http://foo.local/ruleset.json`); @@ -326,6 +326,45 @@ describe('Linter service', () => { ]), ); }); + + it('fallbacks to Content-Type', async () => { + nock('http://foo.local') + .persist() + .get('/ruleset') + .replyWithFile(200, join(__dirname, '__fixtures__/ruleset.json'), { + 'Content-Type': 'application/json', + }); + + const output = await run(`lint ${validOas3SpecPath} -r http://foo.local/ruleset`); + expect(output).toEqual(expect.arrayContaining([expect.objectContaining({ code: 'info-matches-stoplight' })])); + expect(output).toEqual( + expect.not.arrayContaining([ + expect.objectContaining({ + message: 'Info object should contain `contact` object', + }), + ]), + ); + }); + + it('ignores query parameters', async () => { + nock('http://foo.local') + .persist() + .get('/ruleset.json') + .query({ token: 'bar' }) + .replyWithFile(200, join(__dirname, '__fixtures__/ruleset.json'), { + 'Content-Type': 'text/plain', // GitHub raw like + }); + + const output = await run(`lint ${validOas3SpecPath} -r http://foo.local/ruleset.json?token=bar`); + expect(output).toEqual(expect.arrayContaining([expect.objectContaining({ code: 'info-matches-stoplight' })])); + expect(output).toEqual( + expect.not.arrayContaining([ + expect.objectContaining({ + message: 'Info object should contain `contact` object', + }), + ]), + ); + }); }); }); diff --git a/packages/cli/src/services/linter/utils/getRuleset.ts b/packages/cli/src/services/linter/utils/getRuleset.ts index f2af0b7c9..31af3a5b5 100644 --- a/packages/cli/src/services/linter/utils/getRuleset.ts +++ b/packages/cli/src/services/linter/utils/getRuleset.ts @@ -25,10 +25,6 @@ async function getDefaultRulesetFile(): Promise> { return; } -function isBasicRuleset(filepath: string): boolean { - return /\.(json|ya?ml)$/.test(path.extname(filepath)); -} - function isErrorWithCode(error: Error | (Error & { code: unknown })): error is Error & { code: string } { return 'code' in error && typeof error.code === 'string'; } @@ -49,7 +45,7 @@ export async function getRuleset(rulesetFile: Optional): Promise { + if (path.isURL(uri)) { + uri = stripSearchFromUrl(uri); + } + + if (/\.(json|ya?ml)$/.test(path.extname(uri))) { + return true; + } + + try { + const contentType = (await fetch(uri)).headers.get('Content-Type'); + return ( + contentType !== null && ['application/yaml', 'text/yaml', 'application/json', 'text/json'].includes(contentType) + ); + } catch { + return false; + } +} From 748643ed5fba5978451b89ac8a43ac50901034bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ro=C5=BCek?= Date: Mon, 24 Oct 2022 22:25:29 +0200 Subject: [PATCH 2/2] feat(cli): use ruleset-migrator#isBasicRuleset --- packages/cli/package.json | 2 +- .../src/services/linter/utils/getRuleset.ts | 30 +------------------ yarn.lock | 4 +-- 3 files changed, 4 insertions(+), 32 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index e4a440398..9c5046b64 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -40,7 +40,7 @@ "@stoplight/spectral-parsers": "^1.0.1", "@stoplight/spectral-ref-resolver": "1.0.2", "@stoplight/spectral-ruleset-bundler": "^1.0.0", - "@stoplight/spectral-ruleset-migrator": "^1.5.0", + "@stoplight/spectral-ruleset-migrator": "^1.9.0", "@stoplight/spectral-rulesets": ">=1", "@stoplight/spectral-runtime": "^1.1.0", "@stoplight/types": "12.3.0", diff --git a/packages/cli/src/services/linter/utils/getRuleset.ts b/packages/cli/src/services/linter/utils/getRuleset.ts index 31af3a5b5..8bf4571a1 100644 --- a/packages/cli/src/services/linter/utils/getRuleset.ts +++ b/packages/cli/src/services/linter/utils/getRuleset.ts @@ -5,7 +5,7 @@ import * as path from '@stoplight/path'; import * as process from 'process'; import { createRequire } from 'module'; import { fetch } from '@stoplight/spectral-runtime'; -import { migrateRuleset } from '@stoplight/spectral-ruleset-migrator'; +import { migrateRuleset, isBasicRuleset } from '@stoplight/spectral-ruleset-migrator'; import { bundleRuleset } from '@stoplight/spectral-ruleset-bundler'; import { node } from '@stoplight/spectral-ruleset-bundler/presets/node'; import { stdin } from '@stoplight/spectral-ruleset-bundler/plugins/stdin'; @@ -100,31 +100,3 @@ function load(source: string, uri: string): RulesetDefinition { return m.exports; } - -function stripSearchFromUrl(url: string): string { - try { - const { href, search } = new URL(url); - return href.slice(0, href.length - search.length); - } catch { - return url; - } -} - -async function isBasicRuleset(uri: string): Promise { - if (path.isURL(uri)) { - uri = stripSearchFromUrl(uri); - } - - if (/\.(json|ya?ml)$/.test(path.extname(uri))) { - return true; - } - - try { - const contentType = (await fetch(uri)).headers.get('Content-Type'); - return ( - contentType !== null && ['application/yaml', 'text/yaml', 'application/json', 'text/json'].includes(contentType) - ); - } catch { - return false; - } -} diff --git a/yarn.lock b/yarn.lock index fd456c0d5..90c177b4d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2514,7 +2514,7 @@ __metadata: "@stoplight/spectral-parsers": ^1.0.1 "@stoplight/spectral-ref-resolver": 1.0.2 "@stoplight/spectral-ruleset-bundler": ^1.0.0 - "@stoplight/spectral-ruleset-migrator": ^1.5.0 + "@stoplight/spectral-ruleset-migrator": ^1.9.0 "@stoplight/spectral-rulesets": ">=1" "@stoplight/spectral-runtime": ^1.1.0 "@stoplight/types": 12.3.0 @@ -2660,7 +2660,7 @@ __metadata: languageName: unknown linkType: soft -"@stoplight/spectral-ruleset-migrator@^1.5.0, @stoplight/spectral-ruleset-migrator@^1.7.4, @stoplight/spectral-ruleset-migrator@workspace:packages/ruleset-migrator": +"@stoplight/spectral-ruleset-migrator@^1.7.4, @stoplight/spectral-ruleset-migrator@^1.9.0, @stoplight/spectral-ruleset-migrator@workspace:packages/ruleset-migrator": version: 0.0.0-use.local resolution: "@stoplight/spectral-ruleset-migrator@workspace:packages/ruleset-migrator" dependencies: