Add evidence-checker extension#634
Conversation
40fb196 to
ec1e0c4
Compare
c507514 to
ac5278a
Compare
ac5278a to
c67037d
Compare
Signed-off-by: Philipp Heil (zkdev) <philipp.heil@sap.com> Co-authored-by: Franziska Schallhorn <franziska.schallhorn@sap.com>
Signed-off-by: Philipp Heil (zkdev) <philipp.heil@sap.com> Co-authored-by: Franziska Schallhorn <franziska.schallhorn@sap.com>
1e8057f to
b79a5b3
Compare
| 3. Test Scope Label | ||
| ~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| The test scope label is set in the component descriptor of a test artefact (aka an artefact whose purpose label has the value 'test) and it defines for which other artefacts it represents the test evidence. |
There was a problem hiding this comment.
missing closing quote in 'test)
| Functionality | ||
| ------------- | ||
|
|
||
| 1. The extension scans each artefact of a component and first validates whether the currently scanned artefact is a test evidence itself or not. This is achieved with the use of the gardener.cloud/purposes label. An artefact is considered a test evidence provided the label's value is 'test'. |
There was a problem hiding this comment.
label value instead of label's value, no? 🤔
|
|
||
| 1. The extension scans each artefact of a component and first validates whether the currently scanned artefact is a test evidence itself or not. This is achieved with the use of the gardener.cloud/purposes label. An artefact is considered a test evidence provided the label's value is 'test'. | ||
|
|
||
| 2. Provided the gardener.cloud/purposes label's has NOT been given the value 'test' the extension further checks, whether the artefact requires a test or not. This is achieved with the gardener.cloud/test-policy label which is either 'true' or 'false. |
|
|
||
| 1. The extension scans each artefact of a component and first validates whether the currently scanned artefact is a test evidence itself or not. This is achieved with the use of the gardener.cloud/purposes label. An artefact is considered a test evidence provided the label's value is 'test'. | ||
|
|
||
| 2. Provided the gardener.cloud/purposes label's has NOT been given the value 'test' the extension further checks, whether the artefact requires a test or not. This is achieved with the gardener.cloud/test-policy label which is either 'true' or 'false. |
There was a problem hiding this comment.
missing closing quote in 'false
|
|
||
| 3. In case an artefact has been identified as a test artefact (as described in step 1) the extension further checks, for which artefacts within the component the test-evidence is valid for. This can be defined with the help of the gardener.cloud/test-scope label. | ||
|
|
||
| 4. In case one of the artefacts identified in step 2 is not covered by the test artefacts(aka evidences) a finding will be created and test-evidences will have to be provided retrospectively. |
There was a problem hiding this comment.
missing space before parentheses in artefacts(aka evidences)
| self, | ||
| artefact_kind: odg.model.ArtefactKind, | ||
| ) -> bool: | ||
| if artefact_kind is not odg.model.ArtefactKind.RESOURCE: |
There was a problem hiding this comment.
is_supported() can be simplified to a single return statement
return artefact_kind is odg.model.ArtefactKind.RESOURCE
|
|
||
| return missing_test_evidence_finding( | ||
| component_resource_id=artefact, | ||
| resource_node=artefact_node, |
There was a problem hiding this comment.
missing_test_evidence_finding(...) is called with unexpected keyword arguments (component_resource_id and resource_node) but the function signature expects artefact and artefact_node
| test_scope_label: odg.labels.TestScopeLabel = odg.labels.deserialise_label( | ||
| label=test_scope_label, | ||
| ) | ||
| artefact_names_with_test_evidence.append(test_scope_label.value) |
There was a problem hiding this comment.
according to the documentation above, gardener.cloud/test-scope contains a list of artefact names — should this use extend(...) instead of append(...) ?
There was a problem hiding this comment.
I agree, we have an inconsistency here, the definition in odg.labels only allows a single artefact name (as it is also honoured here) but the documentation states differently.
| last_update=now, | ||
| ), | ||
| data=odg.model.TestEvidenceMissingFinding( | ||
| test_status=odg.model.TestStatus.NO_TEST_EVIDENCE, |
There was a problem hiding this comment.
odg.model.TestStatus.NO_TEST_EVIDENCE is already passed when you call it, you can use sub_type here instead of hardcoding the same value again
| resource | ||
| for resource in component.resources | ||
| if ( | ||
| (label := resource.find_label(name=odg.labels.PurposeLabel.name)) |
There was a problem hiding this comment.
can we also deserialize PurposeLabel via odg.labels.deserialise_label(...)?
| @@ -0,0 +1,123 @@ | |||
| {{- $podName := "test-evidence" }} | |||
There was a problem hiding this comment.
As discussed out-of-bands, please rename this consistently to evidence-checker (please don't forget file names as well 🥲).
| terminationGracePeriodSeconds: 300 # 5 min | ||
| containers: | ||
| - name: {{ $podName }} | ||
| image: {{ include "image" .Values.image }} |
There was a problem hiding this comment.
I'm not sure whether this is on purpose for the first iteration, but the Helm chart image mapping configuration is still missing in the .github/workflows/build.yaml workflow.
There was a problem hiding this comment.
Some comments to this image:
-
There should be no question mark after "Test Artefact" as it seems to be a state rather than a condition.
-
The "yes" and "no" captions are missing for the "Do they match?" condition
-
Instead of using a boolean value for the test policy, I'd suggest to use an enum instead because
- it is more meaningful without an additional description (e.g. using the values
test-requiredandno-test-requiredor the like) - it allows future extensions
(this does not only affect this image of course but also the implementation and documentation, but I won't comment there again)
- it is more meaningful without an additional description (e.g. using the values
| issues: | ||
| enable_assignees: False | ||
| categorisations: | ||
| - id: NONE |
There was a problem hiding this comment.
Since it is difficult to change the id afterwards, I'd propose to use a more meaningful id right from the beginning (e.g. no-tests-required and no-test-evidence or similar).
| Datasource.SAST: ( | ||
| Datatype.SAST_FINDING, | ||
| ), | ||
| Datasource.TEST_EVIDENCE: (Datatype.TEST_EVIDENCE_FINDING) |
There was a problem hiding this comment.
This does not return a tuple but instead only a single entry, instead use:
Datasource.TEST_EVIDENCE: (
Datatype.TEST_EVIDENCE_FINDING, # note the trailing comma
)| artefact_node: ocm.iter.ArtefactNode, | ||
| extensions_cfg: odg.extensions_cfg.TestEvidenceConfig, | ||
| ) -> bool: | ||
| artefact = artefact_node.artefact |
There was a problem hiding this comment.
nit: Rather pass in the artefact directly to simplify the function's interface (and don't require an unnecessary complex object although only the artefact is used).
| def missing_test_evidence_finding( | ||
| artefact: odg.model.ComponentArtefactId, | ||
| artefact_node: ocm.iter.ArtefactNode, | ||
| sub_type: odg.model.TestStatus, |
There was a problem hiding this comment.
nit: Rather name this test_status rather than sub_type (I think this comes from the SAST extension where we have indeed a sub_type as well as a sast_status).
| findings_cfg: odg.findings.Finding, | ||
| extensions_cfg: odg.extensions_cfg.TestEvidenceConfig, | ||
| ) -> odg.model.ArtefactMetadata | None: | ||
| categorisation: odg.findings.FindingCategorisation = odg.findings.categorise_finding( |
There was a problem hiding this comment.
The categorisation might as well be None in which case we should not create a finding.
| test_status=odg.model.TestStatus.NO_TEST_EVIDENCE, | ||
| severity=categorisation.id | ||
| ), | ||
| discovery_date=now.date(), |
There was a problem hiding this comment.
We should also store the allowed_processing_time here in the finding (read from the categorisation). Rationale: We always want to apply the processing time which was valid at the time of discovering a finding, as opposed to always using the currently configured one (which might change).
| ): | ||
| return None | ||
|
|
||
| now = datetime.datetime.now() |
There was a problem hiding this comment.
nit: Please add timezone information (ditto further down below):
now = datetime.datetime.now(datetime.timezone.utc)
What this PR does / why we need it:
Adds a new ODG extension which creates findings for OCM resources without test-evidences.
Test-evidences are provided as additional OCM resources, whereas a set of defined OCM labels is used to correlate test-evidences to payload artefacts. Additionally, OCM resources can be flagged as "no tests required" which is useful for scenarios where no actual source code is built.
Which issue(s) this PR fixes:
Fixes #
Special notes for your reviewer:
Release note: