From 979c6665dc8a4be0e486bb379353453902f55379 Mon Sep 17 00:00:00 2001 From: ouvreboite Date: Fri, 14 Jun 2024 15:31:03 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20Add=20a=20"simple"=20example?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/poltergust.yaml | 15 ++-- README.md | 88 ++++++++++++++++--- examples/complex/README.md | 36 ++++++++ .../functions/isRequiredPropertyDefined.js | 0 examples/{valid => complex}/rules1.md | 0 examples/{valid => complex}/rules2.md | 0 .../{valid => complex}/spectral.base.yaml | 4 +- examples/{valid => complex}/spectral.yaml | 2 +- .../subdirectory/subrules.md | 0 examples/invalid/spectral.base.yaml | 4 +- examples/simple/README.md | 30 +++++++ examples/simple/spectral.base.yaml | 3 + examples/simple/spectral.yaml | 11 +++ examples/valid/README.md | 31 ------- 14 files changed, 171 insertions(+), 53 deletions(-) create mode 100644 examples/complex/README.md rename examples/{valid => complex}/functions/isRequiredPropertyDefined.js (100%) rename examples/{valid => complex}/rules1.md (100%) rename examples/{valid => complex}/rules2.md (100%) rename examples/{valid => complex}/spectral.base.yaml (74%) rename examples/{valid => complex}/spectral.yaml (97%) rename examples/{valid => complex}/subdirectory/subrules.md (100%) create mode 100644 examples/simple/README.md create mode 100644 examples/simple/spectral.base.yaml create mode 100644 examples/simple/spectral.yaml delete mode 100644 examples/valid/README.md diff --git a/.github/workflows/poltergust.yaml b/.github/workflows/poltergust.yaml index 84f5e98..1e04450 100644 --- a/.github/workflows/poltergust.yaml +++ b/.github/workflows/poltergust.yaml @@ -7,7 +7,7 @@ on: branches: [ main ] jobs: - build-and-test-valid-example: + build-and-test-valid-examples: permissions: contents: write runs-on: ubuntu-latest @@ -22,10 +22,13 @@ jobs: - name: Install poltergust run: npm ci - - name: Test the valid example ruleset - run: npx poltergust ./examples/valid + - name: Run the simple example + run: npx poltergust ./examples/simple - - name: Commit updated valid ruleset + - name: Run the complex example + run: npx poltergust ./examples/complex + + - name: Commit aggregated rulesets run: | git config --global user.name 'πŸ‘»poltergust' git config --global user.email 'poltergust@bot.github.com' @@ -34,7 +37,7 @@ jobs: build-and-test-invalid-example: - needs: build-and-test-valid-example + needs: build-and-test-valid-examples runs-on: ubuntu-latest steps: @@ -47,6 +50,6 @@ jobs: - name: Install poltergust run: npm ci - - name: Test the invalid example ruleset (should exit 1) + - name: Run the invalid example (should exit 1) run: npx poltergust ./examples/invalid || (exitcode=$?; [ $exitcode -eq 1 ] || exit $exitcode) shell: bash \ No newline at end of file diff --git a/README.md b/README.md index e9a43ef..498eda2 100644 --- a/README.md +++ b/README.md @@ -2,22 +2,88 @@ # πŸ‘» poltergust -An npm CLI to extract, test and merge Spectral rules from .md files. +> With poltergust, you can document, define and test your [Spectral](https://github.com/stoplightio/spectral) rules in a single place. -- **Rules**: A YAML codeblock starting by `#πŸ‘»-rule` is considered a spectral rule and will be aggregated in the spectral.yaml file -- **Test cases**: A YAML codeblock containing `#πŸ‘»-failures:` or `#πŸ‘»-fails-here:` is considered an OpenAPI test case - - `#πŸ‘»-failures: X some-rule-name` expects the given rule to return only X failures for this test case. For example `#πŸ‘»-failures: 0 some-rule-name` can be used to assert that a test case does not trigger a rule. - - `#πŸ‘»-fails-here: some-rule-name` expects the given rule to be trigger at this very line -- **Base ruleset**: to merge the rules, a `spectral.base.yaml` is needed. It should be a standard Spectral ruleset files, with empty rules. But it can includes extends, aliases, functions... +Poltergust is a npm CLI that looks for .md files in a directory (and sub-directories) and extract Spectral rules and test cases. +- **Rules**: any YAML codeblock starting by `#πŸ‘»-rule` is considered a spectral rule and will be aggregated in the spectral.yaml file +- **Test cases**: any YAML codeblock containing `#πŸ‘»-failures:` or `#πŸ‘»-fails-here:` is considered an OpenAPI test case + - `#πŸ‘»-failures: X some-rule-name` expects the given rule to return exactly X failures against the OpenAPI document. + - `#πŸ‘»-failures: 0 some-rule-name` expects the given rule to not fail the OpenAPI document. + - `#πŸ‘»-fails-here: some-rule-name` expects the given rule to fail at a specific line of the OpenAPI document. +- **Base ruleset**: to merge the rules, a `spectral.base.yaml` file is needed. It's a standard Spectral ruleset files (with aliases, funcitons, extends, ...), with empty rules (they will be added by poltergust). -## Setup and run +## How to run ```sh npm install -npx poltergust ./examples/valid +npx poltergust ./your-rules-directory ``` -## Examples +## Simple example -- [valid](examples/valid) -- [invalid](examples/invalid) \ No newline at end of file +(from [simple](examples/simple)) + +1. This is a Spectral rule: + +```yaml +#πŸ‘»-rule +operation-parameters-must-have-description: + description: Operation parameters must have a description + given: $.paths[*][*].parameters[*] + severity: error + then: + field: description + function: truthy +``` + +2. This is a test case for this rule: +```yaml +#πŸ‘»-failures: 1 operation-parameters-must-have-description +openapi: 3.0.1 +paths: + /test/{id}: + get: + parameters: + # the 'id' parameter needs a description + - name: id #πŸ‘»-fails-here: operation-parameters-must-have-description + in: path + required: true + schema: + type: string +``` + +3. The spectral.base.yaml is: +```yaml +formats: ["oas3"] +rules: +#rules will be injected by poltergust +``` + +4. Running poltegust: +```bash +npx poltergust .\examples\simple +πŸ”Ž Testing the spectral rules from the .md files in the directory: .\examples\simple +πŸ‘» operation-parameters-must-have-description (examples\simple\README.md:6) + βœ… Test OK (examples\simple\README.md:18) +βœ… Spectral rules merged in the file: examples\simple\spectral.yaml +``` + +4. The aggregated Spectral ruleset can be found [here](examples/simple/spectral.yaml) + +```yaml +formats: ["oas3"] +rules: +#rules will be injected by poltergust + operation-parameters-must-have-description: + description: Operation parameters must have a description + given: $.paths[*][*].parameters[*] + severity: error + then: + field: description + function: truthy +``` + +## More examples + +- [complex](examples/complex): subdirectories, functions, ... +- [invalid](examples/invalid): a test case that fails diff --git a/examples/complex/README.md b/examples/complex/README.md new file mode 100644 index 0000000..35911e1 --- /dev/null +++ b/examples/complex/README.md @@ -0,0 +1,36 @@ +# Complex example + +* This example contains rules accross several markdown files: [rules1.md](rules1.md) and [rules2.md](rules2.md) and even subdirectories [subdirectory/subrules.md](subdirectory/subrules.md) + * βœ… All the test declared in those files are expected to pass +* Some of the rules use custom functions defined in the [functions](functions) directory +* [spectral.base.yaml](spectral.base.yaml) contains the base rule files that will be used to merge the rules into. For example, it contains the extends, aliases and functions declarations +* [spectral.yaml](spectral.yaml) is the output of the merge operation: [spectral.base.yaml](spectral.base.yaml) + all the rules found in [rules1.md](rules1.md) and [rules2.md](rules2.md) + +## Test ouput + +``` +npx poltergust .\examples\simple +πŸ”Ž Testing the spectral rules from the .md files in the directory: .\examples\simple +πŸ‘» operation-parameters-must-have-description (examples\simple\README.md:6) + βœ… Test OK (examples\simple\README.md:18) +βœ… Spectral rules merged in the file: examples\simple\spectral.yaml +PS C:\Users\jb.muscat\sources\GitHub\api-guidelines> npx poltergust .\examples\complex +πŸ”Ž Testing the spectral rules from the .md files in the directory: .\examples\complex +πŸ‘» base-path-must-start-with-slash (examples\complex\rules1.md:39) + βœ… Test OK (examples\complex\rules1.md:16) + βœ… Test OK (examples\complex\rules1.md:26) +πŸ‘» operation-parameters-must-have-description (examples\complex\rules1.md:90) + βœ… Test OK (examples\complex\rules1.md:57) + βœ… Test OK (examples\complex\rules1.md:72) +πŸ‘» operation-must-have-description (examples\complex\rules1.md:106) +πŸ‘» operation-must-have-no-summary (examples\complex\rules1.md:121) +πŸ‘» operation-must-have-at-least-one-response (examples\complex\rules1.md:134) +πŸ‘» path-parameters-must-be-kebab-case (examples\complex\rules2.md:49) + βœ… Test OK (examples\complex\rules2.md:11) +πŸ‘» required-property-must-exist (examples\complex\rules2.md:96) + βœ… Test OK (examples\complex\rules2.md:66) +πŸ‘» request-bodies-must-have-a-content (examples\complex\subdirectory\subrules.md:41) + βœ… Test OK (examples\complex\subdirectory\subrules.md:8) + βœ… Test OK (examples\complex\subdirectory\subrules.md:25) +βœ… Spectral rules merged in the file: examples\complex\spectral.yaml +``` \ No newline at end of file diff --git a/examples/valid/functions/isRequiredPropertyDefined.js b/examples/complex/functions/isRequiredPropertyDefined.js similarity index 100% rename from examples/valid/functions/isRequiredPropertyDefined.js rename to examples/complex/functions/isRequiredPropertyDefined.js diff --git a/examples/valid/rules1.md b/examples/complex/rules1.md similarity index 100% rename from examples/valid/rules1.md rename to examples/complex/rules1.md diff --git a/examples/valid/rules2.md b/examples/complex/rules2.md similarity index 100% rename from examples/valid/rules2.md rename to examples/complex/rules2.md diff --git a/examples/valid/spectral.base.yaml b/examples/complex/spectral.base.yaml similarity index 74% rename from examples/valid/spectral.base.yaml rename to examples/complex/spectral.base.yaml index 773268c..9f6e29b 100644 --- a/examples/valid/spectral.base.yaml +++ b/examples/complex/spectral.base.yaml @@ -6,5 +6,5 @@ aliases: parameters: - $.paths[*].parameters - $.paths[*][*].parameters -#rules will be injected from the rules/*.md files -rules: \ No newline at end of file +rules: +#rules will be injected by poltergust \ No newline at end of file diff --git a/examples/valid/spectral.yaml b/examples/complex/spectral.yaml similarity index 97% rename from examples/valid/spectral.yaml rename to examples/complex/spectral.yaml index 66ab7f1..731c2c0 100644 --- a/examples/valid/spectral.yaml +++ b/examples/complex/spectral.yaml @@ -6,8 +6,8 @@ aliases: parameters: - $.paths[*].parameters - $.paths[*][*].parameters -#rules will be injected from the rules/*.md files rules: +#rules will be injected by poltergust base-path-must-start-with-slash: description: Base path must be relative (start with a /) message: "{{description}}. But was {{value}}." diff --git a/examples/valid/subdirectory/subrules.md b/examples/complex/subdirectory/subrules.md similarity index 100% rename from examples/valid/subdirectory/subrules.md rename to examples/complex/subdirectory/subrules.md diff --git a/examples/invalid/spectral.base.yaml b/examples/invalid/spectral.base.yaml index 3dd9936..9fc4890 100644 --- a/examples/invalid/spectral.base.yaml +++ b/examples/invalid/spectral.base.yaml @@ -4,5 +4,5 @@ aliases: parameters: - $.paths[*].parameters - $.paths[*][*].parameters -#rules will be injected from the rules/*.md files -rules: \ No newline at end of file +rules: +#rules will be injected by poltergust \ No newline at end of file diff --git a/examples/simple/README.md b/examples/simple/README.md new file mode 100644 index 0000000..83fc419 --- /dev/null +++ b/examples/simple/README.md @@ -0,0 +1,30 @@ +# Simple example + +1. This is a Spectral rule: + +```yaml +#πŸ‘»-rule +operation-parameters-must-have-description: + description: Operation parameters must have a description + given: $.paths[*][*].parameters[*] + severity: error + then: + field: description + function: truthy +``` + +2. This is a test case for this rule: +```yaml +#πŸ‘»-failures: 1 operation-parameters-must-have-description +openapi: 3.0.1 +paths: + /test/{id}: + get: + parameters: + # the 'id' parameter needs a description + - name: id #πŸ‘»-fails-here: operation-parameters-must-have-description + in: path + required: true + schema: + type: string +``` \ No newline at end of file diff --git a/examples/simple/spectral.base.yaml b/examples/simple/spectral.base.yaml new file mode 100644 index 0000000..75e7c0e --- /dev/null +++ b/examples/simple/spectral.base.yaml @@ -0,0 +1,3 @@ +formats: ["oas3"] +rules: +#rules will be injected by poltergust \ No newline at end of file diff --git a/examples/simple/spectral.yaml b/examples/simple/spectral.yaml new file mode 100644 index 0000000..1b31b67 --- /dev/null +++ b/examples/simple/spectral.yaml @@ -0,0 +1,11 @@ +formats: ["oas3"] +rules: +#rules will be injected by poltergust + operation-parameters-must-have-description: + description: Operation parameters must have a description + given: $.paths[*][*].parameters[*] + severity: error + then: + field: description + function: truthy + \ No newline at end of file diff --git a/examples/valid/README.md b/examples/valid/README.md deleted file mode 100644 index 5139448..0000000 --- a/examples/valid/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Valid example - -* This example contains rules accross several markdown files: [rules1.md](rules1.md) and [rules2.md](rules2.md) and even subdirectories [subdirectory/subrules.md](subdirectory/subrules.md) - * βœ… All the test declared in those files are expected to pass -* Some of the rules use custom functions defined in the [functions](functions) directory -* [spectral.base.yaml](spectral.base.yaml) contains the base rule files that will be used to merge the rules into. For example, it contains the extends, aliases and functions declarations -* [spectral.yaml](spectral.yaml) is the output of the merge operation: [spectral.base.yaml](spectral.base.yaml) + all the rules found in [rules1.md](rules1.md) and [rules2.md](rules2.md) - -## Test ouput - -``` -npx poltergust .\examples\valid -πŸ”Ž Testing the spectral rules from the .md files in the directory: .\examples\valid -πŸ‘» base-path-must-start-with-slash (examples\valid\rules1.md:39) - βœ… Test OK (examples\valid\rules1.md:16) - βœ… Test OK (examples\valid\rules1.md:26) -πŸ‘» operation-parameters-must-have-description (examples\valid\rules1.md:90) - βœ… Test OK (examples\valid\rules1.md:57) - βœ… Test OK (examples\valid\rules1.md:72) -πŸ‘» operation-must-have-description (examples\valid\rules1.md:106) -πŸ‘» operation-must-have-no-summary (examples\valid\rules1.md:121) -πŸ‘» operation-must-have-at-least-one-response (examples\valid\rules1.md:134) -πŸ‘» path-parameters-must-be-kebab-case (examples\valid\rules2.md:49) - βœ… Test OK (examples\valid\rules2.md:11) -πŸ‘» required-property-must-exist (examples\valid\rules2.md:96) - βœ… Test OK (examples\valid\rules2.md:66) -πŸ‘» request-bodies-must-have-a-content (examples\valid\subdirectory\subrules.md:41) - βœ… Test OK (examples\valid\subdirectory\subrules.md:8) - βœ… Test OK (examples\valid\subdirectory\subrules.md:25) -βœ… Spectral rules merged in the file: examples\valid\spectral.yaml -``` \ No newline at end of file