-
Notifications
You must be signed in to change notification settings - Fork 108
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
Adding support for linting profiles #595
Conversation
@@ -97,6 +97,9 @@ Example ZLint CLI usage: | |||
echo "Lint mycert.pem with all of the lints except for ETSI ESI sourced lints" | |||
zlint -excludeSources=ETSI_ESI mycert.pem | |||
|
|||
echo "List available lint profiles. A profile is a pre-defined collection of lints." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was apprehensive of adding an example of running a profile here because don't actually have any yet. That is, I didn't want to give an example that doesn't actually run.
@@ -32,11 +32,14 @@ import ( | |||
"github.com/zmap/zlint/v3" | |||
"github.com/zmap/zlint/v3/formattedoutput" | |||
"github.com/zmap/zlint/v3/lint" | |||
|
|||
_ "github.com/zmap/zlint/v3/profiles" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to trigger the init
functions in /profiles
so that we can build our FilterOptions
appropriately. If we try to add this import into lint
then it causes an import cycle between lint
and profiles
😕
@@ -192,10 +207,17 @@ func trimmedList(raw string) []string { | |||
// use. | |||
func setLints() (lint.Registry, error) { | |||
// If there's no filter options set, use the global registry as-is | |||
if nameFilter == "" && includeNames == "" && excludeNames == "" && includeSources == "" && excludeSources == "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a style change because this boolean condition was getting long.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, looks good :-)
@@ -0,0 +1,5 @@ | |||
package profiles |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, sorry, if you have a package with nothing in it but test files then golangci-lint
vomits uncontrollably. We'll have to delete this once our first profile lands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @christopher-henderson. This seems like a nice extension. I left a few small comments.
Do you have thoughts on the first profile to include? There are a couple points in the PR where you work around not having a profile (e.g. w/ todo.go
, and not including a README example). I also had a question about whether we needed a couple model fields. I think maybe we could address both of these things by including a commit in this branch that introduces a profile if there's a good first candidate. What do you think?
// The source of the check, e.g. "BRs: 6.1.6" or "RFC 5280: 4.1.2.6". | ||
Citation string `json:"citation,omitempty"` | ||
|
||
// Programmatic source of the check, BRs, RFC5280, or ZLint | ||
Source LintSource `json:"source,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering whether it's acceptable to consider a Profile
's citations/sources as the aggregate of the citations/sources of the lints indicated in LintNames
. If so maybe we can simplify the model a little bit and drop these two fields.
If you think there is a use-case for having profile-level citations/sources I think the comments need to be adjusted slightly. "source of the check" reads like there's a singular "check" which (IMO) conflicts with the multiple LintNames
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Sorry, this is likely an artifact that I hadn't bothered to aggregate the discussion in #583 into #594)
So these profiles aren't arbitrary groupings. The plan is that they do come a from source requirement (the first impetus of which is sleevi/cabforum-docs#36). So the idea is that a parent source lists a collection of requirements with an explanation as to why they are grouped.
CABF/BR x.y.z
Section A:
Due to whatever reason <requirement A>, <requirement B>, <requirement C> from RFRC5280 should...
{
Citation: "Due to whatever reason, these requirements from RFC5280 should...",
Source: lint.CABFBR_X_Y_Y
}
"source of the check" reads like there's a singular "check"
Effectively there is, in that if one sub-check fails then the whole check fails, and thus you have failed the profile from the cited source. A bit like how a boolean expression can comprised of multiple boolean expressions (and named).
// In Chris' humble opinion the following is what is considered
// altogether a nice day.
func isANiceDay(sunny, cool, butNotTooCool, lightbreeze, bool) {
return sunny && cool && butNotTooCool && lightbreeze
}
Each individual one may-or-may-not be desirable in their own context. However, grouped together they answer the single question, "By Chris' definition is this a nice day?"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
....although that was my take on it. Since @sleevi is the first source of these, does it make sense for there to be a simple inheritance type scheme where we can just say that a profile's citations is the list of its lints' citations?
return profile, ok | ||
} | ||
|
||
func AllProfiles() []Profile { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can you add a godoc comment on this exported func too? 🙇
Absolutely Co-authored-by: Daniel McCarney <daniel@binaryparadox.net>
The first candidates come from @sleevi's work at sleevi/cabforum-docs#36.
I'm somewhat partial to #1 as I think it makes sense to have code ready to go, but not necessarily have dead code in master. |
What is a Profile
A profile derives from the conversation in #583 wherein we would like to have curated lists of lints that, collectively, refer to a particular requirement from, say, the CABF.
The solution put forth in this PR is that a
profile
is essentially an alias for a comma separated list of lints submitted via-includeNames
, however with some extra metadata attached (such as where did thisprofile
come from).Profile Implementation
A profile does not appear to have any behavior of it's own. Rather, it is simply a declaration of lints that are logically grouped together by an external requirement. As such, we can borrow infrastructure from our lints that is similar, however much simpler.
I believe that something as simple as the following should suffice.
I'm not sure if profiles should have a
CheckApplies
? One would think that is inherited from individual lints aggregated within the profile.Running a Profile
Let's say that
the_profile_in_question
is comprised of the lintsa
,b
,c
,d
.Is the equivalent to running
./zlint -includeNames="a,b,c,d"
A new CLI flag has been added that lists each profile as line-delimited JSON (much in the same way one prints out available lints).
Adding a New Profile
The convenience script
newProfile.sh <profile_name>
has been added that acts in much the same way asnewLint.sh
does.Documentation has been added to CONTRIBUTING.md
(resolves #595 )