Skip to main content

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

Metadata

Release files for umpyre 0.1.10

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for umpyre 0.1.10
File Size Uploaded
umpyre-0.1.10.tar.gz 63.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for umpyre 0.1.10
File Interpreter ABI Platform
umpyre-0.1.10-py3-none-any.whl Python 3 none any Details

Total release size: 97.6 kB

Release files / umpyre-0.1.10.tar.gz

Download URL umpyre-0.1.10.tar.gz
Size 63.2 kB
Tags Source
SHA-256 checksum
How to use checksums
d19ec8385c4e2491aac7ddefc4d2652617dfb1813b7ccd0f5ae17694cba58471
BLAKE2b-256 checksum
How to use checksums
47359f0bcdcf44d10ce85b672eefeda5328ee3ec278523d3654ec16c5b73e186
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / umpyre-0.1.10-py3-none-any.whl

Download URL umpyre-0.1.10-py3-none-any.whl
Size 34.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
627a75f295868bd60e21b849600a5d8077614e108fcaa6f4863e749d2760040b
BLAKE2b-256 checksum
How to use checksums
9d11135dbc104bb7e2ae3892b0d14b43efaa5489033c2054ca0a74d9d54daaeb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.1.12

2 release files

0.1.11

2 release files

This release

0.1.10 This release

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page