Skip to main content

Code analysis and quality metrics tracking system for CI/CD

Project description

umpyre

Code analysis and quality metrics tracking system for CI/CD pipelines.

Overview

umpyre provides automated code metrics collection and tracking for Python projects, designed to integrate seamlessly with GitHub Actions CI/CD pipelines. Track code quality trends over time with minimal overhead.

Key Features:

  • 🎯 Pluggable collectors: Workflow status, complexity (wily), coverage, code statistics
  • 📊 Git-based storage: Metrics stored in separate branch, no external dependencies
  • ⚙️ Config-driven: Customize via YAML configuration
  • 🚀 Fast & lightweight: Limited history tracking for speed
  • 🔌 GitHub Action: Drop-in integration for existing workflows

Installation

pip install umpyre

Quick Start

1. Create Configuration

Create .github/umpyre-config.yml:

schema_version: "1.0"

collectors:
  workflow_status:
    enabled: true
    lookback_runs: 10
  
  coverage:
    enabled: true
    source: pytest-cov
  
  umpyre_stats:
    enabled: true
    exclude_dirs: [tests, examples, scrap]

storage:
  branch: code-metrics
  formats: [json, csv]

2. Add to GitHub Actions

In your .github/workflows/ci.yml (after successful PyPI publish):

- name: Track Code Metrics
  if: success()  # Only track metrics after successful publish
  uses: i2mint/umpyre/actions/track-metrics@master
  continue-on-error: true  # Never fails CI - see FAILURE_PROTECTION.md
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}
    config-path: .github/umpyre-config.yml  # Optional: defaults to this path

Important: Metrics collection has triple-layer failure protection and will never break your CI pipeline. See FAILURE_PROTECTION.md for details.

3. View Metrics

Metrics are stored in the code-metrics branch:

  • metrics.json - Latest snapshot
  • metrics.csv - Flat format for analysis
  • history/ - Flat historical records (filename format: YYYY_MM_DD_HH_MM_SS__commit__version.json)

See STORAGE_STRUCTURE.md for full details on storage design and querying.

CLI Usage

# Collect and store metrics
python -m umpyre.cli collect

# Collect with custom config
python -m umpyre.cli collect --config my-config.yml

# Dry run (don't store)
python -m umpyre.cli collect --no-store

# Validate against thresholds (coming soon)
python -m umpyre.cli validate

Querying Stored Metrics

Metrics are stored in a flat structure with parseable filenames: YYYY_MM_DD_HH_MM_SS__shahash__version.json

Shell Queries

# Switch to metrics branch
git checkout code-metrics

# Get all metrics from November 14
ls history/2025_11_14_*

# Find metrics for specific commit
ls history/*__700e012__*

# Find all v0.1.0 metrics
ls history/*__0.1.0.json

# Get latest 10 metrics
ls -t history/ | head -10

# Exclude metrics without version
ls history/ | grep -v "__none.json"

Python Queries

from pathlib import Path
from umpyre.storage import (
    parse_metric_filename,
    find_metrics_by_commit,
    find_metrics_by_version,
    get_latest_metric_for_version,
    get_all_versions,
)

history_dir = Path("history")

# Parse filename
info = parse_metric_filename("2025_11_14_22_45_00__700e012__0.1.0.json")
print(info['commit_sha'])    # '700e012'
print(info['pypi_version'])  # '0.1.0'
print(info['timestamp'])     # datetime object

# Find by commit
metrics = find_metrics_by_commit(history_dir, "700e012")

# Find all metrics for a version
all_v0_1_0 = find_metrics_by_version(history_dir, "0.1.0")

# Get latest metric for a version
latest = get_latest_metric_for_version(history_dir, "0.1.0")

# List all versions
versions = get_all_versions(history_dir)
print(versions)  # ['0.1.0', '0.1.1', '0.2.0']

See STORAGE_STRUCTURE.md for detailed storage design documentation.

Available Collectors

WorkflowStatusCollector

Tracks GitHub CI/CD health via API:

  • Last run status (success/failure)
  • Recent failure count
  • Last successful run timestamp

CoverageCollector

Extracts test coverage from pytest-cov or coverage.py:

  • Line coverage %
  • Branch coverage %
  • Supports JSON and XML formats

WilyCollector

Complexity metrics using wily (requires installation):

  • Cyclomatic complexity
  • Maintainability index
  • Limited to recent commits for speed

UmpyreCollector

Code statistics using built-in analyzer:

  • Function/class counts
  • Line metrics (total, empty, comments, docs)
  • Code ratios and averages

Configuration Reference

See .github/umpyre-config.yml for full options:

schema_version: "1.0"  # Required

collectors:
  workflow_status:
    enabled: true
    lookback_runs: 10  # Number of recent runs to analyze
  
  wily:
    enabled: true
    max_revisions: 5  # Limit for performance
    operators: [cyclomatic, maintainability]
  
  coverage:
    enabled: true
    source: pytest-cov  # or 'coverage'
  
  umpyre_stats:
    enabled: true
    exclude_dirs: [tests, examples, scrap]

storage:
  branch: code-metrics  # Branch name for metrics
  formats: [json, csv]  # Output formats
  retention:
    strategy: all  # or: last_n_days, last_n_commits

visualization:  # Coming in Phase 2
  generate_plots: true
  generate_readme: true
  plot_metrics: [maintainability, coverage, loc]

thresholds:  # Coming in Phase 3
  enabled: false

aggregation:  # Coming in Phase 2
  enabled: false

Architecture

umpyre/
├── collectors/          # Metric collectors (pluggable)
│   ├── base.py         # Abstract Collector with Mapping interface
│   ├── workflow_status.py
│   ├── wily_collector.py
│   ├── coverage_collector.py
│   └── umpyre_collector.py
├── storage/            # Persistence layer
│   ├── git_branch.py  # Git-based storage
│   └── formats.py     # JSON/CSV serialization
├── config.py           # YAML config loading
├── schema.py           # Versioned metric schema
└── cli.py              # Command-line interface

Metric Schema (v1.0)

{
  "schema_version": "1.0",
  "timestamp": "2025-01-15T10:30:00Z",
  "commit_sha": "abc123...",
  "commit_message": "Fix bug in parser",
  "python_version": "3.10",
  "workflow_status": {
    "last_run_status": "success",
    "recent_failure_count": 0
  },
  "metrics": {
    "complexity": {
      "cyclomatic_avg": 3.2,
      "maintainability_index": 75.3
    },
    "coverage": {
      "line_coverage": 87.5,
      "branch_coverage": 82.1
    },
    "code_stats": {
      "num_functions": 342,
      "num_classes": 28
    }
  },
  "collection_duration_seconds": 12.3
}

Roadmap

Phase 1 (✅ Complete): Core tracking system

  • Config-driven collectors
  • Git branch storage
  • CLI and GitHub Action

Phase 2 (Planned): Visualization & Aggregation

  • Plot generation (matplotlib/plotly)
  • Auto-generated README with charts
  • Cross-repository aggregation
  • Organization-wide dashboards

Phase 3 (Planned): Advanced Features

  • Security metrics (bandit)
  • Docstring coverage (interrogate)
  • Threshold validation with custom validators
  • Data pruning and compression
  • Schema migration utilities

Contributing

Contributions welcome! See misc/CHANGELOG.md for recent changes.

Original Code Statistics Feature

Get stats about packages (existing functionality preserved):

from umpyre import modules_info_df, stats_of
import collections

# Analyze a single package
modules_info_df(collections)

# Compare multiple packages
stats_of(['urllib', 'json', 'collections'])

See original README examples above for detailed usage.

License

Apache-2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

umpyre-0.1.2.tar.gz (59.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

umpyre-0.1.2-py3-none-any.whl (33.1 kB view details)

Uploaded Python 3

File details

Details for the file umpyre-0.1.2.tar.gz.

File metadata

  • Download URL: umpyre-0.1.2.tar.gz
  • Upload date:
  • Size: 59.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for umpyre-0.1.2.tar.gz
Algorithm Hash digest
SHA256 3ee5f447bfff99036515eb7a6479200bc2fd5b3026dcd3cf463c43b719673a9e
MD5 eeed059ab32dca34b87846ef3db8eeae
BLAKE2b-256 327f7eb8855b65635e7295190a047814b02b4a4eefec01351ee40af99b6ea224

See more details on using hashes here.

File details

Details for the file umpyre-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: umpyre-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 33.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for umpyre-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 8f16f7c4b84c0bd981b417b2466486a16daf711bb2edeefeb91f9078fba591a4
MD5 934b0ea934614b6f62e25830763f0f0e
BLAKE2b-256 8454c245d77e2b93fafa2cb77363560c37d66605a2a3791eacd077821f00798d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page