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 snapshotmetrics.csv- Flat format for analysishistory/- 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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3ee5f447bfff99036515eb7a6479200bc2fd5b3026dcd3cf463c43b719673a9e
|
|
| MD5 |
eeed059ab32dca34b87846ef3db8eeae
|
|
| BLAKE2b-256 |
327f7eb8855b65635e7295190a047814b02b4a4eefec01351ee40af99b6ea224
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8f16f7c4b84c0bd981b417b2466486a16daf711bb2edeefeb91f9078fba591a4
|
|
| MD5 |
934b0ea934614b6f62e25830763f0f0e
|
|
| BLAKE2b-256 |
8454c245d77e2b93fafa2cb77363560c37d66605a2a3791eacd077821f00798d
|