diff --git a/.github/workflows/poltergust.yaml b/.github/workflows/poltergust.yaml index 521a521..23c1f10 100644 --- a/.github/workflows/poltergust.yaml +++ b/.github/workflows/poltergust.yaml @@ -7,7 +7,7 @@ on: branches: [ main ] jobs: - test: + build-and-test-valid-example: runs-on: ubuntu-latest steps: @@ -20,5 +20,26 @@ jobs: - name: Install poltergust run: npm ci - - name: Run Poltergust tests - run: npx poltergust test ./example \ No newline at end of file + - name: Test the example ruleset + run: npx poltergust test ./example + + build-and-test-invalid-example: + needs: build-and-test-valid-example + runs-on: ubuntu-latest + + steps: + - name: Check out code + uses: actions/checkout@v2 + + - name: Use Node.js + uses: actions/setup-node@v2 + + - name: Install poltergust + run: npm ci + + - name: Test the example ruleset + run: npx poltergust test ./example + + - name: Test the invalid example ruleset (should exit 1) + run: npx poltergust test ./invalid-example || (exitcode=$?; [ $exitcode -eq 1 ] || exit $exitcode) + shell: bash \ No newline at end of file diff --git a/README.md b/README.md index 9627362..ef84764 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Run Poltergust Tests](https://github.com/ouvreboite/api-guidelines/actions/workflows/poltergust.yaml/badge.svg)](https://github.com/ouvreboite/api-guidelines/actions/workflows/poltergust.yaml) + # 👻 poltergust An npm CLI to extract Spectral rules from .md files, merge them and test them. diff --git a/example/parameters.md b/example/parameters.md index b007016..abb56d6 100644 --- a/example/parameters.md +++ b/example/parameters.md @@ -59,7 +59,7 @@ paths: /mouses/{mice-id}: get: parameters: - - name: mice-id #spectral-should-fail-here-❌: path-parameters-must-be-kebab-case + - name: mice-id #spectral-should-not-fail-here-✅: path-parameters-must-be-kebab-case in: path required: true schema: diff --git a/functions.mjs b/functions.mjs index b36b8b1..045170e 100644 --- a/functions.mjs +++ b/functions.mjs @@ -170,25 +170,28 @@ export function generateRuleFileContent(spectralRulesContents, rulesDir){ * @return {boolean} success */ export async function runTestCase(rule, testCase, rulesDir){ - //write rule file to temp dir - const tempDir = await mkdtemp(rule.name+"-test-"); - const tempRuleFilePath = path.join(tempDir, '.spectral.yaml'); - const functionsDirPath = path.join(rulesDir, 'functions'); - const tempFunctionsDirPath = path.join(tempDir, 'functions') - let ruleFile = generateRuleFileContent([rule.content], rulesDir); - fs.writeFileSync(tempRuleFilePath, ruleFile); - - //copy the functions folder into the temp dir - fs.mkdirSync(tempFunctionsDirPath); - fs.readdirSync(functionsDirPath).forEach(file => { - const sourceFile = path.join(functionsDirPath, file); - const destFile = path.join(tempFunctionsDirPath, file); - fs.copyFileSync(sourceFile, destFile); - }); - let ok = true; + //write rule file to temp dir + const tempDir = await mkdtemp(rule.name+"-test-"); try{ + const tempRuleFilePath = path.join(tempDir, '.spectral.yaml'); + let ruleFile = generateRuleFileContent([rule.content], rulesDir); + fs.writeFileSync(tempRuleFilePath, ruleFile); + + //if the function dir exists, copy the functions folder into the temp dir + const functionsDirPath = path.join(rulesDir, 'functions'); + if(fs.existsSync(functionsDirPath)){ + const tempFunctionsDirPath = path.join(tempDir, 'functions') + fs.mkdirSync(tempFunctionsDirPath); + + fs.readdirSync(functionsDirPath).forEach(file => { + const sourceFile = path.join(functionsDirPath, file); + const destFile = path.join(tempFunctionsDirPath, file); + fs.copyFileSync(sourceFile, destFile); + }); + } + //run test case against the rule const spectral = new Spectral(); spectral.setRuleset(await bundleAndLoadRuleset(path.resolve(tempRuleFilePath), { fs, fetch })); diff --git a/index.mjs b/index.mjs index 1e8d41b..ed793aa 100644 --- a/index.mjs +++ b/index.mjs @@ -43,8 +43,9 @@ if (args[0] === 'merge') { } for(let testCase of testCases){ - await runTestCase(rule, testCase, rulesDir); + const testCaseSuccess = await runTestCase(rule, testCase, rulesDir); + if(! testCaseSuccess) + process.exitCode = 1; } } - process.exit(1); } \ No newline at end of file diff --git a/invalid-example/invalid.md b/invalid-example/invalid.md new file mode 100644 index 0000000..ec630f8 --- /dev/null +++ b/invalid-example/invalid.md @@ -0,0 +1,35 @@ +# API rules + +1. [base-path-must-start-with-slash](#base-path-must-start-with-slash) + +## base-path-must-start-with-slash + +```yaml +#spectral-test +#spectral-should-not-fail-anywhere-✅: base-path-must-start-with-slash +openapi: 3.0.1 +info: + title: Test + version: 1.0.0 +servers: +- url: do-not-start-with-slash #in fact, it should fail here +``` + +
+ Spectral rule 🤖 + +```yaml +#spectral-rule +base-path-must-start-with-slash: + description: Base path must start with /. + message: "{{description}}. But was {{value}}." + given: $.servers[*] + severity: error + then: + field: url + function: pattern + functionOptions: + match: "^\/" +``` + +
\ No newline at end of file diff --git a/invalid-example/spectral.base.yaml b/invalid-example/spectral.base.yaml new file mode 100644 index 0000000..3dd9936 --- /dev/null +++ b/invalid-example/spectral.base.yaml @@ -0,0 +1,8 @@ +formats: ["oas3"] +extends: "spectral:oas" +aliases: + parameters: + - $.paths[*].parameters + - $.paths[*][*].parameters +#rules will be injected from the rules/*.md files +rules: \ No newline at end of file diff --git a/invalid-example/spectral.yaml b/invalid-example/spectral.yaml new file mode 100644 index 0000000..acb0f24 --- /dev/null +++ b/invalid-example/spectral.yaml @@ -0,0 +1,19 @@ +formats: ["oas3"] +extends: "spectral:oas" +aliases: + parameters: + - $.paths[*].parameters + - $.paths[*][*].parameters +#rules will be injected from the rules/*.md files +rules: + base-path-must-start-with-slash: + description: Base path must start with /. + message: "{{description}}. But was {{value}}." + given: $.servers[*] + severity: error + then: + field: url + function: pattern + functionOptions: + match: "^\/" + \ No newline at end of file