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.1.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.1-py3-none-any.whl (33.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: umpyre-0.1.1.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.1.tar.gz
Algorithm Hash digest
SHA256 5c4bbd86b971ee92561180bc5fa4185943b2e12a8b51767f60ca0e9f9d6210f8
MD5 f74675d58178dd2e4ac45c1342266a35
BLAKE2b-256 fb625c84e39ac236da9ff227168d07e2b6362cf026b718179302ea74fd7f65b9

See more details on using hashes here.

File details

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

File metadata

  • Download URL: umpyre-0.1.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 cc521a54cd13cfcf57c3b059f8611ba1adb5c2abd880c11f3dc242b7313567d3
MD5 ecd792847cc4b1db501169d9a329b8a7
BLAKE2b-256 6b0765b7e5b79d83d33204446a4a0098d9ec0afba8e458a6ea588c899547197c

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