repofail 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- repofail-0.1.2/.github/workflows/publish.yml +26 -0
- repofail-0.1.2/.github/workflows/repofail.yml +63 -0
- repofail-0.1.2/.gitignore +8 -0
- repofail-0.1.2/CONTRIBUTING.md +17 -0
- repofail-0.1.2/PKG-INFO +244 -0
- repofail-0.1.2/README.md +231 -0
- repofail-0.1.2/RULES.md +95 -0
- repofail-0.1.2/contract.json +9 -0
- repofail-0.1.2/docs/assets/demo-autogpt.png +0 -0
- repofail-0.1.2/docs/assets/repofail-logo.png +0 -0
- repofail-0.1.2/docs/logo.png +0 -0
- repofail-0.1.2/docs/screenshots/high_failure.png +0 -0
- repofail-0.1.2/pyproject.toml +25 -0
- repofail-0.1.2/repofail/__init__.py +3 -0
- repofail-0.1.2/repofail/cli.py +401 -0
- repofail-0.1.2/repofail/contract.py +121 -0
- repofail-0.1.2/repofail/engine.py +68 -0
- repofail-0.1.2/repofail/fleet.py +116 -0
- repofail-0.1.2/repofail/format.py +306 -0
- repofail-0.1.2/repofail/models.py +75 -0
- repofail-0.1.2/repofail/risk.py +97 -0
- repofail-0.1.2/repofail/rules/__init__.py +5 -0
- repofail-0.1.2/repofail/rules/abi_wheel_mismatch.py +80 -0
- repofail-0.1.2/repofail/rules/apple_silicon.py +95 -0
- repofail-0.1.2/repofail/rules/base.py +35 -0
- repofail-0.1.2/repofail/rules/docker_only.py +37 -0
- repofail-0.1.2/repofail/rules/gpu_memory.py +31 -0
- repofail-0.1.2/repofail/rules/info_signals.py +142 -0
- repofail-0.1.2/repofail/rules/lock_file_missing.py +28 -0
- repofail-0.1.2/repofail/rules/ml_niche.py +96 -0
- repofail-0.1.2/repofail/rules/native_toolchain.py +53 -0
- repofail-0.1.2/repofail/rules/node_engine.py +80 -0
- repofail-0.1.2/repofail/rules/node_eol.py +50 -0
- repofail-0.1.2/repofail/rules/node_windows.py +21 -0
- repofail-0.1.2/repofail/rules/port_collision.py +28 -0
- repofail-0.1.2/repofail/rules/python_eol.py +52 -0
- repofail-0.1.2/repofail/rules/python_version.py +75 -0
- repofail-0.1.2/repofail/rules/registry.py +167 -0
- repofail-0.1.2/repofail/rules/spec_drift.py +82 -0
- repofail-0.1.2/repofail/rules/system_libs.py +24 -0
- repofail-0.1.2/repofail/rules/torch_cuda.py +73 -0
- repofail-0.1.2/repofail/rules/yaml_loader.py +90 -0
- repofail-0.1.2/repofail/scanner/__init__.py +6 -0
- repofail-0.1.2/repofail/scanner/ast_scan.py +208 -0
- repofail-0.1.2/repofail/scanner/host.py +156 -0
- repofail-0.1.2/repofail/scanner/parsers.py +384 -0
- repofail-0.1.2/repofail/scanner/repo.py +298 -0
- repofail-0.1.2/repofail/telemetry.py +93 -0
- repofail-0.1.2/tests/__init__.py +0 -0
- repofail-0.1.2/tests/test_cli_stage2.py +37 -0
- repofail-0.1.2/tests/test_contract.py +71 -0
- repofail-0.1.2/tests/test_fleet.py +61 -0
- repofail-0.1.2/tests/test_integration.py +44 -0
- repofail-0.1.2/tests/test_ml_rules.py +99 -0
- repofail-0.1.2/tests/test_rules.py +249 -0
- repofail-0.1.2/tests/test_scanner.py +97 -0
- repofail-0.1.2/tests/test_telemetry.py +52 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
environment: pypi
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.12"
|
|
21
|
+
|
|
22
|
+
- run: pip install build
|
|
23
|
+
|
|
24
|
+
- run: python -m build
|
|
25
|
+
|
|
26
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# repofail — CI guardrail for runtime compatibility
|
|
2
|
+
#
|
|
3
|
+
# In this repo: checks repofail itself.
|
|
4
|
+
# To use in your repo: copy this file, change install step to:
|
|
5
|
+
# pip install git+https://github.com/youruser/repofail.git
|
|
6
|
+
# # or: pip install repofail (when on PyPI)
|
|
7
|
+
|
|
8
|
+
name: repofail
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
push:
|
|
12
|
+
branches: [main, master]
|
|
13
|
+
pull_request:
|
|
14
|
+
branches: [main, master]
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
check:
|
|
18
|
+
strategy:
|
|
19
|
+
fail-fast: false
|
|
20
|
+
matrix:
|
|
21
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
22
|
+
python: ["3.10", "3.11", "3.12"]
|
|
23
|
+
exclude:
|
|
24
|
+
# Trim matrix: 3.11 on each OS is enough for quick CI
|
|
25
|
+
- os: ubuntu-latest
|
|
26
|
+
python: "3.10"
|
|
27
|
+
- os: ubuntu-latest
|
|
28
|
+
python: "3.12"
|
|
29
|
+
- os: macos-latest
|
|
30
|
+
python: "3.10"
|
|
31
|
+
- os: macos-latest
|
|
32
|
+
python: "3.12"
|
|
33
|
+
- os: windows-latest
|
|
34
|
+
python: "3.10"
|
|
35
|
+
- os: windows-latest
|
|
36
|
+
python: "3.12"
|
|
37
|
+
runs-on: ${{ matrix.os }}
|
|
38
|
+
env:
|
|
39
|
+
PYTHONUTF8: 1
|
|
40
|
+
steps:
|
|
41
|
+
- uses: actions/checkout@v4
|
|
42
|
+
|
|
43
|
+
- name: Set up Python
|
|
44
|
+
uses: actions/setup-python@v5
|
|
45
|
+
with:
|
|
46
|
+
python-version: ${{ matrix.python }}
|
|
47
|
+
|
|
48
|
+
- name: Install repofail
|
|
49
|
+
run: pip install -e .
|
|
50
|
+
|
|
51
|
+
- name: Run repofail
|
|
52
|
+
run: repofail --ci
|
|
53
|
+
|
|
54
|
+
- name: Test all commands
|
|
55
|
+
run: |
|
|
56
|
+
repofail
|
|
57
|
+
repofail -j
|
|
58
|
+
repofail gen .
|
|
59
|
+
repofail s
|
|
60
|
+
repofail a .
|
|
61
|
+
|
|
62
|
+
- name: Run tests
|
|
63
|
+
run: pip install pytest && pytest tests/ -v
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
repofail is opinionated and deterministic.
|
|
4
|
+
|
|
5
|
+
We welcome:
|
|
6
|
+
|
|
7
|
+
- New deterministic rules
|
|
8
|
+
- Improvements to host inspection
|
|
9
|
+
- Clearer error evidence
|
|
10
|
+
- Performance improvements
|
|
11
|
+
|
|
12
|
+
We do NOT accept:
|
|
13
|
+
|
|
14
|
+
- Heuristic guesses
|
|
15
|
+
- AI-based predictions
|
|
16
|
+
- Cloud integrations
|
|
17
|
+
- Non-deterministic scoring
|
repofail-0.1.2/PKG-INFO
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: repofail
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Predict why a repository will fail on your machine before you run it.
|
|
5
|
+
Author: Jayanth
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Requires-Dist: pyyaml>=6.0
|
|
8
|
+
Requires-Dist: tomli>=2.0; python_version < '3.11'
|
|
9
|
+
Requires-Dist: typer>=0.9.0
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
<p align="center">
|
|
15
|
+
<img src="docs/logo.png" width="180" alt="repofail logo">
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<h1 align="center">repofail</h1>
|
|
19
|
+
|
|
20
|
+
<p align="center">
|
|
21
|
+
Deterministic runtime compatibility analyzer
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
<p align="center">
|
|
25
|
+
<a href="https://pypi.org/project/repofail/"><img src="https://img.shields.io/pypi/v/repofail"></a>
|
|
26
|
+
<img src="https://img.shields.io/badge/ci-passing-brightgreen">
|
|
27
|
+
<img src="https://img.shields.io/badge/python-3.10+-blue">
|
|
28
|
+
<img src="https://img.shields.io/badge/runtime-validated-success">
|
|
29
|
+
<img src="https://img.shields.io/badge/rules-20+-informational">
|
|
30
|
+
</p>
|
|
31
|
+
|
|
32
|
+
<p align="center">
|
|
33
|
+
Predict why a repository will fail on your machine before you run it.
|
|
34
|
+
</p>
|
|
35
|
+
|
|
36
|
+
<p align="center">
|
|
37
|
+
<em>repofail answers one question: <strong>Will this repository actually run here?</strong><br>
|
|
38
|
+
It inspects both the repo and your machine — then reports deterministic incompatibilities before you install anything.</em>
|
|
39
|
+
</p>
|
|
40
|
+
|
|
41
|
+
<p align="center">
|
|
42
|
+
<a href="#why-this-exists">Why</a> ·
|
|
43
|
+
<a href="#example-output">Example</a> ·
|
|
44
|
+
<a href="#works-on">Works on</a> ·
|
|
45
|
+
<a href="#install">Install</a> ·
|
|
46
|
+
<a href="#usage">Usage</a> ·
|
|
47
|
+
<a href="#rules">Rules</a> ·
|
|
48
|
+
<a href="#ci-integration">CI</a> ·
|
|
49
|
+
<a href="#contracts">Contracts</a>
|
|
50
|
+
</p>
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Why This Exists
|
|
55
|
+
|
|
56
|
+
Most tools install dependencies.
|
|
57
|
+
|
|
58
|
+
Few tools tell you:
|
|
59
|
+
|
|
60
|
+
- Your Node version violates `engines.node`.
|
|
61
|
+
- Docker targets the wrong architecture.
|
|
62
|
+
- CUDA is hard-coded with no fallback.
|
|
63
|
+
- CI and local Python versions drifted.
|
|
64
|
+
|
|
65
|
+
repofail inspects both the repository and your machine — then reports deterministic incompatibilities before install or runtime.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Works on
|
|
70
|
+
|
|
71
|
+
repofail works on:
|
|
72
|
+
|
|
73
|
+
- Python projects
|
|
74
|
+
- Node projects
|
|
75
|
+
- Dockerized repos
|
|
76
|
+
- ML repositories
|
|
77
|
+
- Monorepos
|
|
78
|
+
|
|
79
|
+
Run it against any local clone.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Example output
|
|
84
|
+
|
|
85
|
+
<p align="center">
|
|
86
|
+
<img src="docs/screenshots/high_failure.png" width="850" alt="repofail output">
|
|
87
|
+
</p>
|
|
88
|
+
|
|
89
|
+
repofail surfaces deterministic failures before install or runtime. No heuristics. No AI guesses. Evidence only.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Install
|
|
94
|
+
|
|
95
|
+
**From PyPI (recommended)**
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
pip install repofail
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Or with pipx (isolated CLI install):
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
pipx install repofail
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**From source (development)**
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
git clone https://github.com/jayvenn21/repofail.git
|
|
111
|
+
cd repofail
|
|
112
|
+
pip install -e .
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Usage
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# Scan
|
|
119
|
+
repofail # Scan current dir
|
|
120
|
+
repofail -p /path/to/repo # Scan specific repo
|
|
121
|
+
repofail -j # JSON output (machine-readable)
|
|
122
|
+
repofail -m # Markdown output
|
|
123
|
+
repofail -v # Verbose: rule IDs and low-confidence hints
|
|
124
|
+
repofail --ci # CI mode: exit 1 if HIGH rules fire
|
|
125
|
+
repofail --fail-on MEDIUM # CI: fail on MEDIUM or higher (default: HIGH)
|
|
126
|
+
repofail -r # Save failure report when rules fire (opt-in telemetry)
|
|
127
|
+
|
|
128
|
+
# Rules
|
|
129
|
+
repofail -e list # List all rules
|
|
130
|
+
repofail -e spec_drift # Explain a rule
|
|
131
|
+
|
|
132
|
+
# Contracts
|
|
133
|
+
repofail gen . # Generate env contract to stdout
|
|
134
|
+
repofail gen . -o contract.json
|
|
135
|
+
repofail check contract.json
|
|
136
|
+
|
|
137
|
+
# Fleet
|
|
138
|
+
repofail a /path # Audit: scan all repos in directory
|
|
139
|
+
repofail a /path -j # Audit with JSON output
|
|
140
|
+
repofail sim . -H host.json # Simulate: would this work on target host?
|
|
141
|
+
repofail s # Stats: local failure counts (from -r reports)
|
|
142
|
+
repofail s -j # Stats with JSON output
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## CI integration
|
|
148
|
+
|
|
149
|
+
```yaml
|
|
150
|
+
- uses: actions/checkout@v4
|
|
151
|
+
- uses: actions/setup-python@v5
|
|
152
|
+
with:
|
|
153
|
+
python-version: "3.12"
|
|
154
|
+
- run: pip install repofail
|
|
155
|
+
- run: repofail --ci
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Exits 1 if HIGH rules fire. Use `--fail-on MEDIUM` to be stricter.
|
|
159
|
+
|
|
160
|
+
## Contracts
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
repofail gen . -o contract.json
|
|
164
|
+
repofail check contract.json
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Versioned runtime expectations. Teams share contracts. CI checks drift.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Rules
|
|
172
|
+
|
|
173
|
+
| Tool | Reads Repo | Inspects Host | Predicts Failure | CI Enforceable |
|
|
174
|
+
|------|------------|---------------|------------------|----------------|
|
|
175
|
+
| pip | ✅ | ❌ | ❌ | ❌ |
|
|
176
|
+
| Docker | ✅ | ❌ | ❌ | ❌ |
|
|
177
|
+
| **repofail** | ✅ | ✅ | ✅ | ✅ |
|
|
178
|
+
|
|
179
|
+
**Deterministic rule coverage** — repofail includes checks across:
|
|
180
|
+
|
|
181
|
+
- **Spec violations** — version ranges, engines.node, requires-python
|
|
182
|
+
- **Architecture mismatches** — Apple Silicon vs amd64 Docker
|
|
183
|
+
- **Hardware constraints** — CUDA requirements, GPU memory
|
|
184
|
+
- **Toolchain gaps** — missing compilers, Rust, node-gyp
|
|
185
|
+
- **Runtime drift** — CI vs Docker vs local inconsistencies
|
|
186
|
+
- **Environment shape** — multi-service RAM pressure, port collisions
|
|
187
|
+
|
|
188
|
+
See all rules: `repofail -e list` · Explain one: `repofail -e <rule_id>`
|
|
189
|
+
|
|
190
|
+
<details>
|
|
191
|
+
<summary>Rule reference</summary>
|
|
192
|
+
|
|
193
|
+
| Rule | Severity | When |
|
|
194
|
+
|------|----------|------|
|
|
195
|
+
| Torch CUDA mismatch | HIGH | Hard-coded CUDA, host has no GPU |
|
|
196
|
+
| Python version violation | HIGH | Host outside `requires-python` range |
|
|
197
|
+
| Spec drift | HIGH | pyproject vs Docker vs CI — inconsistent Python |
|
|
198
|
+
| Node engine mismatch | HIGH | package.json engines.node vs host |
|
|
199
|
+
| Lock file missing | HIGH | package.json has deps, no lock file |
|
|
200
|
+
| Apple Silicon wheel mismatch | MEDIUM/HIGH | arm64 + x86-only packages or Docker amd64 |
|
|
201
|
+
| … | | `repofail -e list` |
|
|
202
|
+
|
|
203
|
+
</details>
|
|
204
|
+
|
|
205
|
+
<details>
|
|
206
|
+
<summary>Scoring model</summary>
|
|
207
|
+
|
|
208
|
+
**Compatibility Score** = `100 − Σ(weight × confidence × determinism)`
|
|
209
|
+
|
|
210
|
+
| Severity | Weight | Determinism |
|
|
211
|
+
|----------|--------|-------------|
|
|
212
|
+
| HIGH | 45 | 1.0 for spec violations |
|
|
213
|
+
| MEDIUM | 20 | 0.8–1.0 |
|
|
214
|
+
| LOW | 7 | 0.5–1.0 |
|
|
215
|
+
| INFO | 5 | structural only |
|
|
216
|
+
|
|
217
|
+
**Determinism scale:** `1.0` = guaranteed failure · `0.75` = high likelihood · `0.6` = probabilistic (spec drift) · `0.5` = structural risk
|
|
218
|
+
|
|
219
|
+
Score floors at 10%. When score ≤15% with HIGH rules: "— fatal deterministic violations present".
|
|
220
|
+
|
|
221
|
+
</details>
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Architecture
|
|
226
|
+
|
|
227
|
+
```
|
|
228
|
+
repofail/
|
|
229
|
+
cli.py
|
|
230
|
+
engine.py
|
|
231
|
+
scanner/ # Repo + host inspection
|
|
232
|
+
rules/ # Deterministic rule implementations
|
|
233
|
+
fleet.py # Audit, simulate
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Extensible via `.repofail/rules.yaml`.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Testing
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
pytest tests/ -v
|
|
244
|
+
```
|
repofail-0.1.2/README.md
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/logo.png" width="180" alt="repofail logo">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">repofail</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
Deterministic runtime compatibility analyzer
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://pypi.org/project/repofail/"><img src="https://img.shields.io/pypi/v/repofail"></a>
|
|
13
|
+
<img src="https://img.shields.io/badge/ci-passing-brightgreen">
|
|
14
|
+
<img src="https://img.shields.io/badge/python-3.10+-blue">
|
|
15
|
+
<img src="https://img.shields.io/badge/runtime-validated-success">
|
|
16
|
+
<img src="https://img.shields.io/badge/rules-20+-informational">
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
Predict why a repository will fail on your machine before you run it.
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
<p align="center">
|
|
24
|
+
<em>repofail answers one question: <strong>Will this repository actually run here?</strong><br>
|
|
25
|
+
It inspects both the repo and your machine — then reports deterministic incompatibilities before you install anything.</em>
|
|
26
|
+
</p>
|
|
27
|
+
|
|
28
|
+
<p align="center">
|
|
29
|
+
<a href="#why-this-exists">Why</a> ·
|
|
30
|
+
<a href="#example-output">Example</a> ·
|
|
31
|
+
<a href="#works-on">Works on</a> ·
|
|
32
|
+
<a href="#install">Install</a> ·
|
|
33
|
+
<a href="#usage">Usage</a> ·
|
|
34
|
+
<a href="#rules">Rules</a> ·
|
|
35
|
+
<a href="#ci-integration">CI</a> ·
|
|
36
|
+
<a href="#contracts">Contracts</a>
|
|
37
|
+
</p>
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Why This Exists
|
|
42
|
+
|
|
43
|
+
Most tools install dependencies.
|
|
44
|
+
|
|
45
|
+
Few tools tell you:
|
|
46
|
+
|
|
47
|
+
- Your Node version violates `engines.node`.
|
|
48
|
+
- Docker targets the wrong architecture.
|
|
49
|
+
- CUDA is hard-coded with no fallback.
|
|
50
|
+
- CI and local Python versions drifted.
|
|
51
|
+
|
|
52
|
+
repofail inspects both the repository and your machine — then reports deterministic incompatibilities before install or runtime.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Works on
|
|
57
|
+
|
|
58
|
+
repofail works on:
|
|
59
|
+
|
|
60
|
+
- Python projects
|
|
61
|
+
- Node projects
|
|
62
|
+
- Dockerized repos
|
|
63
|
+
- ML repositories
|
|
64
|
+
- Monorepos
|
|
65
|
+
|
|
66
|
+
Run it against any local clone.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Example output
|
|
71
|
+
|
|
72
|
+
<p align="center">
|
|
73
|
+
<img src="docs/screenshots/high_failure.png" width="850" alt="repofail output">
|
|
74
|
+
</p>
|
|
75
|
+
|
|
76
|
+
repofail surfaces deterministic failures before install or runtime. No heuristics. No AI guesses. Evidence only.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Install
|
|
81
|
+
|
|
82
|
+
**From PyPI (recommended)**
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pip install repofail
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Or with pipx (isolated CLI install):
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
pipx install repofail
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**From source (development)**
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
git clone https://github.com/jayvenn21/repofail.git
|
|
98
|
+
cd repofail
|
|
99
|
+
pip install -e .
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Usage
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# Scan
|
|
106
|
+
repofail # Scan current dir
|
|
107
|
+
repofail -p /path/to/repo # Scan specific repo
|
|
108
|
+
repofail -j # JSON output (machine-readable)
|
|
109
|
+
repofail -m # Markdown output
|
|
110
|
+
repofail -v # Verbose: rule IDs and low-confidence hints
|
|
111
|
+
repofail --ci # CI mode: exit 1 if HIGH rules fire
|
|
112
|
+
repofail --fail-on MEDIUM # CI: fail on MEDIUM or higher (default: HIGH)
|
|
113
|
+
repofail -r # Save failure report when rules fire (opt-in telemetry)
|
|
114
|
+
|
|
115
|
+
# Rules
|
|
116
|
+
repofail -e list # List all rules
|
|
117
|
+
repofail -e spec_drift # Explain a rule
|
|
118
|
+
|
|
119
|
+
# Contracts
|
|
120
|
+
repofail gen . # Generate env contract to stdout
|
|
121
|
+
repofail gen . -o contract.json
|
|
122
|
+
repofail check contract.json
|
|
123
|
+
|
|
124
|
+
# Fleet
|
|
125
|
+
repofail a /path # Audit: scan all repos in directory
|
|
126
|
+
repofail a /path -j # Audit with JSON output
|
|
127
|
+
repofail sim . -H host.json # Simulate: would this work on target host?
|
|
128
|
+
repofail s # Stats: local failure counts (from -r reports)
|
|
129
|
+
repofail s -j # Stats with JSON output
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## CI integration
|
|
135
|
+
|
|
136
|
+
```yaml
|
|
137
|
+
- uses: actions/checkout@v4
|
|
138
|
+
- uses: actions/setup-python@v5
|
|
139
|
+
with:
|
|
140
|
+
python-version: "3.12"
|
|
141
|
+
- run: pip install repofail
|
|
142
|
+
- run: repofail --ci
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Exits 1 if HIGH rules fire. Use `--fail-on MEDIUM` to be stricter.
|
|
146
|
+
|
|
147
|
+
## Contracts
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
repofail gen . -o contract.json
|
|
151
|
+
repofail check contract.json
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Versioned runtime expectations. Teams share contracts. CI checks drift.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Rules
|
|
159
|
+
|
|
160
|
+
| Tool | Reads Repo | Inspects Host | Predicts Failure | CI Enforceable |
|
|
161
|
+
|------|------------|---------------|------------------|----------------|
|
|
162
|
+
| pip | ✅ | ❌ | ❌ | ❌ |
|
|
163
|
+
| Docker | ✅ | ❌ | ❌ | ❌ |
|
|
164
|
+
| **repofail** | ✅ | ✅ | ✅ | ✅ |
|
|
165
|
+
|
|
166
|
+
**Deterministic rule coverage** — repofail includes checks across:
|
|
167
|
+
|
|
168
|
+
- **Spec violations** — version ranges, engines.node, requires-python
|
|
169
|
+
- **Architecture mismatches** — Apple Silicon vs amd64 Docker
|
|
170
|
+
- **Hardware constraints** — CUDA requirements, GPU memory
|
|
171
|
+
- **Toolchain gaps** — missing compilers, Rust, node-gyp
|
|
172
|
+
- **Runtime drift** — CI vs Docker vs local inconsistencies
|
|
173
|
+
- **Environment shape** — multi-service RAM pressure, port collisions
|
|
174
|
+
|
|
175
|
+
See all rules: `repofail -e list` · Explain one: `repofail -e <rule_id>`
|
|
176
|
+
|
|
177
|
+
<details>
|
|
178
|
+
<summary>Rule reference</summary>
|
|
179
|
+
|
|
180
|
+
| Rule | Severity | When |
|
|
181
|
+
|------|----------|------|
|
|
182
|
+
| Torch CUDA mismatch | HIGH | Hard-coded CUDA, host has no GPU |
|
|
183
|
+
| Python version violation | HIGH | Host outside `requires-python` range |
|
|
184
|
+
| Spec drift | HIGH | pyproject vs Docker vs CI — inconsistent Python |
|
|
185
|
+
| Node engine mismatch | HIGH | package.json engines.node vs host |
|
|
186
|
+
| Lock file missing | HIGH | package.json has deps, no lock file |
|
|
187
|
+
| Apple Silicon wheel mismatch | MEDIUM/HIGH | arm64 + x86-only packages or Docker amd64 |
|
|
188
|
+
| … | | `repofail -e list` |
|
|
189
|
+
|
|
190
|
+
</details>
|
|
191
|
+
|
|
192
|
+
<details>
|
|
193
|
+
<summary>Scoring model</summary>
|
|
194
|
+
|
|
195
|
+
**Compatibility Score** = `100 − Σ(weight × confidence × determinism)`
|
|
196
|
+
|
|
197
|
+
| Severity | Weight | Determinism |
|
|
198
|
+
|----------|--------|-------------|
|
|
199
|
+
| HIGH | 45 | 1.0 for spec violations |
|
|
200
|
+
| MEDIUM | 20 | 0.8–1.0 |
|
|
201
|
+
| LOW | 7 | 0.5–1.0 |
|
|
202
|
+
| INFO | 5 | structural only |
|
|
203
|
+
|
|
204
|
+
**Determinism scale:** `1.0` = guaranteed failure · `0.75` = high likelihood · `0.6` = probabilistic (spec drift) · `0.5` = structural risk
|
|
205
|
+
|
|
206
|
+
Score floors at 10%. When score ≤15% with HIGH rules: "— fatal deterministic violations present".
|
|
207
|
+
|
|
208
|
+
</details>
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Architecture
|
|
213
|
+
|
|
214
|
+
```
|
|
215
|
+
repofail/
|
|
216
|
+
cli.py
|
|
217
|
+
engine.py
|
|
218
|
+
scanner/ # Repo + host inspection
|
|
219
|
+
rules/ # Deterministic rule implementations
|
|
220
|
+
fleet.py # Audit, simulate
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Extensible via `.repofail/rules.yaml`.
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Testing
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
pytest tests/ -v
|
|
231
|
+
```
|
repofail-0.1.2/RULES.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# repofail Rules
|
|
2
|
+
|
|
3
|
+
High-confidence incompatibility rules. Deterministic, no AI. Extensible via YAML.
|
|
4
|
+
|
|
5
|
+
## List rules
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
repofail --explain list
|
|
9
|
+
repofail --explain torch_cuda_mismatch
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## The rules
|
|
13
|
+
|
|
14
|
+
### 1. torch_cuda_mismatch (HIGH)
|
|
15
|
+
|
|
16
|
+
**When:** Repo imports `torch.cuda` or uses `device="cuda"` but host has no NVIDIA GPU.
|
|
17
|
+
|
|
18
|
+
**Fix:** Run on a machine with CUDA, or use CPU-only PyTorch.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
### 2. apple_silicon_wheels (MEDIUM/HIGH)
|
|
23
|
+
|
|
24
|
+
**When:** Host is macOS arm64 and repo depends on packages with x86-only wheels: `nvidia-cuda-*`, `cuda-python`, `horovod`, etc.
|
|
25
|
+
|
|
26
|
+
**Fix:** Use Rosetta, conda-forge, or verify ARM wheels exist.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
### 3. python_version_mismatch (HIGH)
|
|
31
|
+
|
|
32
|
+
**When:** Repo's `requires-python` (pyproject.toml/setup.py) doesn't include host's Python version.
|
|
33
|
+
|
|
34
|
+
**Fix:** Install the required Python (pyenv, conda, asdf).
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
### 4. native_toolchain_missing (MEDIUM)
|
|
39
|
+
|
|
40
|
+
**When:** Repo has Node native modules (node-gyp) or Rust/Cargo, but host has no gcc/clang.
|
|
41
|
+
|
|
42
|
+
**Fix:** Install Xcode CLI tools (macOS) or `build-essential` (Linux).
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
### 5. gpu_memory_risk (LOW/MEDIUM)
|
|
47
|
+
|
|
48
|
+
**When:** Repo uses torch + diffusers/transformers and host RAM < 16 GB.
|
|
49
|
+
|
|
50
|
+
**Fix:** Use smaller models, add swap, or run on a machine with more RAM.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
### 6. node_native_windows (MEDIUM)
|
|
55
|
+
|
|
56
|
+
**When:** Host is Windows and repo has Node native modules (node-gyp).
|
|
57
|
+
|
|
58
|
+
**Fix:** Use WSL, or install Visual Studio Build Tools.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
### 7. missing_system_libs (MEDIUM)
|
|
63
|
+
|
|
64
|
+
**When:** Repo requires libGL (opencv) or ffmpeg but host doesn't have them.
|
|
65
|
+
|
|
66
|
+
**Fix:** Install libgl1-mesa-glx (Linux) or ffmpeg.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## YAML Rules (Step 3 — Extensible)
|
|
71
|
+
|
|
72
|
+
Add `.repofail/rules.yaml` or `repofail-rules.yaml` in your repo:
|
|
73
|
+
|
|
74
|
+
```yaml
|
|
75
|
+
- id: custom_cuda_check
|
|
76
|
+
when:
|
|
77
|
+
repo.uses_torch: true
|
|
78
|
+
host.cuda_available: false
|
|
79
|
+
severity: HIGH
|
|
80
|
+
explanation: "Custom CUDA check for this project"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Contributing rules
|
|
86
|
+
|
|
87
|
+
Rules are in `repofail/rules/`. Each rule is a module with:
|
|
88
|
+
|
|
89
|
+
1. `check(repo: RepoProfile, host: HostProfile) -> RuleResult | None`
|
|
90
|
+
2. Returns `None` if the rule doesn't apply
|
|
91
|
+
3. Returns `RuleResult` with `rule_id`, `severity`, `message`, `reason`, `host_summary`
|
|
92
|
+
|
|
93
|
+
Add metadata to `repofail/rules/registry.py` for `--explain`. Add the check to `repofail/engine.py`.
|
|
94
|
+
|
|
95
|
+
Keep rules deterministic. No network. No guessing.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|