repofail 0.2.3__tar.gz → 0.2.5__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.2.5/.gitignore +22 -0
- {repofail-0.2.3 → repofail-0.2.5}/Formula/repofail.rb +6 -4
- repofail-0.2.3/README.md → repofail-0.2.5/PKG-INFO +125 -10
- repofail-0.2.3/PKG-INFO → repofail-0.2.5/README.md +106 -23
- {repofail-0.2.3 → repofail-0.2.5}/pyproject.toml +12 -1
- repofail-0.2.5/repofail/__init__.py +8 -0
- repofail-0.2.3/.gitignore +0 -8
- repofail-0.2.3/repofail/__init__.py +0 -3
- {repofail-0.2.3 → repofail-0.2.5}/.github/workflows/publish.yml +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/.github/workflows/repofail.yml +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/CONTRIBUTING.md +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/RULES.md +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/contract.json +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/docs/assets/demo-autogpt.png +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/docs/assets/repofail-logo.png +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/docs/logo.png +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/docs/screenshots/high_failure.png +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/docs/screenshots/nodefail.gif +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/cli.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/contract.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/engine.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/fleet.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/format.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/models.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/risk.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/__init__.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/abi_wheel_mismatch.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/apple_silicon.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/base.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/docker_only.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/gpu_memory.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/info_signals.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/lock_file_missing.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/ml_niche.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/native_toolchain.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/node_engine.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/node_eol.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/node_windows.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/port_collision.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/python_eol.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/python_version.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/registry.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/spec_drift.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/system_libs.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/torch_cuda.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/rules/yaml_loader.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/scanner/__init__.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/scanner/ast_scan.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/scanner/host.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/scanner/parsers.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/scanner/repo.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/repofail/telemetry.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/tests/__init__.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/tests/test_cli_stage2.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/tests/test_contract.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/tests/test_fleet.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/tests/test_integration.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/tests/test_ml_rules.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/tests/test_rules.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/tests/test_scanner.py +0 -0
- {repofail-0.2.3 → repofail-0.2.5}/tests/test_telemetry.py +0 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
dist/
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.pyc
|
|
4
|
+
.pytest_cache/
|
|
5
|
+
*.egg-info/
|
|
6
|
+
.eggs/
|
|
7
|
+
.venv/
|
|
8
|
+
.venv-check/
|
|
9
|
+
venv/
|
|
10
|
+
testenv/
|
|
11
|
+
VISION.md
|
|
12
|
+
repofail-contract.json
|
|
13
|
+
|
|
14
|
+
# Sensitive / local-only (never commit)
|
|
15
|
+
.env
|
|
16
|
+
.env.local
|
|
17
|
+
.env.*.local
|
|
18
|
+
.secrets
|
|
19
|
+
secrets.yaml
|
|
20
|
+
.credentials
|
|
21
|
+
*.pem
|
|
22
|
+
.DS_Store
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
# Homebrew formula for repofail
|
|
2
2
|
# To use: copy to your tap repo (e.g. homebrew-tap/Formula/repofail.rb)
|
|
3
|
-
# Then: brew tap jayvenn21/tap && brew install repofail
|
|
4
|
-
# Or: brew install --formula Formula/repofail.rb (from this repo)
|
|
3
|
+
# Then: brew tap jayvenn21/tap && brew install jayvenn21/tap/repofail
|
|
5
4
|
#
|
|
6
5
|
# Homebrew uses --no-deps when installing the main package, so all Python
|
|
7
6
|
# dependencies must be declared as resources below.
|
|
7
|
+
# If SHA256 fails after pushing a new tag, get the correct hash with:
|
|
8
|
+
# curl -sL https://github.com/jayvenn21/repofail/archive/refs/tags/vX.Y.Z.tar.gz | shasum -a 256
|
|
8
9
|
|
|
9
10
|
class Repofail < Formula
|
|
10
11
|
include Language::Python::Virtualenv
|
|
11
12
|
|
|
12
13
|
desc "Deterministic runtime compatibility analyzer"
|
|
13
14
|
homepage "https://github.com/jayvenn21/repofail"
|
|
14
|
-
url "https://github.com/jayvenn21/repofail/archive/refs/tags/v0.2.
|
|
15
|
-
|
|
15
|
+
url "https://github.com/jayvenn21/repofail/archive/refs/tags/v0.2.5.tar.gz"
|
|
16
|
+
# Replace with v0.2.5 tarball SHA after tagging: curl -sL https://github.com/jayvenn21/repofail/archive/refs/tags/v0.2.5.tar.gz | shasum -a 256
|
|
17
|
+
sha256 "d5558cd419c8d46bdc958064cb97f963d1ea793866414c025906ec15033512ed"
|
|
16
18
|
license "MIT"
|
|
17
19
|
|
|
18
20
|
# App supports Python 3.10+. We use 3.12 for current Homebrew; change to
|
|
@@ -1,5 +1,24 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: repofail
|
|
3
|
+
Version: 0.2.5
|
|
4
|
+
Summary: Predict why a repository will fail on your machine before you run it.
|
|
5
|
+
Author: Jayanth
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Requires-Dist: pyyaml>=6.0
|
|
14
|
+
Requires-Dist: tomli>=2.0; python_version < '3.11'
|
|
15
|
+
Requires-Dist: typer>=0.9.0
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
1
20
|
<p align="center">
|
|
2
|
-
<img src="https://raw.githubusercontent.com/jayvenn21/repofail/
|
|
21
|
+
<img src="https://raw.githubusercontent.com/jayvenn21/repofail/main/docs/logo.png" width="180" alt="repofail logo">
|
|
3
22
|
</p>
|
|
4
23
|
|
|
5
24
|
<h1 align="center">repofail</h1>
|
|
@@ -9,14 +28,16 @@
|
|
|
9
28
|
</p>
|
|
10
29
|
|
|
11
30
|
<p align="center">
|
|
12
|
-
<a href="https://pypi.org/project/repofail/"><img src="https://img.shields.io/pypi/v/repofail
|
|
13
|
-
<img src="https://img.shields.io/
|
|
14
|
-
<img src="https://img.shields.io/
|
|
15
|
-
<img src="https://img.shields.io/
|
|
16
|
-
<img src="https://img.shields.io/badge/
|
|
31
|
+
<a href="https://pypi.org/project/repofail/"><img src="https://img.shields.io/pypi/v/repofail" alt="PyPI"></a>
|
|
32
|
+
<a href="https://pypi.org/project/repofail/"><img src="https://img.shields.io/pypi/pyversions/repofail" alt="Python"></a>
|
|
33
|
+
<a href="https://pypi.org/project/repofail/"><img src="https://img.shields.io/pypi/dm/repofail" alt="Downloads"></a>
|
|
34
|
+
<a href="https://github.com/jayvenn21/repofail/actions"><img src="https://img.shields.io/github/actions/workflow/status/jayvenn21/repofail/repofail.yml?branch=main" alt="CI"></a>
|
|
35
|
+
<img src="https://img.shields.io/badge/runtime-validated-brightgreen" alt="Runtime">
|
|
36
|
+
<img src="https://img.shields.io/badge/rules-20%2B-blue" alt="Rules">
|
|
17
37
|
</p>
|
|
18
38
|
|
|
19
39
|
<p align="center">
|
|
40
|
+
<strong>The static analyzer for runtime compatibility.</strong><br>
|
|
20
41
|
Predict why a repository will fail on your machine before you run it.
|
|
21
42
|
</p>
|
|
22
43
|
|
|
@@ -33,11 +54,24 @@
|
|
|
33
54
|
<a href="#usage">Usage</a> ·
|
|
34
55
|
<a href="#rules">Rules</a> ·
|
|
35
56
|
<a href="#ci-integration">CI</a> ·
|
|
36
|
-
<a href="#contracts">Contracts</a>
|
|
57
|
+
<a href="#contracts">Contracts</a> ·
|
|
58
|
+
<a href="#faq">FAQ</a>
|
|
37
59
|
</p>
|
|
38
60
|
|
|
39
61
|
---
|
|
40
62
|
|
|
63
|
+
## Quickstart (30 seconds)
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pip install repofail
|
|
67
|
+
cd /path/to/any/repo
|
|
68
|
+
repofail
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
You get a compatibility score and a list of deterministic blockers (Node version, Python range, CUDA, lock file, spec drift, etc.). No install of the repo’s dependencies. No cloud. No AI.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
41
75
|
## Why This Exists
|
|
42
76
|
|
|
43
77
|
Most tools install dependencies.
|
|
@@ -70,13 +104,25 @@ Run it against any local clone.
|
|
|
70
104
|
## Example output
|
|
71
105
|
|
|
72
106
|
<p align="center">
|
|
73
|
-
<img src="https://raw.githubusercontent.com/jayvenn21/repofail/
|
|
107
|
+
<img src="https://raw.githubusercontent.com/jayvenn21/repofail/main/docs/screenshots/nodefail.gif" width="850" alt="Node engine mismatch demo">
|
|
74
108
|
</p>
|
|
75
109
|
|
|
76
110
|
Deterministic spec violation detected — engines.node requires 22.x, host is 20.x.
|
|
77
111
|
|
|
78
112
|
---
|
|
79
113
|
|
|
114
|
+
## Case studies
|
|
115
|
+
|
|
116
|
+
| Scenario | Without repofail | With repofail |
|
|
117
|
+
|----------|------------------|----------------|
|
|
118
|
+
| **Node engine mismatch** | Clone → `npm install` → `EBADENGINE` → search, fix, retry | `repofail .` → "Node 22.x required, host is 20.x" + suggested fix in <1s |
|
|
119
|
+
| **CUDA on laptop** | Clone → `pip install` → run → `RuntimeError: CUDA unavailable` | `repofail .` → "Hard-coded CUDA path, host has no GPU" before you run |
|
|
120
|
+
| **Spec drift (Python)** | CI passes, local fails; pyproject says 3.11, Docker uses 3.9 | `repofail .` → "Spec drift — 3 distinct Python targets" + where they differ |
|
|
121
|
+
|
|
122
|
+
Try the demos: [node engine](https://github.com/jayvenn21/repofail-demo-node-engine), [spec drift](https://github.com/jayvenn21/repofail-demo-spec-drift), [CUDA hardcoded](https://github.com/jayvenn21/repofail-demo-cuda-hardcoded).
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
80
126
|
## Install
|
|
81
127
|
|
|
82
128
|
**From PyPI (recommended)**
|
|
@@ -85,12 +131,25 @@ Deterministic spec violation detected — engines.node requires 22.x, host is 20
|
|
|
85
131
|
pip install repofail
|
|
86
132
|
```
|
|
87
133
|
|
|
88
|
-
|
|
134
|
+
**One-liner (curl)**
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
curl -sSL https://raw.githubusercontent.com/jayvenn21/repofail/main/install.sh | bash
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**pipx (isolated CLI)**
|
|
89
141
|
|
|
90
142
|
```bash
|
|
91
143
|
pipx install repofail
|
|
92
144
|
```
|
|
93
145
|
|
|
146
|
+
**Homebrew** (formula: [jayvenn21/homebrew-tap](https://github.com/jayvenn21/homebrew-tap))
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
brew tap jayvenn21/tap
|
|
150
|
+
brew install jayvenn21/tap/repofail
|
|
151
|
+
```
|
|
152
|
+
|
|
94
153
|
**From source (development)**
|
|
95
154
|
|
|
96
155
|
```bash
|
|
@@ -139,6 +198,31 @@ repofail s -j # Stats with JSON output
|
|
|
139
198
|
|
|
140
199
|
## CI integration
|
|
141
200
|
|
|
201
|
+
**Option A — Reusable action (comment on PR + fail CI)**
|
|
202
|
+
|
|
203
|
+
```yaml
|
|
204
|
+
name: repofail
|
|
205
|
+
on:
|
|
206
|
+
pull_request:
|
|
207
|
+
branches: [main, master]
|
|
208
|
+
jobs:
|
|
209
|
+
check:
|
|
210
|
+
runs-on: ubuntu-latest
|
|
211
|
+
steps:
|
|
212
|
+
- uses: actions/checkout@v4
|
|
213
|
+
- uses: jayvenn21/repofail/.github/actions/repofail@main
|
|
214
|
+
with:
|
|
215
|
+
path: .
|
|
216
|
+
fail_on: HIGH
|
|
217
|
+
comment: 'true'
|
|
218
|
+
upload_artifact: 'true'
|
|
219
|
+
pr_number: ${{ github.event.pull_request.number }}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
The action installs repofail, runs a compatibility check, comments the Markdown report on the PR, uploads the JSON artifact, and fails the job if violations meet the threshold.
|
|
223
|
+
|
|
224
|
+
**Option B — Inline (no comment)**
|
|
225
|
+
|
|
142
226
|
```yaml
|
|
143
227
|
- uses: actions/checkout@v4
|
|
144
228
|
- uses: actions/setup-python@v5
|
|
@@ -157,7 +241,7 @@ repofail gen . -o contract.json
|
|
|
157
241
|
repofail check contract.json
|
|
158
242
|
```
|
|
159
243
|
|
|
160
|
-
Versioned runtime expectations. Teams share contracts. CI checks drift.
|
|
244
|
+
Versioned runtime expectations. Teams share contracts. CI checks drift. Generated contracts report the installed repofail version (from PyPI/Homebrew) so tooling stays traceable.
|
|
161
245
|
|
|
162
246
|
---
|
|
163
247
|
|
|
@@ -230,8 +314,39 @@ Extensible via `.repofail/rules.yaml`.
|
|
|
230
314
|
|
|
231
315
|
---
|
|
232
316
|
|
|
317
|
+
## FAQ
|
|
318
|
+
|
|
319
|
+
**Does repofail install or run my project?**
|
|
320
|
+
No. It only reads configs and (optionally) inspects Python/JS for patterns. No `pip install`, no `npm install`, no execution.
|
|
321
|
+
|
|
322
|
+
**Does it need the internet?**
|
|
323
|
+
No. It runs fully offline. Host inspection uses local subprocesses (e.g. `node --version`).
|
|
324
|
+
|
|
325
|
+
**Why “deterministic”?**
|
|
326
|
+
Same repo + same host → same result. No ML, no heuristics that change between runs. Rules are based on config and code.
|
|
327
|
+
|
|
328
|
+
**Can I add my own rules?**
|
|
329
|
+
Yes. Put a `.repofail/rules.yaml` (or `repofail-rules.yaml`) in the repo and define conditions on `repo.*` and `host.*`. See `repofail -e list` for built-in rule IDs.
|
|
330
|
+
|
|
331
|
+
**What if my repo is clean?**
|
|
332
|
+
You get a high score (e.g. 96–100%) and “No deterministic blockers detected.” repofail does not invent problems.
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## When not to use it
|
|
337
|
+
|
|
338
|
+
- **You need dependency resolution** — use pip, npm, poetry, etc. repofail does not install or resolve.
|
|
339
|
+
- **You need security scanning** — use Dependabot, Snyk, or similar. repofail is compatibility-only.
|
|
340
|
+
- **You want “AI suggested fixes”** — repofail gives deterministic, rule-based suggestions only.
|
|
341
|
+
- **You run only in one environment** — if every dev and CI use the same OS/runtime, the value is smaller (still useful for drift and contracts).
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
233
345
|
## Testing
|
|
234
346
|
|
|
235
347
|
```bash
|
|
348
|
+
pip install -e ".[dev]"
|
|
236
349
|
pytest tests/ -v
|
|
237
350
|
```
|
|
351
|
+
|
|
352
|
+
**Quick checks:** `bash -n install.sh` (syntax). The GitHub Action runs on every PR in this repo (see [.github/workflows/repofail.yml](.github/workflows/repofail.yml)); to test the reusable action, use it in another repo’s workflow on a PR.
|
|
@@ -1,18 +1,5 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: repofail
|
|
3
|
-
Version: 0.2.3
|
|
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
1
|
<p align="center">
|
|
15
|
-
<img src="https://raw.githubusercontent.com/jayvenn21/repofail/
|
|
2
|
+
<img src="https://raw.githubusercontent.com/jayvenn21/repofail/main/docs/logo.png" width="180" alt="repofail logo">
|
|
16
3
|
</p>
|
|
17
4
|
|
|
18
5
|
<h1 align="center">repofail</h1>
|
|
@@ -22,14 +9,16 @@ Description-Content-Type: text/markdown
|
|
|
22
9
|
</p>
|
|
23
10
|
|
|
24
11
|
<p align="center">
|
|
25
|
-
<a href="https://pypi.org/project/repofail/"><img src="https://img.shields.io/pypi/v/repofail
|
|
26
|
-
<img src="https://img.shields.io/
|
|
27
|
-
<img src="https://img.shields.io/
|
|
28
|
-
<img src="https://img.shields.io/
|
|
29
|
-
<img src="https://img.shields.io/badge/
|
|
12
|
+
<a href="https://pypi.org/project/repofail/"><img src="https://img.shields.io/pypi/v/repofail" alt="PyPI"></a>
|
|
13
|
+
<a href="https://pypi.org/project/repofail/"><img src="https://img.shields.io/pypi/pyversions/repofail" alt="Python"></a>
|
|
14
|
+
<a href="https://pypi.org/project/repofail/"><img src="https://img.shields.io/pypi/dm/repofail" alt="Downloads"></a>
|
|
15
|
+
<a href="https://github.com/jayvenn21/repofail/actions"><img src="https://img.shields.io/github/actions/workflow/status/jayvenn21/repofail/repofail.yml?branch=main" alt="CI"></a>
|
|
16
|
+
<img src="https://img.shields.io/badge/runtime-validated-brightgreen" alt="Runtime">
|
|
17
|
+
<img src="https://img.shields.io/badge/rules-20%2B-blue" alt="Rules">
|
|
30
18
|
</p>
|
|
31
19
|
|
|
32
20
|
<p align="center">
|
|
21
|
+
<strong>The static analyzer for runtime compatibility.</strong><br>
|
|
33
22
|
Predict why a repository will fail on your machine before you run it.
|
|
34
23
|
</p>
|
|
35
24
|
|
|
@@ -46,11 +35,24 @@ Description-Content-Type: text/markdown
|
|
|
46
35
|
<a href="#usage">Usage</a> ·
|
|
47
36
|
<a href="#rules">Rules</a> ·
|
|
48
37
|
<a href="#ci-integration">CI</a> ·
|
|
49
|
-
<a href="#contracts">Contracts</a>
|
|
38
|
+
<a href="#contracts">Contracts</a> ·
|
|
39
|
+
<a href="#faq">FAQ</a>
|
|
50
40
|
</p>
|
|
51
41
|
|
|
52
42
|
---
|
|
53
43
|
|
|
44
|
+
## Quickstart (30 seconds)
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install repofail
|
|
48
|
+
cd /path/to/any/repo
|
|
49
|
+
repofail
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
You get a compatibility score and a list of deterministic blockers (Node version, Python range, CUDA, lock file, spec drift, etc.). No install of the repo’s dependencies. No cloud. No AI.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
54
56
|
## Why This Exists
|
|
55
57
|
|
|
56
58
|
Most tools install dependencies.
|
|
@@ -83,13 +85,25 @@ Run it against any local clone.
|
|
|
83
85
|
## Example output
|
|
84
86
|
|
|
85
87
|
<p align="center">
|
|
86
|
-
<img src="https://raw.githubusercontent.com/jayvenn21/repofail/
|
|
88
|
+
<img src="https://raw.githubusercontent.com/jayvenn21/repofail/main/docs/screenshots/nodefail.gif" width="850" alt="Node engine mismatch demo">
|
|
87
89
|
</p>
|
|
88
90
|
|
|
89
91
|
Deterministic spec violation detected — engines.node requires 22.x, host is 20.x.
|
|
90
92
|
|
|
91
93
|
---
|
|
92
94
|
|
|
95
|
+
## Case studies
|
|
96
|
+
|
|
97
|
+
| Scenario | Without repofail | With repofail |
|
|
98
|
+
|----------|------------------|----------------|
|
|
99
|
+
| **Node engine mismatch** | Clone → `npm install` → `EBADENGINE` → search, fix, retry | `repofail .` → "Node 22.x required, host is 20.x" + suggested fix in <1s |
|
|
100
|
+
| **CUDA on laptop** | Clone → `pip install` → run → `RuntimeError: CUDA unavailable` | `repofail .` → "Hard-coded CUDA path, host has no GPU" before you run |
|
|
101
|
+
| **Spec drift (Python)** | CI passes, local fails; pyproject says 3.11, Docker uses 3.9 | `repofail .` → "Spec drift — 3 distinct Python targets" + where they differ |
|
|
102
|
+
|
|
103
|
+
Try the demos: [node engine](https://github.com/jayvenn21/repofail-demo-node-engine), [spec drift](https://github.com/jayvenn21/repofail-demo-spec-drift), [CUDA hardcoded](https://github.com/jayvenn21/repofail-demo-cuda-hardcoded).
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
93
107
|
## Install
|
|
94
108
|
|
|
95
109
|
**From PyPI (recommended)**
|
|
@@ -98,12 +112,25 @@ Deterministic spec violation detected — engines.node requires 22.x, host is 20
|
|
|
98
112
|
pip install repofail
|
|
99
113
|
```
|
|
100
114
|
|
|
101
|
-
|
|
115
|
+
**One-liner (curl)**
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
curl -sSL https://raw.githubusercontent.com/jayvenn21/repofail/main/install.sh | bash
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**pipx (isolated CLI)**
|
|
102
122
|
|
|
103
123
|
```bash
|
|
104
124
|
pipx install repofail
|
|
105
125
|
```
|
|
106
126
|
|
|
127
|
+
**Homebrew** (formula: [jayvenn21/homebrew-tap](https://github.com/jayvenn21/homebrew-tap))
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
brew tap jayvenn21/tap
|
|
131
|
+
brew install jayvenn21/tap/repofail
|
|
132
|
+
```
|
|
133
|
+
|
|
107
134
|
**From source (development)**
|
|
108
135
|
|
|
109
136
|
```bash
|
|
@@ -152,6 +179,31 @@ repofail s -j # Stats with JSON output
|
|
|
152
179
|
|
|
153
180
|
## CI integration
|
|
154
181
|
|
|
182
|
+
**Option A — Reusable action (comment on PR + fail CI)**
|
|
183
|
+
|
|
184
|
+
```yaml
|
|
185
|
+
name: repofail
|
|
186
|
+
on:
|
|
187
|
+
pull_request:
|
|
188
|
+
branches: [main, master]
|
|
189
|
+
jobs:
|
|
190
|
+
check:
|
|
191
|
+
runs-on: ubuntu-latest
|
|
192
|
+
steps:
|
|
193
|
+
- uses: actions/checkout@v4
|
|
194
|
+
- uses: jayvenn21/repofail/.github/actions/repofail@main
|
|
195
|
+
with:
|
|
196
|
+
path: .
|
|
197
|
+
fail_on: HIGH
|
|
198
|
+
comment: 'true'
|
|
199
|
+
upload_artifact: 'true'
|
|
200
|
+
pr_number: ${{ github.event.pull_request.number }}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
The action installs repofail, runs a compatibility check, comments the Markdown report on the PR, uploads the JSON artifact, and fails the job if violations meet the threshold.
|
|
204
|
+
|
|
205
|
+
**Option B — Inline (no comment)**
|
|
206
|
+
|
|
155
207
|
```yaml
|
|
156
208
|
- uses: actions/checkout@v4
|
|
157
209
|
- uses: actions/setup-python@v5
|
|
@@ -170,7 +222,7 @@ repofail gen . -o contract.json
|
|
|
170
222
|
repofail check contract.json
|
|
171
223
|
```
|
|
172
224
|
|
|
173
|
-
Versioned runtime expectations. Teams share contracts. CI checks drift.
|
|
225
|
+
Versioned runtime expectations. Teams share contracts. CI checks drift. Generated contracts report the installed repofail version (from PyPI/Homebrew) so tooling stays traceable.
|
|
174
226
|
|
|
175
227
|
---
|
|
176
228
|
|
|
@@ -243,8 +295,39 @@ Extensible via `.repofail/rules.yaml`.
|
|
|
243
295
|
|
|
244
296
|
---
|
|
245
297
|
|
|
298
|
+
## FAQ
|
|
299
|
+
|
|
300
|
+
**Does repofail install or run my project?**
|
|
301
|
+
No. It only reads configs and (optionally) inspects Python/JS for patterns. No `pip install`, no `npm install`, no execution.
|
|
302
|
+
|
|
303
|
+
**Does it need the internet?**
|
|
304
|
+
No. It runs fully offline. Host inspection uses local subprocesses (e.g. `node --version`).
|
|
305
|
+
|
|
306
|
+
**Why “deterministic”?**
|
|
307
|
+
Same repo + same host → same result. No ML, no heuristics that change between runs. Rules are based on config and code.
|
|
308
|
+
|
|
309
|
+
**Can I add my own rules?**
|
|
310
|
+
Yes. Put a `.repofail/rules.yaml` (or `repofail-rules.yaml`) in the repo and define conditions on `repo.*` and `host.*`. See `repofail -e list` for built-in rule IDs.
|
|
311
|
+
|
|
312
|
+
**What if my repo is clean?**
|
|
313
|
+
You get a high score (e.g. 96–100%) and “No deterministic blockers detected.” repofail does not invent problems.
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## When not to use it
|
|
318
|
+
|
|
319
|
+
- **You need dependency resolution** — use pip, npm, poetry, etc. repofail does not install or resolve.
|
|
320
|
+
- **You need security scanning** — use Dependabot, Snyk, or similar. repofail is compatibility-only.
|
|
321
|
+
- **You want “AI suggested fixes”** — repofail gives deterministic, rule-based suggestions only.
|
|
322
|
+
- **You run only in one environment** — if every dev and CI use the same OS/runtime, the value is smaller (still useful for drift and contracts).
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
246
326
|
## Testing
|
|
247
327
|
|
|
248
328
|
```bash
|
|
329
|
+
pip install -e ".[dev]"
|
|
249
330
|
pytest tests/ -v
|
|
250
331
|
```
|
|
332
|
+
|
|
333
|
+
**Quick checks:** `bash -n install.sh` (syntax). The GitHub Action runs on every PR in this repo (see [.github/workflows/repofail.yml](.github/workflows/repofail.yml)); to test the reusable action, use it in another repo’s workflow on a PR.
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "repofail"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.5"
|
|
8
8
|
description = "Predict why a repository will fail on your machine before you run it."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -14,6 +14,14 @@ dependencies = [
|
|
|
14
14
|
"tomli>=2.0; python_version < '3.11'",
|
|
15
15
|
"pyyaml>=6.0",
|
|
16
16
|
]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
24
|
+
]
|
|
17
25
|
|
|
18
26
|
[project.scripts]
|
|
19
27
|
repofail = "repofail.cli:_main"
|
|
@@ -23,3 +31,6 @@ dev = [
|
|
|
23
31
|
"pytest>=7.0",
|
|
24
32
|
]
|
|
25
33
|
|
|
34
|
+
[tool.hatch.build.targets.sdist]
|
|
35
|
+
exclude = [".venv-check", ".venv-check/**", "testenv", "testenv/**", ".venv", ".venv/**", "venv", "venv/**"]
|
|
36
|
+
|
repofail-0.2.3/.gitignore
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|