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 validate subcommand #380

Merged
merged 32 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f326d1c
wip: initial build of validate command, copied from grype gate
willmurphyscode Aug 27, 2024
973e19d
WIP: working, and specify the tool order
willmurphyscode Aug 28, 2024
cf1f047
make format
willmurphyscode Aug 28, 2024
b362976
wip: mostly working after some big re-arranging
willmurphyscode Aug 29, 2024
40e8214
wip: deltas and tool labels wired up
willmurphyscode Aug 29, 2024
18dc360
wip: new commentary mechanism wired up
willmurphyscode Aug 29, 2024
1996a6a
fix linting
willmurphyscode Aug 29, 2024
42c7fa3
fix a couple display bugs
willmurphyscode Aug 29, 2024
b04794d
fix: pass in max year
willmurphyscode Aug 29, 2024
d78b6ee
feat: allow multiple or all result sets to be specified
willmurphyscode Aug 29, 2024
f093c58
add ability to filter validations by namespace
willmurphyscode Aug 30, 2024
fb96330
export yardstick/validate
willmurphyscode Aug 31, 2024
ed4c81f
validate presence of all allowed namespaces
willmurphyscode Aug 31, 2024
c9d6bf3
clean up some false starts
willmurphyscode Sep 4, 2024
cfe0112
chore: add some more logging
willmurphyscode Sep 4, 2024
0b61526
more work on yardstick validate
willmurphyscode Sep 5, 2024
e991888
feat: enable quality gate to fail on empty match set
willmurphyscode Sep 12, 2024
fe434b4
guess tool orientation from only one label
willmurphyscode Sep 13, 2024
b5044f8
refactor: simplify gate
willmurphyscode Sep 18, 2024
46a22cb
refactor: extra compute deltas
willmurphyscode Sep 18, 2024
9d8194e
refactor: extract tool designations, better docs
willmurphyscode Sep 18, 2024
11c2fc0
test: clean up and test gate dataclass
willmurphyscode Sep 18, 2024
cf2509e
refactor: make validate its own module
willmurphyscode Sep 18, 2024
ea816e4
chore: linting and rearranging
willmurphyscode Sep 18, 2024
54b7100
chore: clean up false start
willmurphyscode Sep 18, 2024
3aa3c16
chore: clean up more false starts
willmurphyscode Sep 18, 2024
d54a18b
test: test for delta dataclass
willmurphyscode Sep 19, 2024
61087ce
test: some unit tests for validate_image
willmurphyscode Sep 19, 2024
0f5e556
move compute_deltas to delta file and test
willmurphyscode Sep 19, 2024
1e47970
chore: more cleaning up
willmurphyscode Sep 19, 2024
c4e457c
test: more complete test of validate_image
willmurphyscode Sep 20, 2024
d291ef0
chore: bump poetry
willmurphyscode Sep 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/validations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ permissions:

env:
PYTHON_VERSION: "3.11"
POETRY_VERSION: "1.3.2"
POETRY_VERSION: "1.8.3"

jobs:

Expand Down
14 changes: 13 additions & 1 deletion src/yardstick/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import logging
from typing import Callable, Optional

from . import arrange, artifact, capture, cli, comparison, label, store, tool, utils
from . import (
arrange,
artifact,
capture,
cli,
comparison,
label,
store,
tool,
validate,
utils,
)

__all__ = [
"arrange",
Expand All @@ -12,6 +23,7 @@
"label",
"store",
"tool",
"validate",
"utils",
]

Expand Down
2 changes: 2 additions & 0 deletions src/yardstick/artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ class ScanConfiguration:
image_digest: str
tool_name: str
tool_version: str
tool_label: str | None = None
image_tag: str = ""
timestamp: datetime.datetime | None = field(
default=None,
Expand Down Expand Up @@ -205,6 +206,7 @@ def new(
tool_name=tool_obj.id,
tool_version=tool_obj.version,
timestamp=timestamp,
tool_label=label,
)


Expand Down
3 changes: 2 additions & 1 deletion src/yardstick/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import yaml

from yardstick import store
from yardstick.cli import config, label, result
from yardstick.cli import config, label, result, validate


@click.option("--verbose", "-v", default=False, help="show logs", is_flag=True)
Expand Down Expand Up @@ -126,5 +126,6 @@ def version(_: config.Application):
print(f"{d.name} {d.version} ({d.locate_file(d.name).parent})")


cli.add_command(validate.validate)
cli.add_command(result.group)
cli.add_command(label.group)
36 changes: 35 additions & 1 deletion src/yardstick/cli/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import yaml
from dataclass_wizard import asdict, fromdict # type: ignore[import]

from yardstick import artifact
from yardstick import artifact, validate
from yardstick.store import config as store_config

DEFAULT_CONFIGS = (
Expand Down Expand Up @@ -115,11 +115,17 @@ def parse_oci_reference(image: str) -> tuple[str, str, str, str, str]:
return host, path, repository, tag, digest


@dataclass()
class Validation(validate.GateConfig):
name: str = "default"


@dataclass()
class ResultSet:
description: str = ""
declared: list[artifact.ScanRequest] = field(default_factory=list)
matrix: ScanMatrix = field(default_factory=ScanMatrix)
validations: list[Validation] = field(default_factory=list)

def images(self) -> list[str]:
return self.matrix.images + [req.image for req in self.declared]
Expand Down Expand Up @@ -151,6 +157,34 @@ class Application:
default_max_year: int | None = None
derive_year_from_cve_only: bool = False

def max_year_for_any_result_set(self, result_sets: list[str]) -> int | None:
years = []
for result_set in result_sets:
m = self.max_year_for_result_set(result_set)
if m is not None:
years.append(m)

if not years:
return None

return max(years)

def max_year_for_result_set(self, result_set: str) -> int | None:
"""return the max year needed by any validation on the result set, or default_max_year"""
rs = self.result_sets.get(result_set, None)
years = []
if rs is not None:
for gate in rs.validations:
if gate.max_year is not None:
years.append(gate.max_year)
elif self.default_max_year is not None:
years.append(self.default_max_year)

if years:
return max(years)

return self.default_max_year


def clean_dict_keys(d):
new = {}
Expand Down
Loading