Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
503 changes: 501 additions & 2 deletions checkup.schema.json

Large diffs are not rendered by default.

32 changes: 18 additions & 14 deletions checkup.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,23 @@ tags:
project: checkup

providers:
- name: git
- name: git

metrics:
- type: git_days_since_last_update
- type: git_tracked_file_count
pattern: src/checkup/*
- type: git_tracked_file_count
name: checkup_yaml_exists
pattern: checkup.yaml
- type: git_tracked_file_count
name: pre_commit_config_exists
pattern: .pre-commit-config.yaml
- type: python_version
- type: python_version_check
min_version: '3.13'
max_version: '3.15'
- type: git_days_since_last_update
- type: git_tracked_file_count
name: checkup_yaml_exists
description: Checkup yaml exists
pattern: checkup.yaml
- type: git_tracked_file_count
name: pre_commit_config_exists
description: Pre-commit config exists
pattern: .pre-commit-config.yaml
- type: python_version
- type: python_version_check
min_version: "3.13"
max_version: "3.15"

materializer:
type: console
pretty: true
7 changes: 2 additions & 5 deletions plugins/checkup-conveyor/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ version = "0.4.0"
description = "Conveyor metrics for checkup"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"checkup",
"requests"
]
dependencies = ["checkup", "requests"]

[project.urls]
Homepage = "https://github.com/datamindedbe/checkup"
Expand All @@ -22,7 +19,7 @@ conveyor = "checkup_conveyor:ConveyorProvider"

[project.entry-points."checkup.metrics"]
conveyor_last_deployment_time = "checkup_conveyor.conveyor_metric:ConveyorLastDeploymentTime"
conveyor_is_dirty_deployment = "checkup_conveyor.conveyor_metric:ConveyorIsDirtyDeployment"
conveyor_clean_deployment = "checkup_conveyor.conveyor_metric:ConveyorCleanDeployment"
conveyor_last_run_status = "checkup_conveyor.conveyor_metric:ConveyorLastRunStatus"

[build-system]
Expand Down
13 changes: 8 additions & 5 deletions plugins/checkup-conveyor/src/checkup_conveyor/conveyor_metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from checkup import Context
from checkup.measurement import Measurement, Measurements
from checkup.metric import Unit
from checkup_conveyor import ConveyorMetric

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -33,10 +34,12 @@ def calculate(self, context: Context, measurements: Measurements) -> Measurement
)


class ConveyorIsDirtyDeployment(ConveyorMetric):
name: ClassVar[str] = "Conveyor Is Dirty Deployment"
description: ClassVar[str] = "True if the last deployment was dirty"
unit: ClassVar[str] = "boolean"
class ConveyorCleanDeployment(ConveyorMetric):
name: ClassVar[str] = "Conveyor Clean Deployment"
description: ClassVar[str] = (
"Whether the last deployment was built from a clean git tree"
)
unit: ClassVar[str] = Unit.BOOLEAN

def calculate(self, context: Context, measurements: Measurements) -> Measurement:
proj_id = self.get_conveyor_project_id(context)
Expand All @@ -54,7 +57,7 @@ def calculate(self, context: Context, measurements: Measurements) -> Measurement
diagnostic = (
"Commit changes to git, and deploy the project again." if is_dirty else ""
)
return self.measure(value=is_dirty, diagnostic=diagnostic)
return self.measure(value=not is_dirty, diagnostic=diagnostic)


class ConveyorLastRunStatus(ConveyorMetric):
Expand Down
4 changes: 2 additions & 2 deletions plugins/checkup-conveyor/test/test_conveyor_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pytest
from checkup_conveyor import ConveyorProvider
from checkup_conveyor.conveyor_metric import (
ConveyorIsDirtyDeployment,
ConveyorCleanDeployment,
ConveyorLastDeploymentTime,
ConveyorLastRunStatus,
)
Expand All @@ -25,7 +25,7 @@ def test_conveyor_integration():
.with_metrics(
[
ConveyorLastDeploymentTime,
ConveyorIsDirtyDeployment,
ConveyorCleanDeployment,
ConveyorLastRunStatus,
]
)
Expand Down
10 changes: 5 additions & 5 deletions plugins/checkup-cruft/src/checkup_cruft/metrics.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from datetime import UTC, datetime

from checkup.measurement import Measurement, Measurements
from checkup.metric import Metric
from checkup.metric import Metric, Unit
from checkup.provider import Provider
from checkup.types import Context
from checkup_cruft.provider import CruftProvider
Expand All @@ -27,11 +27,11 @@ class CruftLinkedMetric(CruftMetric):

name: str = "cruft_linked"
description: str = "Whether a .cruft.json template link is present"
unit: str = "boolean"
unit: str = Unit.BOOLEAN

def calculate(self, context: Context, measurements: Measurements) -> Measurement:
cruft = self.get_context(context)
return self.measure(value=1 if cruft.get("present") else 0)
return self.measure(value=bool(cruft.get("present")))


class CruftDaysSinceUpdateMetric(CruftMetric):
Expand Down Expand Up @@ -98,14 +98,14 @@ class CruftUpToDateMetric(CruftMetric):

name: str = "cruft_up_to_date"
description: str = "Whether the project matches the latest template commit"
unit: str = "boolean"
unit: str = Unit.BOOLEAN

def calculate(self, context: Context, measurements: Measurements) -> Measurement:
cruft = self.get_context(context)
behind = cruft.get("commits_behind")
if behind is None:
return self.measure(value=None, diagnostic="Template not fetched")
return self.measure(value=1 if behind == 0 else 0)
return self.measure(value=behind == 0)


class CruftDaysBehindTemplateMetric(CruftMetric):
Expand Down
8 changes: 4 additions & 4 deletions plugins/checkup-cruft/tests/test_cruft_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ def _measure(repo: Path, metric, *, fetch_template: bool = False):

def test_linked_true(make_product, template_repo):
repo = make_product(template_repo, "deadbeef")
assert _measure(repo, CruftLinkedMetric()).value == 1
assert _measure(repo, CruftLinkedMetric()).value is True


def test_linked_false(make_product):
repo = make_product()
assert _measure(repo, CruftLinkedMetric()).value == 0
assert _measure(repo, CruftLinkedMetric()).value is False


def test_days_since_update_fresh(make_product, template_repo):
Expand Down Expand Up @@ -96,12 +96,12 @@ def test_up_to_date_when_pinned_to_head(make_product, template_repo):
check=True,
).stdout.strip()
repo = make_product(template_repo, head)
assert _measure(repo, CruftUpToDateMetric(), fetch_template=True).value == 1
assert _measure(repo, CruftUpToDateMetric(), fetch_template=True).value is True


def test_up_to_date_false_when_behind(make_product, template_repo):
repo = make_product(template_repo, _first_commit(template_repo))
assert _measure(repo, CruftUpToDateMetric(), fetch_template=True).value == 0
assert _measure(repo, CruftUpToDateMetric(), fetch_template=True).value is False


def test_days_behind_template(make_product, template_repo):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging

from checkup.measurement import Measurement, Measurements
from checkup.metric import Metric
from checkup.metric import Metric, Unit
from checkup.types import Context
from checkup_dbt.metrics.base import DbtMetric
from checkup_dbt.metrics.quality.version import DbtVersionMetric
Expand All @@ -16,7 +16,7 @@ class DbtSupportedVersionMetric(DbtMetric):

name: str = "dbt_supported_version"
description: str = "Whether dbt version meets minimum requirement"
unit: str = "boolean"
unit: str = Unit.BOOLEAN

min_version: str

Expand All @@ -34,12 +34,11 @@ def calculate(self, context: Context, measurements: Measurements) -> Measurement

supported = major_version == min_major and minor_version >= min_minor

value = 1 if supported else 0
diagnostic = ""
if not supported:
diagnostic = (
f"dbt version {version} does not meet minimum requirement of {self.min_version}. "
f"Please upgrade dbt to version {self.min_version} or later."
)
logger.info(f"dbt version {version} supported: {bool(value)}")
return self.measure(value=value, diagnostic=diagnostic)
logger.info(f"dbt version {version} supported: {supported}")
return self.measure(value=supported, diagnostic=diagnostic)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging

from checkup.measurement import Measurement, Measurements
from checkup.metric import Metric
from checkup.metric import Metric, Unit
from checkup.types import Context
from checkup_dbt.metrics.base import DbtMetric
from checkup_dbt.metrics.core.columns import DbtColumnsMetric
Expand All @@ -20,7 +20,7 @@ class DbtColumnTestCoverageMetric(DbtMetric):

name: str = "dbt_column_test_coverage"
description: str = "Percentage of columns with at least one test"
unit: str = "percent"
unit: str = Unit.PERCENT

@classmethod
def depends_on(cls) -> list[type[Metric]]:
Expand Down
2 changes: 1 addition & 1 deletion plugins/checkup-dbt/tests/test_quality_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def test_supported_version_metric(sample_manifest_path: Path):
m for m in result.measurements if m.metric.name == "dbt_supported_version"
)
assert measurement.metric.unit == "boolean"
assert measurement.value == 1
assert measurement.value is True


def test_supported_version_metric_requires_min_version():
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from checkup.measurement import Measurement, Measurements
from checkup.metric import Metric
from checkup.metric import Metric, Unit
from checkup.types import Context
from checkup_python.metrics.utils import parse_semantic_version
from checkup_python.metrics.version import PythonVersionMetric
Expand All @@ -13,7 +13,7 @@ class PythonVersionCheckMetric(Metric):

name: str = "python_version_check"
description: str = "The Python version adheres to a minimum and maximum boundary"
unit: str = "bool"
unit: str = Unit.BOOLEAN

min_version: str
max_version: str
Expand Down
8 changes: 2 additions & 6 deletions src/checkup/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
SQLAlchemyMaterializer,
)
from checkup.measurement import Measurement, Measurements
from checkup.metric import ExecutorType, Metric
from checkup.metric import ExecutorType, Metric, Unit
from checkup.provider import Provider
from checkup.providers.tags import TagProvider
from checkup.types import Context
Expand All @@ -25,30 +25,26 @@
Measurement.model_rebuild()

__all__ = [
# Core
"CheckHub",
"MeasurementResult",
"Metric",
"Measurement",
"Measurements",
"ExecutorType",
"Unit",
"Provider",
"TagProvider",
"Context",
# Executors
"ProviderExecutor",
"MetricCalculator",
# Materializers
"Materializer",
"ConsoleMaterializer",
"CSVMaterializer",
"HTMLMaterializer",
"SQLAlchemyMaterializer",
# Exceptions
"ProviderError",
"MetricPicklingError",
"DuplicateMetricNameError",
# Utilities
"suppress_subprocess_output",
]

Expand Down
4 changes: 2 additions & 2 deletions src/checkup/cli/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from rich.console import Console

from checkup.cli.utils import parse_cli_item
from checkup.configuration import CheckupConfig
from checkup.hub import CheckHub
from checkup.materializers import ConsoleMaterializer
Expand Down Expand Up @@ -170,8 +171,7 @@ def _resolve_materializer(
"""

if override:
mat_type = override
mat_config = {}
mat_type, mat_config = parse_cli_item(override)
elif config.materializer:
mat_type = config.materializer.type
mat_config = config.materializer.config
Expand Down
10 changes: 5 additions & 5 deletions src/checkup/materializers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
"""Materializers for outputting measurements."""

from checkup.materializers.base import (
Materializer,
group_measurements_by_tags,
group_measurements_hierarchical,
)
from checkup.materializers.base import Materializer
from checkup.materializers.console import ConsoleMaterializer
from checkup.materializers.csv_file import CSVMaterializer
from checkup.materializers.database import SQLAlchemyMaterializer
from checkup.materializers.html_report import HTMLMaterializer
from checkup.materializers.markdown import MarkdownMaterializer
from checkup.materializers.utils import (
group_measurements_by_tags,
group_measurements_hierarchical,
)

__all__ = [
"ConsoleMaterializer",
Expand Down
Loading
Loading