Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(linting): Add support for linting decK files #981

Merged
merged 3 commits into from
Oct 18, 2023
Merged

feat(linting): Add support for linting decK files #981

merged 3 commits into from
Oct 18, 2023

Conversation

mheap
Copy link
Member

@mheap mheap commented Jul 24, 2023

Adds support for linting declarative configurations.

Example usage:

deck file lint -s ./kong.yaml -r ruleset.yaml

You can control what's considered an error:

deck file lint -s ./kong.yaml -r ruleset.yaml --fail-severity info

Or only show errors:

deck file lint -s ./kong.yaml -r ruleset.yaml -D

It supports JSON and YAML output in addition to a human readable default:

Linting Violations: 2
Failures: 1

[9:15] Must use HTTPS protocol: `http` does not match the expression `^https`
[1:18] Check the version is correct: `3.0` does not match the expression `^1.1$`
exit status 1

Tested with the following input files:

# kong.yaml
_format_version: "3.0"
services:
  - host: mockbin.org
    id: b1525aee-d304-11ed-afa1-0242ac120002
    name: summer-time
    path: /requests
    plugins: []
    port: 443
    protocol: http
    routes:
      - id: b7d87736-d304-11ed-afa1-0242ac120002
        methods:
          - GET
        name: summer-time_get
        paths:
          - ~/summer-time$
        plugins: []
        regex_priority: 200
        strip_path: false
        tags: []
# ruleset.yaml
rules:
  version-30:
    description: "Check the version is correct"
    given: $._format_version
    severity: error
    then:
      function: pattern
      functionOptions:
        match: "^1.1$"
  https-only:
    description: "Must use HTTPS protocol"
    given: $.services[*].protocol
    severity: warn
    then:
      function: pattern
      functionOptions:
        match: "^https"

Usage:

Usage:
  deck file lint [flags] lint-file

Flags:
  -D, --display-only-failures   only display failures
      --fail-severity string    minimum severity to fail on (default "warn")
      --format string           output format: default, json or yaml (default "default")
  -h, --help                    help for lint
  -r, --ruleset string          Ruleset to apply to the state file.
  -s, --state string            decK file to process. Use - to read from stdin. (default "-")

Jira: APIOPS-53

edit: added jira link

@mheap mheap requested a review from a team July 24, 2023 09:21
@CLAassistant
Copy link

CLAassistant commented Jul 24, 2023

CLA assistant check
All committers have signed the CLA.

@mheap mheap force-pushed the file-lint branch 2 times, most recently from 5823a9b to 8540606 Compare July 24, 2023 09:32
Copy link
Collaborator

@GGabriele GGabriele left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work!

I added a few suggestions and requests in the code. On top of those, can you please make sure to rebase on top of main and also add some basic test? Something like this should be relatively easy to replicate.

cmd/file_lint.go Outdated Show resolved Hide resolved
cmd/file_lint.go Outdated
)

var (
cmdLintInputFilename string
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 2 variables are never used.

Also, not passing a statefile and using - as default doesn't work:

$ ./deck file lint - --ruleset ruleset.yaml
panic: open -: no such file or directory

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear what lint-file is in the usage, so this usage appears undefined to me. If we want to allow positional arguments, it seems we need to decide if that is the input state file(s) or the rules file(s). Can the underlying library support multiple rules files? It may make sense to allow a single input state file via -s,--state and multiple rules files as the positional arguments.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the underlying library support multiple rules files?

The library gets a single input, so it's a matter of implementing the logic in decK to merge the rulesets.

It may make sense to just support a single state file and a single ruleset for starters. WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t see a use case for supporting multiple at this point. Users can run the tool multiple times, or use the merge function to generate a single input

cmd/file_lint.go Show resolved Hide resolved
cmd/file_lint.go Outdated Show resolved Hide resolved
cmd/file_lint.go Outdated Show resolved Hide resolved
cmd/file_lint.go Outdated Show resolved Hide resolved
cmd/file_lint.go Outdated Show resolved Hide resolved
cmd/file_lint.go Outdated Show resolved Hide resolved
cmd/file_lint.go Show resolved Hide resolved
cmd/file_lint.go Outdated Show resolved Hide resolved
cmd/file_lint.go Outdated
Long: `Long description Here`,
RunE: executeLint,
Short: "Lint a file against a ruleset",
Long: "Lint a file against a ruleset. \n" +
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mheap @rspurgeon can you please validate these?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not sure what lint-file represents in this usage. I think we're using flags for both the state file and the rules file, so what is lint-file?

As far as help text:

Suggested change
Long: "Lint a file against a ruleset. \n" +
Long: "Validate a decK state file against a linting ruleset, reporting any violations or failures. Report output can be returned in JSON, YAML, or human readable format (see --format). \n" +

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also think it's important we document the --fail-severity flag and how it affects the return code of the command. I assume that users of this will want to branch behaviors based on command return code. I think we should provide details here. I would make a suggestion, but I'm not sure at this point how the code works in that regard.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion!

Fixed this. 3bdd2fe

Copy link
Collaborator

@GGabriele GGabriele Aug 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would make a suggestion, but I'm not sure at this point how the code works in that regard.

Basically --fail-severity will gate what returns a non-zero (1) exit code. Feel free to make a suggestion.

Also, is --display-only-failures expected to care about error only or it should adapt to the --fail-severity value? If the --display-only-failures flag should care only about error I suggest we change it to --display-only-errors.

Thoughts? @rspurgeon @mheap

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--fail-severity and --display-only-failures are taken from Spectral, which is the defacto implementation of linting https://docs.stoplight.io/docs/spectral/9ffa04e052cc1-spectral-cli

We should adapt to the --fail-severity value

From Spectral:

-D, --display-only-failures only output results equal to or greater than --fail-severity [boolean] [default: false]

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mheap thanks for the clarifying!

a4e025c

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just adopt what the spectral CLI supports directly? Can we update our usage to be:

-F, --fail-severity results of this level or above will trigger a failure exit code
[string] [choices: "error", "warn", "info", "hint"] [default: "error"]
-D, --display-only-failures only output results equal to or greater than --fail-severity [boolean] [default: false]

@codecov-commenter
Copy link

codecov-commenter commented Aug 22, 2023

Codecov Report

Attention: 122 lines in your changes are missing coverage. Please review.

Comparison is base (30f19db) 33.50% compared to head (70f4eb2) 33.18%.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #981      +/-   ##
==========================================
- Coverage   33.50%   33.18%   -0.33%     
==========================================
  Files         101      102       +1     
  Lines       12460    12582     +122     
==========================================
  Hits         4175     4175              
- Misses       7878     8000     +122     
  Partials      407      407              
Files Coverage Δ
cmd/root.go 0.88% <0.00%> (-0.01%) ⬇️
cmd/file_lint.go 0.00% <0.00%> (ø)

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

GGabriele
GGabriele previously approved these changes Aug 23, 2023
@rspurgeon
Copy link
Collaborator

Should we output the severity in plaintext mode? It is provided in JSON or YAML format and I think is helpful for adjusting the rules or severity threshold.

./deck file lint -s ~/dev/tmp/kong-mock.yaml -r ~/dev/tmp/ruleset.yaml
Linting Violations: 2
Failures: 2

[10:15] Must use HTTPS protocol: `http` does not match the expression `^https`
[2:18] Check the version is correct: `3.0` does not match the expression `^1.1$`

Maybe something like:

[error][10:15] Must use HTTPS protocol: `http` does not match the expression `^https`
[warn][2:18] Check the version is correct: `3.0` does not match the expression `^1.1$`

@GGabriele
Copy link
Collaborator

@rspurgeon I think I addressed both your latest comments. Let me know!

Copy link
Collaborator

@rspurgeon rspurgeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, impressive work @mheap and @GGabriele

cmd/file_lint.go Outdated Show resolved Hide resolved
mikefero
mikefero previously approved these changes Sep 6, 2023
Copy link
Contributor

@mikefero mikefero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. @mheap Do we plan on creating docs for this new feature and give some guidance to users (or even create a few real world examples)?

@rspurgeon
Copy link
Collaborator

As discussed with @Tieske , I'd prefer we hold this for a new release version instead of merging into a revision release. We want to bundle this with other APIops related features that are slated for completion the coming weeks. Part of that work includes public docs, blog announcement, etc...

@Tieske
Copy link
Member

Tieske commented Oct 17, 2023

added a commit to line up the cli args with the other commands. Please review the last commit.

Tieske
Tieske previously approved these changes Oct 17, 2023
@Tieske
Copy link
Member

Tieske commented Oct 17, 2023

As discussed with @Tieske , I'd prefer we hold this for a new release version instead of merging into a revision release. We want to bundle this with other APIops related features that are slated for completion the coming weeks. Part of that work includes public docs, blog announcement, etc...

@rspurgeon this no longer holds right? we can merge once approved?

@rspurgeon
Copy link
Collaborator

@rspurgeon this no longer holds right? we can merge once approved?

Yes, thank you... We are clear to ship incremental (non-breaking) features in minor releases. We should provide sufficient documentation both in product and on public docs site before merging, however.

@Tieske Tieske merged commit dc106ee into main Oct 18, 2023
35 checks passed
@Tieske Tieske deleted the file-lint branch October 18, 2023 15:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants