-
Notifications
You must be signed in to change notification settings - Fork 308
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
refactor(scanner)!: Use the configurable plugin API for scanner wrappers #7673
Conversation
679a7e5
to
fecf57f
Compare
Codecov ReportAll modified lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #7673 +/- ##
=========================================
Coverage 68.06% 68.06%
Complexity 2023 2023
=========================================
Files 344 344
Lines 16741 16741
Branches 2371 2371
=========================================
Hits 11394 11394
Misses 4366 4366
Partials 981 981
Flags with carried forward coverage won't be shown. Click here to find out more.
☔ View full report in Codecov by Sentry. |
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 believe reference.yml
should also be adjusted for the scanner options.
private const val COMMAND_LINE_PROPERTY = "commandLine" | ||
private const val COMMAND_LINE_NON_CONFIG_PROPERTY = "commandLineNonConfig" | ||
|
||
fun create(options: Options) = | ||
ScanCodeConfig(options[COMMAND_LINE_PROPERTY], options[COMMAND_LINE_NON_CONFIG_PROPERTY]) |
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: Strictly speaking IMO the knowledge about the names of the keys in the options map is not something the ScanCodeConfig
should need to care about. All existing implementations inline this to parseConfig
, which I believe is the better place, as it "glues" options to ScanCodeConfig
.
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.
Ah, now I see where this probably comes from: The ScanOss implementation already did it that way. However, I'd then prefer to inline this for ScanOss in a preceding commit.
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 think the ScanOss implementation was actually inspired by the FossId config. Looking at the number of properties the FossIdConfig
supports in this case there is a clear benefit in moving the parsing to a separate file. What would you think of keeping the implementation as is for now and to discuss in the next dev meeting if we want to align on one approach?
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.
discuss in the next dev meeting
I'm fine with that, it was only a nit anyway. Please put this on the agenda then.
} | ||
|
||
final override fun create(config: CONFIG): ScannerWrapper { | ||
throw UnsupportedOperationException("Use create(CONFIG, ScannerMatcherConfig) instead.") |
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: Maybe single-quote the function call for clarity?
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.
Are these backticks now instead of single quotes? If I'm not mistaken so far we never use backticks in such output, so I'd prefer to stick to single quotes.
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.
Right, I used backticks out of habit, switched to single quotes now.
"other" to "value" | ||
) | ||
|
||
ScannerMatcherConfig.create(options).second shouldContainExactly mapOf("other" to "value") |
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.
Can't we uncritically combine the tests by also asserting .first
here? Like
with(ScannerMatcherConfig.create(options)) {
with(first) {
regScannerName shouldBe "foo"
minVersion shouldBe "1.2.3"
maxVersion shouldBe "4.5.6"
configuration shouldBe "config"
}
second shouldContainExactly mapOf("other" to "value")
}
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 could, but since the tests are super fast I like that the test name already shows which feature of the function is tested/broken.
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 don't think that's worth the code duplication, but ok.
* the properties that are used to configure the matcher. | ||
*/ | ||
fun create(options: Options): Pair<ScannerMatcherConfig, Options> { | ||
val filteredOptions = options.filterKeys { it !in properties } |
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.
Another thought: Now that we have a clean separation between options
and secrets
, it seems a bit weird to include storage related configuration into scanner options. It probably would be cleaner to introduce a third "top-level" matcher
configuration map for these. Or even move the matcher options to the storage configuration (if scan storages were plugins) as you might want to have more lenient matchers for storages that e.g. only offer older ScanCode results ("better take something than nothing"), but use more strict matchers for storages that also have newer ScanCode results.
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 also not super happy about the tight coupling of the matcher and the wrapper config, but I would prefer to keep it for now to not further complicate the changes. In a similar direction I was thinking that it could be useful to allow different configurations for the same scanner class, like we allow it for curation providers, for example to use different settings to scan projects and packages. However, since this and the feature you suggested to have different matchers for different storages are currently theoretical use cases without a real demand I think we should discuss these ideas first in the dev or community meetings.
fecf57f
to
b2e4a11
Compare
The scanner options are not yet changed in this PR, this will happen in the next PR which will take the secrets map into use for scanner wrappers. |
But isn't this commit then temporarily breaking scanner matcher configuration as it is now expected to come from per-scanner options, but there are no such options yet? |
No, the were already part of the scanner specific options before, see: ort/model/src/main/resources/reference.yml Lines 207 to 218 in 5cdf8ce
|
Use the `TypedConfigurablePluginFactory` interface as base for the `ScannerWrapperFactory` to further align the plugin APIs. While at it, extract the logic to parse the scanner matcher properties to a central place to not have to repeat the properties in the configuration classes for all scanner wrappers. This also makes it possible to use `Unit` as configuration class for scanners that do not offer any configuration options. As this change makes the configuration classes of the scanner wrappers part of the public API, they must not be `internal` anymore. Scanners that provide secret configuration options will be migrated to read them from the `secrets` map instead of the `options` map in later commits. Signed-off-by: Martin Nonnenmacher <martin.nonnenmacher@bosch.io>
b2e4a11
to
9577b50
Compare
Use the
TypedConfigurablePluginFactory
interface as base for theScannerWrapperFactory
to further align the plugin APIs. While at it, extract the logic to parse the scanner matcher properties to a central place to not have to repeat the properties in the configuration classes for all scanner wrappers. This also makes it possible to useUnit
as configuration class for scanners that do not offer any configuration options.As this change makes the configuration classes of the scanner wrappers part of the public API, they must not be
internal
anymore.Scanners that provide secret configuration options will be migrated to read them from the
secrets
map instead of theoptions
map in later commits.Breaking API change:
The
ScannerWrapperFactory
API was changed so all scanner wrapper plugins need to be adapted. See the PR diff for examples.