diff --git a/.gitignore b/.gitignore index 6429cdc7..ded22649 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.mise.toml + .vunnel.yaml .grype-db.yaml .grype.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0ce2e84d..8ff70a17 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ # the default is to run these on commit + push default_stages: - - push + - pre-push repos: - repo: https://github.com/pre-commit/pre-commit-hooks @@ -10,47 +10,47 @@ repos: # Prevent giant files from being committed. - id: check-added-large-files stages: - - push + - pre-push # Checks for a common error of placing code before the docstring. - id: check-docstring-first stages: - - push + - pre-push # Attempts to load all yaml files to verify syntax. - id: check-yaml stages: - - push + - pre-push # Attempts to load all json files to verify syntax. - id: check-json stages: - - push + - pre-push # Makes sure files end in a newline and only a newline. - id: end-of-file-fixer stages: - - push + - pre-push # Trims trailing whitespace. - id: trailing-whitespace stages: - - push + - pre-push # Check for files that contain merge conflict strings. - id: check-merge-conflict stages: - - push + - pre-push # Simply check whether files parse as valid python. - id: check-ast stages: - - push + - pre-push # Check for files with names that would conflict on a case-insensitive filesystem like MacOS HFS+ or Windows FAT. - id: check-case-conflict stages: - - push + - pre-push # why use the local repo instead of hosted hooks? so that dependencies are centrally managed through poetry - repo: local diff --git a/schema/provider-workspace-state/schema-1.0.3.json b/schema/provider-workspace-state/schema-1.0.3.json new file mode 100644 index 00000000..5e7870d9 --- /dev/null +++ b/schema/provider-workspace-state/schema-1.0.3.json @@ -0,0 +1,84 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "title": "provider-workspace-state", + "description": "describes the filesystem state of a provider workspace directory", + "properties": { + "provider": { + "type": "string" + }, + "urls": { + "type": "array", + "items": [ + { + "type": "string" + } + ] + }, + "store": { + "type": "string" + }, + "timestamp": { + "type": "string" + }, + "listing": { + "type": "object", + "properties": { + "digest": { + "type": "string" + }, + "path": { + "type": "string" + }, + "algorithm": { + "type": "string" + } + }, + "required": [ + "digest", + "path", + "algorithm" + ] + }, + "version": { + "type": "integer", + "description": "version describing the result data shape + the provider processing behavior semantics" + }, + "distribution_version": { + "type": "integer", + "description": "version describing purely the result data shape" + }, + "processor": { + "type": "string", + "description": "the application that created the workspace, formatted as 'name@version'" + }, + "schema": { + "type": "object", + "properties": { + "version": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "required": [ + "version", + "url" + ] + }, + "stale": { + "type": "boolean", + "description": "set to true if the workspace is stale and cannot be used for an incremental update" + } + }, + "required": [ + "provider", + "urls", + "store", + "timestamp", + "listing", + "version", + "schema" + ] +} diff --git a/src/vunnel/schema.py b/src/vunnel/schema.py index e5d1f898..30ba94a3 100644 --- a/src/vunnel/schema.py +++ b/src/vunnel/schema.py @@ -4,7 +4,7 @@ from dataclasses import dataclass # Note: this metadata.json file currently is not allowed to have a breaking change -PROVIDER_WORKSPACE_STATE_SCHEMA_VERSION = "1.0.2" +PROVIDER_WORKSPACE_STATE_SCHEMA_VERSION = "1.0.3" PROVIDER_ARCHIVE_LISTING_SCHEMA_VERSION = "1.0.0" MATCH_EXCLUSION_SCHEMA_VERSION = "1.0.0" diff --git a/src/vunnel/workspace.py b/src/vunnel/workspace.py index 66b46083..a361ced7 100644 --- a/src/vunnel/workspace.py +++ b/src/vunnel/workspace.py @@ -17,6 +17,7 @@ from vunnel.utils import hasher if TYPE_CHECKING: + import types from collections.abc import Generator METADATA_FILENAME = "metadata.json" @@ -38,10 +39,31 @@ class State(DataClassDictMixin): timestamp: datetime.datetime version: int = 1 distribution_version: int = 1 + processor: str | None = None listing: Optional[File] = None # noqa:UP007 # why use Optional? mashumaro does not support this on python 3.9 schema: schema_def.Schema = field(default_factory=schema_def.ProviderStateSchema) stale: bool = False + def __post_init__(self) -> None: + if not self.processor: + metadata: types.ModuleType + package_name = "vunnel" + version = "dev" + try: + from importlib import metadata + except ImportError: + # Python < 3.8 + import importlib_metadata as metadata + + try: + if not metadata: + raise metadata.PackageNotFoundError + version = metadata.version(package_name) + except metadata.PackageNotFoundError: + version = "unknown" + + self.processor = f"{package_name}@{version}" + @staticmethod def read(root: str) -> State: metadata_path = os.path.join(root, METADATA_FILENAME)