crapkit 0.4.7__tar.gz → 0.4.9__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.
- {crapkit-0.4.7 → crapkit-0.4.9}/PKG-INFO +150 -3
- crapkit-0.4.7/src/crapkit.egg-info/PKG-INFO → crapkit-0.4.9/README.md +1147 -1039
- {crapkit-0.4.7 → crapkit-0.4.9}/pyproject.toml +1 -1
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/__init__.py +1 -1
- crapkit-0.4.7/README.md → crapkit-0.4.9/src/crapkit.egg-info/PKG-INFO +1186 -1000
- {crapkit-0.4.7 → crapkit-0.4.9}/LICENSE +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/setup.cfg +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/__main__.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/_pygdefer.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/analyze.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/cache.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/churn.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/churn_cache.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/churn_log.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/cli/__init__.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/cli/_shared.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/cli/admin.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/cli/analyses.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/cli/claude_hook.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/cli/parser.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/cli/queue.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/cli/ratchet_cmds.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/cli/reports.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/cli/scoring.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/cli/verifying.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/config.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/coupling.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/coupling_cache.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/coverage_istanbul.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/coverage_py.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/covstream.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/diffparse.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/digest.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/discover.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/doctor.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/dup.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/errors.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/gitio.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/hook.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/junitparse.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/keys.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/lanes.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/lizardcognitive.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/lizardpowershell.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/lizardrust.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/lizardshell.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/mcp_server.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/merge.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/mutate.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/mutate_pool.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/override.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/packet.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/procs.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/ratchet.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/ratchet_report.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/report.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/sarif.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/sarifio.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/scaffold.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/score.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/snapshot.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/store.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/uncovered.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/universe.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/verify.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/watch.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit/worklist.py +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit.egg-info/SOURCES.txt +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit.egg-info/dependency_links.txt +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit.egg-info/entry_points.txt +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit.egg-info/requires.txt +0 -0
- {crapkit-0.4.7 → crapkit-0.4.9}/src/crapkit.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: crapkit
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.9
|
|
4
4
|
Summary: Scores every function on complexity times uncovered risk, ranks the worst, and blocks commits that add more.
|
|
5
5
|
Author: Jean-Francois Gagne
|
|
6
6
|
License: MIT
|
|
@@ -44,6 +44,8 @@ Dynamic: license-file
|
|
|
44
44
|
[](https://pypi.org/project/crapkit/)
|
|
45
45
|
[](LICENSE)
|
|
46
46
|
|
|
47
|
+

|
|
48
|
+
|
|
47
49
|
crapkit scores every function in your repo on complexity times uncovered risk, ranks the
|
|
48
50
|
worst ones by how often the file changes, and blocks commits that add more. It reads
|
|
49
51
|
Python, TypeScript, TSX, JavaScript, Swift, Go, Rust, shell, PowerShell, C and C++,
|
|
@@ -145,7 +147,7 @@ changing crapkit.
|
|
|
145
147
|
|
|
146
148
|
```
|
|
147
149
|
$ crapkit --version
|
|
148
|
-
crapkit 0.4.
|
|
150
|
+
crapkit 0.4.9
|
|
149
151
|
```
|
|
150
152
|
|
|
151
153
|
`python -m crapkit` works identically to the console script and is what to use from a
|
|
@@ -373,7 +375,7 @@ crapkit ships a `.pre-commit-hooks.yaml` declaring `id: crapkit-gate`. In your
|
|
|
373
375
|
repos:
|
|
374
376
|
- repo: https://github.com/JeanFrancoisGagne/crapkit
|
|
375
377
|
# crapkit's release step rewrites this line to the tag it just cut
|
|
376
|
-
rev: v0.4.
|
|
378
|
+
rev: v0.4.9
|
|
377
379
|
hooks:
|
|
378
380
|
- id: crapkit-gate
|
|
379
381
|
```
|
|
@@ -469,6 +471,151 @@ commit, and a row in the override log. All three land or nothing does, and an un
|
|
|
469
471
|
`alert_command` refuses the override outright. See
|
|
470
472
|
[docs/ratchet.md](docs/ratchet.md#overrides-and-the-audit-trail).
|
|
471
473
|
|
|
474
|
+
## The GitHub Action
|
|
475
|
+
|
|
476
|
+
[action.yml](action.yml) at this repository's root is a composite action, so a reviewer
|
|
477
|
+
sees crapkit's numbers on the pull request without installing anything. Four lines add it
|
|
478
|
+
to a workflow, and every input has a default:
|
|
479
|
+
|
|
480
|
+
```yaml
|
|
481
|
+
- uses: actions/checkout@v4
|
|
482
|
+
with:
|
|
483
|
+
fetch-depth: 0
|
|
484
|
+
- uses: JeanFrancoisGagne/crapkit@v0.4.8
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
The whole job those four lines sit in:
|
|
488
|
+
|
|
489
|
+
```yaml
|
|
490
|
+
on: pull_request
|
|
491
|
+
jobs:
|
|
492
|
+
crapkit:
|
|
493
|
+
runs-on: ubuntu-latest
|
|
494
|
+
permissions:
|
|
495
|
+
pull-requests: write # the comment, and nothing else
|
|
496
|
+
steps:
|
|
497
|
+
- uses: actions/checkout@v4
|
|
498
|
+
with:
|
|
499
|
+
fetch-depth: 0 # the diff, and verify's baseline commit
|
|
500
|
+
- run: pip install -e ".[dev]" # whatever your lanes need to run
|
|
501
|
+
- uses: JeanFrancoisGagne/crapkit@v0.4.8
|
|
502
|
+
with:
|
|
503
|
+
gate: "false"
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
That `pip install` step is the one people leave out, and it is the same one Route 4 above
|
|
507
|
+
names: the action installs crapkit and nothing else, so your lanes still need whatever
|
|
508
|
+
your test command needs. Without it the lane writes no artifact and the comment says so.
|
|
509
|
+
|
|
510
|
+
`fetch-depth: 0` is the other one. `actions/checkout` clones a single commit; the action
|
|
511
|
+
reads the pull request's changed files out of git and `verify` reads the diff against the
|
|
512
|
+
baseline's commit. With a shallow clone the file list comes back empty and the comment
|
|
513
|
+
ranks the whole repository instead of the diff.
|
|
514
|
+
|
|
515
|
+
The action installs crapkit from `$GITHUB_ACTION_PATH`, which is its own checkout of the
|
|
516
|
+
ref you pinned in `uses:`. So `@v0.4.8` scores your tree with 0.4.8's crapkit rather than
|
|
517
|
+
with whatever released last, and pinning a tag is the whole version policy.
|
|
518
|
+
|
|
519
|
+
### What the comment looks like
|
|
520
|
+
|
|
521
|
+
One comment per pull request, edited in place on every push. A hidden
|
|
522
|
+
`<!-- crapkit-action -->` line is how the next run finds it, so a fifteen-push branch
|
|
523
|
+
carries one comment and not fifteen. On a `push` event there is no pull request to carry
|
|
524
|
+
it, and the same text goes to the job log instead.
|
|
525
|
+
|
|
526
|
+
Rendered against this repository's own store, with a base commit fifteen back standing in
|
|
527
|
+
for a pull request:
|
|
528
|
+
|
|
529
|
+
```markdown
|
|
530
|
+
<!-- crapkit-action -->
|
|
531
|
+
|
|
532
|
+
## crapkit
|
|
533
|
+
|
|
534
|
+
1333 functions in 61 files, 0 over target, CRAP load 3713.89, grade A+.
|
|
535
|
+
|
|
536
|
+
**verify passed.** Run 2 against baseline 1, 7 changed files.
|
|
537
|
+
|
|
538
|
+
### Worklist: 39 changed files
|
|
539
|
+
|
|
540
|
+
| File | Function | ccn | risk | remedy |
|
|
541
|
+
|---|---|---:|---:|---|
|
|
542
|
+
| `src/crapkit/cli/admin.py:1026` | `_recorded_roots( recorded )` | 6 | 10.9908 | ok |
|
|
543
|
+
| `src/crapkit/lanes.py:646` | `build_retest_command( template : str , tests : set [ str ] )` | 6 | 10.8234 | ok |
|
|
544
|
+
| `src/crapkit/cli/admin.py:80` | `_next_step( scopes : dict , lanes : tuple )` | 5 | 9.159 | ok |
|
|
545
|
+
| `src/crapkit/cli/admin.py:239` | `_pytest_cov_probe( command : str )` | 5 | 9.159 | ok |
|
|
546
|
+
| `src/crapkit/cli/admin.py:505` | `_segment_problems( name : str , cwd : Path , tokens : list [ str ] )` | 5 | 9.159 | ok |
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
The rows are the ranked worklist for the files the pull request changed, worst first,
|
|
550
|
+
`top` of them. `risk` is ccn times churn weight, the number `crapkit worklist` ranks on,
|
|
551
|
+
and `remedy` is the run's own verdict for that function: `decompose`, `add-tests` or `ok`.
|
|
552
|
+
A pull request that touches no ranked function gets the heading and no table.
|
|
553
|
+
|
|
554
|
+
The two file counts describe the same diff, counted twice. `39 changed files` is
|
|
555
|
+
`git diff --name-only base.sha...HEAD`, the branch's own commits, and it is what the
|
|
556
|
+
table is filtered to. The count on the verdict line is what `verify` measured from the
|
|
557
|
+
same fork point. With `delta: "false"` the second one is 0, because there is nothing
|
|
558
|
+
behind the checkout to measure from.
|
|
559
|
+
|
|
560
|
+
### The inputs
|
|
561
|
+
|
|
562
|
+
| Input | Default | What it does |
|
|
563
|
+
|---|---|---|
|
|
564
|
+
| `gate` | `"false"` | `"true"` exits with `crapkit verify`'s own code, so a finding fails the check. Anything else exits 0 and the comment is the whole output |
|
|
565
|
+
| `delta` | `"true"` | scores the pull request's base commit first, so the verdict covers the commits the pull request adds. Costs a second lane run; `"false"` scores the checkout alone |
|
|
566
|
+
| `top` | `"5"` | worklist rows rendered in the table |
|
|
567
|
+
| `python-version` | `"3.12"` | the interpreter `actions/setup-python` installs crapkit into |
|
|
568
|
+
|
|
569
|
+
`gate: "false"` is the default on purpose. A team adopts the action before it has decided
|
|
570
|
+
which findings should stop a merge, and a check that fails on day one gets turned off on
|
|
571
|
+
day two.
|
|
572
|
+
|
|
573
|
+
### What the verdict line covers
|
|
574
|
+
|
|
575
|
+
On a pull request, the commits the pull request adds. The action scores the fork point
|
|
576
|
+
first, then the checkout, then runs `crapkit verify --base <fork>`, which measures the
|
|
577
|
+
diff from there and takes the fork point's run as its baseline. So the gate judges the
|
|
578
|
+
functions in the diff a reviewer is reading, and a repository that was already over its
|
|
579
|
+
ceiling before the branch started does not fail every pull request that touches it.
|
|
580
|
+
|
|
581
|
+
The fork point is `git merge-base` of `base.sha` and HEAD, not `base.sha` itself.
|
|
582
|
+
`base.sha` is the base branch's tip when the event fired, so a base branch that moved
|
|
583
|
+
after the branch forked carries commits HEAD never saw, and a run there would be neither
|
|
584
|
+
the baseline verify wants nor a diff anyone is reviewing.
|
|
585
|
+
|
|
586
|
+
The base run happens in a detached worktree under `RUNNER_TEMP`, and its store is copied
|
|
587
|
+
over the checkout's so both runs sit in one place. The cost is **two lane runs on a pull
|
|
588
|
+
request**: your suite runs once at the fork point and once on the checkout. Set `delta:
|
|
589
|
+
"false"` to skip the base run, and the verdict falls back to the checkout against its own
|
|
590
|
+
run, which reports the tree's own health and judges no changed function.
|
|
591
|
+
|
|
592
|
+
Three things leave the base run unmade, and none of them fails the job: a shallow clone
|
|
593
|
+
that does not hold the fork point, a fork point older than your `crapkit.toml`, and a
|
|
594
|
+
lane that will not run against that tree. The step logs `crapkit base scoring exited N`
|
|
595
|
+
and the verdict falls back the same way `delta: "false"` does. A `push` event never makes
|
|
596
|
+
one, because there is no base commit and no pull request to comment on.
|
|
597
|
+
|
|
598
|
+
One requirement the base run adds: the lane has to measure the tree it runs in. A lane
|
|
599
|
+
that reaches an installed copy of your package instead of the checkout will measure the
|
|
600
|
+
pull request's code while standing on the base commit, and the two runs then describe the
|
|
601
|
+
same tree. `crapkit verify` refuses a run whose artifact names files outside the tree
|
|
602
|
+
(exit 5), which catches the loud version of this; a lane pinned to a path outside the
|
|
603
|
+
worktree is the quiet one. Point the lane at the tree, or set `delta: "false"`.
|
|
604
|
+
|
|
605
|
+
`--reuse-artifacts` is what keeps each of those runs to one pass of your suite. `coverage`
|
|
606
|
+
ran the lanes moments earlier on that tree, and verify parses those artifacts rather than
|
|
607
|
+
running the whole suite a second time for the same numbers.
|
|
608
|
+
|
|
609
|
+
The other gate that judges a delta is the portable baseline in [Route 4](#route-4-ci):
|
|
610
|
+
commit `crapkit-baseline.tsv` on the default branch and run `crapkit verify --baseline-tsv
|
|
611
|
+
crapkit-baseline.tsv` in a step of your own. It needs no second lane run, and it needs
|
|
612
|
+
someone to keep that file current.
|
|
613
|
+
|
|
614
|
+
The comment is posted with `gh api` and the job's own `GITHUB_TOKEN`, which needs
|
|
615
|
+
`pull-requests: write`. Two things it cannot do: a pull request from a fork gets a
|
|
616
|
+
read-only token, so the POST is a 403 there, and a self-hosted runner without the `gh` CLI
|
|
617
|
+
on PATH fails that step. Both leave the rendered text in the job log.
|
|
618
|
+
|
|
472
619
|
## Subcommands
|
|
473
620
|
|
|
474
621
|
Every subcommand takes `--repo PATH` (default `.`), and the flag goes **after** the
|