crapkit 0.7.4__tar.gz → 0.7.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.
Files changed (90) hide show
  1. {crapkit-0.7.4/src/crapkit.egg-info → crapkit-0.7.5}/PKG-INFO +5 -5
  2. {crapkit-0.7.4 → crapkit-0.7.5}/README.md +4 -4
  3. {crapkit-0.7.4 → crapkit-0.7.5}/pyproject.toml +1 -1
  4. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/__init__.py +1 -1
  5. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/cli/scoring.py +43 -2
  6. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/score.py +63 -14
  7. {crapkit-0.7.4 → crapkit-0.7.5/src/crapkit.egg-info}/PKG-INFO +5 -5
  8. {crapkit-0.7.4 → crapkit-0.7.5}/LICENSE +0 -0
  9. {crapkit-0.7.4 → crapkit-0.7.5}/setup.cfg +0 -0
  10. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/__main__.py +0 -0
  11. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/_analysis_pool.py +0 -0
  12. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/_mcp_stdio.py +0 -0
  13. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/_process_family.py +0 -0
  14. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/_process_owner.py +0 -0
  15. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/_pygdefer.py +0 -0
  16. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/_windows_job.py +0 -0
  17. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/analyze.py +0 -0
  18. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/cache.py +0 -0
  19. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/churn.py +0 -0
  20. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/churn_cache.py +0 -0
  21. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/churn_log.py +0 -0
  22. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/cli/__init__.py +0 -0
  23. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/cli/_shared.py +0 -0
  24. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/cli/admin.py +0 -0
  25. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/cli/analyses.py +0 -0
  26. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/cli/claude_hook.py +0 -0
  27. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/cli/maintenance.py +0 -0
  28. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/cli/parser.py +0 -0
  29. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/cli/queue.py +0 -0
  30. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/cli/ratchet_cmds.py +0 -0
  31. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/cli/reports.py +0 -0
  32. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/cli/verifying.py +0 -0
  33. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/config.py +0 -0
  34. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/config_contract.py +0 -0
  35. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/coupling.py +0 -0
  36. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/coupling_cache.py +0 -0
  37. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/coverage_istanbul.py +0 -0
  38. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/coverage_py.py +0 -0
  39. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/covstream.py +0 -0
  40. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/diffparse.py +0 -0
  41. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/digest.py +0 -0
  42. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/doctor.py +0 -0
  43. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/dup.py +0 -0
  44. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/errors.py +0 -0
  45. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/gitio.py +0 -0
  46. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/gitpaths.py +0 -0
  47. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/hook.py +0 -0
  48. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/invocation.py +0 -0
  49. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/junitparse.py +0 -0
  50. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/keys.py +0 -0
  51. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/lanes.py +0 -0
  52. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/lizardcognitive.py +0 -0
  53. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/lizardpowershell.py +0 -0
  54. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/lizardpython.py +0 -0
  55. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/lizardrust.py +0 -0
  56. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/lizardshell.py +0 -0
  57. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/lizardtypescript.py +0 -0
  58. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/locks.py +0 -0
  59. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/logs.py +0 -0
  60. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/mcp_server.py +0 -0
  61. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/merge.py +0 -0
  62. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/mutate.py +0 -0
  63. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/mutate_pool.py +0 -0
  64. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/override.py +0 -0
  65. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/packet.py +0 -0
  66. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/procs.py +0 -0
  67. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/ratchet.py +0 -0
  68. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/ratchet_report.py +0 -0
  69. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/ratchetfile.py +0 -0
  70. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/records.py +0 -0
  71. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/report.py +0 -0
  72. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/repotext.py +0 -0
  73. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/resources.py +0 -0
  74. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/retention.py +0 -0
  75. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/rootfind.py +0 -0
  76. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/sarif.py +0 -0
  77. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/sarifio.py +0 -0
  78. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/scaffold.py +0 -0
  79. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/snapshot.py +0 -0
  80. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/store.py +0 -0
  81. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/uncovered.py +0 -0
  82. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/universe.py +0 -0
  83. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/verify.py +0 -0
  84. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/watch.py +0 -0
  85. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit/worklist.py +0 -0
  86. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit.egg-info/SOURCES.txt +0 -0
  87. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit.egg-info/dependency_links.txt +0 -0
  88. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit.egg-info/entry_points.txt +0 -0
  89. {crapkit-0.7.4 → crapkit-0.7.5}/src/crapkit.egg-info/requires.txt +0 -0
  90. {crapkit-0.7.4 → crapkit-0.7.5}/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.7.4
3
+ Version: 0.7.5
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
@@ -199,7 +199,7 @@ files. Review those commands before running Crapkit in a repository you do not t
199
199
 
200
200
  ```
201
201
  $ crapkit --version
202
- crapkit 0.7.4
202
+ crapkit 0.7.5
203
203
  ```
204
204
 
205
205
  `python -m crapkit` works identically to the console script and is what to use from a
@@ -455,7 +455,7 @@ crapkit ships a `.pre-commit-hooks.yaml` declaring `id: crapkit-gate`. In your
455
455
  repos:
456
456
  - repo: https://github.com/JeanFrancoisGagne/crapkit
457
457
  # crapkit's release step rewrites this line to the tag it just cut
458
- rev: v0.7.4
458
+ rev: v0.7.5
459
459
  hooks:
460
460
  - id: crapkit-gate
461
461
  ```
@@ -563,7 +563,7 @@ to a workflow, and every input has a default:
563
563
  - uses: actions/checkout@v4
564
564
  with:
565
565
  fetch-depth: 0
566
- - uses: JeanFrancoisGagne/crapkit@v0.7.4
566
+ - uses: JeanFrancoisGagne/crapkit@v0.7.5
567
567
  ```
568
568
 
569
569
  The whole job those four lines sit in:
@@ -583,7 +583,7 @@ jobs:
583
583
  with:
584
584
  python-version: "3.12" # the interpreter the install below lands in
585
585
  - run: pip install -e ".[dev]" # whatever your lanes need to run
586
- - uses: JeanFrancoisGagne/crapkit@v0.7.4
586
+ - uses: JeanFrancoisGagne/crapkit@v0.7.5
587
587
  with:
588
588
  gate: "false"
589
589
  ```
@@ -158,7 +158,7 @@ files. Review those commands before running Crapkit in a repository you do not t
158
158
 
159
159
  ```
160
160
  $ crapkit --version
161
- crapkit 0.7.4
161
+ crapkit 0.7.5
162
162
  ```
163
163
 
164
164
  `python -m crapkit` works identically to the console script and is what to use from a
@@ -414,7 +414,7 @@ crapkit ships a `.pre-commit-hooks.yaml` declaring `id: crapkit-gate`. In your
414
414
  repos:
415
415
  - repo: https://github.com/JeanFrancoisGagne/crapkit
416
416
  # crapkit's release step rewrites this line to the tag it just cut
417
- rev: v0.7.4
417
+ rev: v0.7.5
418
418
  hooks:
419
419
  - id: crapkit-gate
420
420
  ```
@@ -522,7 +522,7 @@ to a workflow, and every input has a default:
522
522
  - uses: actions/checkout@v4
523
523
  with:
524
524
  fetch-depth: 0
525
- - uses: JeanFrancoisGagne/crapkit@v0.7.4
525
+ - uses: JeanFrancoisGagne/crapkit@v0.7.5
526
526
  ```
527
527
 
528
528
  The whole job those four lines sit in:
@@ -542,7 +542,7 @@ jobs:
542
542
  with:
543
543
  python-version: "3.12" # the interpreter the install below lands in
544
544
  - run: pip install -e ".[dev]" # whatever your lanes need to run
545
- - uses: JeanFrancoisGagne/crapkit@v0.7.4
545
+ - uses: JeanFrancoisGagne/crapkit@v0.7.5
546
546
  with:
547
547
  gate: "false"
548
548
  ```
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "crapkit"
7
- version = "0.7.4"
7
+ version = "0.7.5"
8
8
  description = "Scores every function on complexity times uncovered risk, ranks the worst, and blocks commits that add more."
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  license = { text = "MIT" }
@@ -1,2 +1,2 @@
1
1
  """crapkit: deterministic CRAP-score framework."""
2
- __version__ = "0.7.4"
2
+ __version__ = "0.7.5"
@@ -281,7 +281,7 @@ def _scored_run(root: Path, cfg, lanes, *, reuse_artifacts: bool, reuse_unchange
281
281
  `git` is the caller's GitFacts when it already has one — verify asks for the
282
282
  dirty set before this runs, and that answer is the one the lanes must see too.
283
283
  """
284
- from ..score import score_rows
284
+ from ..score import SharedSpanFold, score_rows
285
285
 
286
286
  git = git or GitFacts(root)
287
287
  commit, rows, corpus, cache_hits, tool_versions = _build_inventory(root, cfg, git)
@@ -294,14 +294,55 @@ def _scored_run(root: Path, cfg, lanes, *, reuse_artifacts: bool, reuse_unchange
294
294
  # Only scopes a SUCCESSFUL lane covers count as measured; a failed lane's
295
295
  # scopes fall back to no-lane flags rather than reading as untested code.
296
296
  lane_scopes = {s for lane in succeeded for s in lane.scopes}
297
+ shared_spans = SharedSpanFold()
297
298
  scored = score_rows(rows, coverage_by_path, lane_scopes=lane_scopes, target=cfg.target,
298
299
  scope_targets=cfg.scope_targets,
299
- cc_only_scopes=cfg.coverage_optional_scopes)
300
+ cc_only_scopes=cfg.coverage_optional_scopes,
301
+ shared_spans=shared_spans)
302
+ _note_shared_spans(shared_spans, cfg)
300
303
  test_failures = {f for prov in provenance.values() for f in prov.get("failures", ())}
301
304
  return _ScoredRun(commit, scored, provenance, lane_errors, test_failures, tool_versions,
302
305
  corpus, cache_hits, dead_lines)
303
306
 
304
307
 
308
+ _SPANS_NAMED = 3
309
+
310
+
311
+ def _over_target_at_zero(members, cfg):
312
+ """The worst function on each shared span that its ceiling can fail.
313
+
314
+ Every function on a shared span scores as uncovered, and a function of
315
+ complexity 2 scores 6 at zero coverage, so no ceiling of 6 can fail it.
316
+ The count carries those; the named lines are the ones worth splitting.
317
+ """
318
+ from ..score import crap
319
+
320
+ for span in members:
321
+ worst = max(span, key=lambda row: row.ccn)
322
+ if crap(worst.ccn, 0.0) > cfg.ceiling_of(worst.scope):
323
+ yield worst
324
+
325
+
326
+ def _note_shared_spans(fold, cfg) -> None:
327
+ """Name the source line spans more than one function declares.
328
+
329
+ Loud but not fatal, the shape `_note_unanalyzable` settled for unreadable
330
+ files: the join cannot tell whose coverage is whose on such a span, and
331
+ ending the run over it left the consumer repo with no coverage run at all.
332
+ """
333
+ if not fold.sites:
334
+ return
335
+ over = sorted(_over_target_at_zero(fold.sites, cfg), key=lambda row: (-row.ccn, row.path))
336
+ tail = f"; {len(over)} of them hold a function over its target:" if over else ""
337
+ print(f"crapkit: {len(fold.sites)} source line span(s) hold more than one function; "
338
+ "coverage cannot say whose is whose, so those functions score as uncovered, and "
339
+ f"splitting the definitions onto separate lines measures them{tail}", file=sys.stderr)
340
+ for row in over[:_SPANS_NAMED]:
341
+ print(f"crapkit: {row.path}:{row.start} (complexity {row.ccn})", file=sys.stderr)
342
+ if len(over) > _SPANS_NAMED:
343
+ print(f"crapkit: ... and {len(over) - _SPANS_NAMED} more", file=sys.stderr)
344
+
345
+
305
346
  def _run_kind(lanes, cfg, failures) -> str:
306
347
  """A --lane subset or a run with failed lanes must never serve as the
307
348
  verify baseline: its lane set differs from what verify runs, so every
@@ -285,27 +285,71 @@ def overlay_stale_coverage(
285
285
  return scored
286
286
 
287
287
 
288
+ class SharedSpanFold:
289
+ """The source line spans more than one function declares in one run.
290
+
291
+ The join cannot tell whose coverage is whose there, so each such function
292
+ scores as uncovered and the run names the spans instead of ending. Filled
293
+ while scoring; the caller reports it once.
294
+ """
295
+
296
+ def __init__(self) -> None:
297
+ self.sites: list[list[InventoryRow]] = []
298
+
299
+ def add(self, members: list[InventoryRow]) -> None:
300
+ self.sites.append(members)
301
+
302
+
303
+ def _identity(row) -> tuple:
304
+ """What separates two functions on one span: the name, and the occurrence
305
+ that tells sibling callbacks on a line apart."""
306
+ return row.long_name, row.occurrence
307
+
308
+
309
+ def _join_member(members: list, row) -> None:
310
+ """A third function on the span joins its members; another copy of one that
311
+ is already there (the same function in a second scope) does not."""
312
+ if all(_identity(member) != _identity(row) for member in members):
313
+ members.append(row)
314
+
315
+
288
316
  def _shared_source_spans(rows, lane_scopes: set, cc_only_scopes) -> dict:
289
- seen, collisions = {}, {}
317
+ """span -> the distinct functions declaring it, for spans more than one does."""
318
+ first, collisions = {}, {}
290
319
  for row in rows:
291
320
  if _cov_without_join(row, lane_scopes, cc_only_scopes) is not None:
292
321
  continue
293
322
  span = row.path, row.start, row.end
294
- identity = row.long_name, row.occurrence
295
- if seen.setdefault(span, identity) != identity:
296
- collisions[span] = row
323
+ seen = first.setdefault(span, row)
324
+ if _identity(seen) != _identity(row):
325
+ _join_member(collisions.setdefault(span, [seen]), row)
297
326
  return collisions
298
327
 
299
328
 
300
- def _check_coverage_spans(rows, coverage_by_path: dict, start_index: dict,
301
- lane_scopes: set, cc_only_scopes) -> None:
302
- for row in _shared_source_spans(rows, lane_scopes, cc_only_scopes).values():
303
- _, flag = _span_join_cov(row, coverage_by_path, start_index)
304
- if flag == "measured":
305
- raise ToolError(
306
- f"coverage for {row.path}:{row.start} cannot distinguish functions "
307
- "with the same line span; split their definitions onto separate "
308
- "lines and regenerate coverage")
329
+ def _ambiguous_spans(rows, coverage_by_path: dict, start_index: dict,
330
+ lane_scopes: set, cc_only_scopes) -> dict:
331
+ """The shared spans a measurement would speak about, so the join would hand
332
+ every function on the span one function's number.
333
+
334
+ Through 0.7.4 this raised and ended the run. One consumer repo holds 591
335
+ shared spans, 459 of them measured, so a run died on the first one it met
336
+ and the repo never finished a coverage run at all. Refusing the ambiguous
337
+ number is the specified behaviour; ending the run over it was not, the
338
+ shape _note_unanalyzable settled for unreadable files.
339
+ """
340
+ ambiguous = {}
341
+ for span, members in _shared_source_spans(rows, lane_scopes, cc_only_scopes).items():
342
+ if _span_join_cov(members[0], coverage_by_path, start_index)[1] == "measured":
343
+ ambiguous[span] = members
344
+ return ambiguous
345
+
346
+
347
+ def _ambiguous_cov(row, ambiguous: dict) -> tuple[float, str] | None:
348
+ """Uncovered, never the neighbour's number: the honest floor for a function
349
+ whose measurement cannot be told from another's."""
350
+ if (row.path, row.start, row.end) in ambiguous:
351
+ return 0.0, "untested"
352
+ return None
309
353
 
310
354
 
311
355
  def score_rows(
@@ -316,12 +360,17 @@ def score_rows(
316
360
  target: int = 6,
317
361
  scope_targets: dict[str, int] | None = None,
318
362
  cc_only_scopes: frozenset[str] = frozenset(),
363
+ shared_spans: SharedSpanFold | None = None,
319
364
  ) -> list[ScoredRow]:
320
365
  start_index = _start_index(coverage_by_path)
321
- _check_coverage_spans(rows, coverage_by_path, start_index, lane_scopes, cc_only_scopes)
366
+ ambiguous = _ambiguous_spans(rows, coverage_by_path, start_index, lane_scopes, cc_only_scopes)
367
+ for members in ambiguous.values():
368
+ if shared_spans is not None:
369
+ shared_spans.add(members)
322
370
  scored = []
323
371
  for r in rows:
324
372
  cov, flag = (_cov_without_join(r, lane_scopes, cc_only_scopes)
373
+ or _ambiguous_cov(r, ambiguous)
325
374
  or _span_join_cov(r, coverage_by_path, start_index))
326
375
  scored.append(_finish(r, cov, flag, target=target, scope_targets=scope_targets))
327
376
  return scored
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crapkit
3
- Version: 0.7.4
3
+ Version: 0.7.5
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
@@ -199,7 +199,7 @@ files. Review those commands before running Crapkit in a repository you do not t
199
199
 
200
200
  ```
201
201
  $ crapkit --version
202
- crapkit 0.7.4
202
+ crapkit 0.7.5
203
203
  ```
204
204
 
205
205
  `python -m crapkit` works identically to the console script and is what to use from a
@@ -455,7 +455,7 @@ crapkit ships a `.pre-commit-hooks.yaml` declaring `id: crapkit-gate`. In your
455
455
  repos:
456
456
  - repo: https://github.com/JeanFrancoisGagne/crapkit
457
457
  # crapkit's release step rewrites this line to the tag it just cut
458
- rev: v0.7.4
458
+ rev: v0.7.5
459
459
  hooks:
460
460
  - id: crapkit-gate
461
461
  ```
@@ -563,7 +563,7 @@ to a workflow, and every input has a default:
563
563
  - uses: actions/checkout@v4
564
564
  with:
565
565
  fetch-depth: 0
566
- - uses: JeanFrancoisGagne/crapkit@v0.7.4
566
+ - uses: JeanFrancoisGagne/crapkit@v0.7.5
567
567
  ```
568
568
 
569
569
  The whole job those four lines sit in:
@@ -583,7 +583,7 @@ jobs:
583
583
  with:
584
584
  python-version: "3.12" # the interpreter the install below lands in
585
585
  - run: pip install -e ".[dev]" # whatever your lanes need to run
586
- - uses: JeanFrancoisGagne/crapkit@v0.7.4
586
+ - uses: JeanFrancoisGagne/crapkit@v0.7.5
587
587
  with:
588
588
  gate: "false"
589
589
  ```
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