smallsteps 0.1.2__tar.gz → 0.1.4__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 (26) hide show
  1. smallsteps-0.1.4/.basedpyright/baseline.json +506 -0
  2. {smallsteps-0.1.2 → smallsteps-0.1.4}/.github/actions/smallsteps/action.yaml +4 -0
  3. {smallsteps-0.1.2 → smallsteps-0.1.4}/.github/workflows/ci.yaml +7 -1
  4. {smallsteps-0.1.2 → smallsteps-0.1.4}/PKG-INFO +8 -7
  5. {smallsteps-0.1.2 → smallsteps-0.1.4}/README.md +7 -6
  6. {smallsteps-0.1.2 → smallsteps-0.1.4}/pyproject.toml +3 -2
  7. smallsteps-0.1.4/smallsteps.toml +17 -0
  8. {smallsteps-0.1.2 → smallsteps-0.1.4}/src/smallsteps/ci_adapter.py +1 -3
  9. {smallsteps-0.1.2 → smallsteps-0.1.4}/uv.lock +34 -4
  10. smallsteps-0.1.2/smallsteps.toml +0 -9
  11. {smallsteps-0.1.2 → smallsteps-0.1.4}/.gitignore +0 -0
  12. {smallsteps-0.1.2 → smallsteps-0.1.4}/.python-version +0 -0
  13. {smallsteps-0.1.2 → smallsteps-0.1.4}/src/smallsteps/__init__.py +0 -0
  14. {smallsteps-0.1.2 → smallsteps-0.1.4}/src/smallsteps/cli.py +0 -0
  15. {smallsteps-0.1.2 → smallsteps-0.1.4}/src/smallsteps/cli_helpers.py +0 -0
  16. {smallsteps-0.1.2 → smallsteps-0.1.4}/src/smallsteps/command_runner.py +0 -0
  17. {smallsteps-0.1.2 → smallsteps-0.1.4}/src/smallsteps/config_adapter.py +0 -0
  18. {smallsteps-0.1.2 → smallsteps-0.1.4}/src/smallsteps/parsing.py +0 -0
  19. {smallsteps-0.1.2 → smallsteps-0.1.4}/src/smallsteps/prober.py +0 -0
  20. {smallsteps-0.1.2 → smallsteps-0.1.4}/src/smallsteps/ratchet.py +0 -0
  21. {smallsteps-0.1.2 → smallsteps-0.1.4}/tests/__init__.py +0 -0
  22. {smallsteps-0.1.2 → smallsteps-0.1.4}/tests/helpers.py +0 -0
  23. {smallsteps-0.1.2 → smallsteps-0.1.4}/tests/test_cli.py +0 -0
  24. {smallsteps-0.1.2 → smallsteps-0.1.4}/tests/test_command_runner.py +0 -0
  25. {smallsteps-0.1.2 → smallsteps-0.1.4}/tests/test_prober.py +0 -0
  26. {smallsteps-0.1.2 → smallsteps-0.1.4}/tests/test_ratchet.py +0 -0
@@ -0,0 +1,506 @@
1
+ {
2
+ "files": {
3
+ "./src/smallsteps/ci_adapter.py": [
4
+ {
5
+ "code": "reportUnusedCallResult",
6
+ "range": {
7
+ "startColumn": 12,
8
+ "endColumn": 54,
9
+ "lineCount": 1
10
+ }
11
+ }
12
+ ],
13
+ "./src/smallsteps/cli.py": [
14
+ {
15
+ "code": "reportCallInDefaultInitializer",
16
+ "range": {
17
+ "startColumn": 16,
18
+ "endColumn": 5,
19
+ "lineCount": 3
20
+ }
21
+ },
22
+ {
23
+ "code": "reportCallInDefaultInitializer",
24
+ "range": {
25
+ "startColumn": 20,
26
+ "endColumn": 5,
27
+ "lineCount": 3
28
+ }
29
+ },
30
+ {
31
+ "code": "reportCallInDefaultInitializer",
32
+ "range": {
33
+ "startColumn": 23,
34
+ "endColumn": 5,
35
+ "lineCount": 3
36
+ }
37
+ },
38
+ {
39
+ "code": "reportCallInDefaultInitializer",
40
+ "range": {
41
+ "startColumn": 32,
42
+ "endColumn": 5,
43
+ "lineCount": 3
44
+ }
45
+ },
46
+ {
47
+ "code": "reportCallInDefaultInitializer",
48
+ "range": {
49
+ "startColumn": 26,
50
+ "endColumn": 5,
51
+ "lineCount": 3
52
+ }
53
+ },
54
+ {
55
+ "code": "reportAny",
56
+ "range": {
57
+ "startColumn": 8,
58
+ "endColumn": 21,
59
+ "lineCount": 1
60
+ }
61
+ },
62
+ {
63
+ "code": "reportAny",
64
+ "range": {
65
+ "startColumn": 48,
66
+ "endColumn": 61,
67
+ "lineCount": 1
68
+ }
69
+ },
70
+ {
71
+ "code": "reportCallInDefaultInitializer",
72
+ "range": {
73
+ "startColumn": 28,
74
+ "endColumn": 5,
75
+ "lineCount": 6
76
+ }
77
+ },
78
+ {
79
+ "code": "reportCallInDefaultInitializer",
80
+ "range": {
81
+ "startColumn": 26,
82
+ "endColumn": 62,
83
+ "lineCount": 1
84
+ }
85
+ },
86
+ {
87
+ "code": "reportMatchNotExhaustive",
88
+ "range": {
89
+ "startColumn": 14,
90
+ "endColumn": 25,
91
+ "lineCount": 1
92
+ }
93
+ },
94
+ {
95
+ "code": "reportImplicitStringConcatenation",
96
+ "range": {
97
+ "startColumn": 20,
98
+ "endColumn": 105,
99
+ "lineCount": 2
100
+ }
101
+ },
102
+ {
103
+ "code": "reportImplicitStringConcatenation",
104
+ "range": {
105
+ "startColumn": 20,
106
+ "endColumn": 101,
107
+ "lineCount": 2
108
+ }
109
+ },
110
+ {
111
+ "code": "reportImplicitStringConcatenation",
112
+ "range": {
113
+ "startColumn": 20,
114
+ "endColumn": 55,
115
+ "lineCount": 2
116
+ }
117
+ },
118
+ {
119
+ "code": "reportCallInDefaultInitializer",
120
+ "range": {
121
+ "startColumn": 22,
122
+ "endColumn": 5,
123
+ "lineCount": 6
124
+ }
125
+ },
126
+ {
127
+ "code": "reportCallInDefaultInitializer",
128
+ "range": {
129
+ "startColumn": 26,
130
+ "endColumn": 5,
131
+ "lineCount": 3
132
+ }
133
+ },
134
+ {
135
+ "code": "reportImplicitStringConcatenation",
136
+ "range": {
137
+ "startColumn": 12,
138
+ "endColumn": 47,
139
+ "lineCount": 3
140
+ }
141
+ }
142
+ ],
143
+ "./src/smallsteps/command_runner.py": [
144
+ {
145
+ "code": "reportDeprecated",
146
+ "range": {
147
+ "startColumn": 19,
148
+ "endColumn": 27,
149
+ "lineCount": 1
150
+ }
151
+ },
152
+ {
153
+ "code": "reportUnannotatedClassAttribute",
154
+ "range": {
155
+ "startColumn": 13,
156
+ "endColumn": 28,
157
+ "lineCount": 1
158
+ }
159
+ },
160
+ {
161
+ "code": "reportImplicitOverride",
162
+ "range": {
163
+ "startColumn": 8,
164
+ "endColumn": 16,
165
+ "lineCount": 1
166
+ }
167
+ },
168
+ {
169
+ "code": "reportAny",
170
+ "range": {
171
+ "startColumn": 28,
172
+ "endColumn": 36,
173
+ "lineCount": 1
174
+ }
175
+ },
176
+ {
177
+ "code": "reportAny",
178
+ "range": {
179
+ "startColumn": 28,
180
+ "endColumn": 42,
181
+ "lineCount": 1
182
+ }
183
+ },
184
+ {
185
+ "code": "reportAny",
186
+ "range": {
187
+ "startColumn": 48,
188
+ "endColumn": 56,
189
+ "lineCount": 1
190
+ }
191
+ },
192
+ {
193
+ "code": "reportAny",
194
+ "range": {
195
+ "startColumn": 48,
196
+ "endColumn": 62,
197
+ "lineCount": 1
198
+ }
199
+ },
200
+ {
201
+ "code": "reportImplicitStringConcatenation",
202
+ "range": {
203
+ "startColumn": 16,
204
+ "endColumn": 49,
205
+ "lineCount": 3
206
+ }
207
+ },
208
+ {
209
+ "code": "reportImplicitOverride",
210
+ "range": {
211
+ "startColumn": 8,
212
+ "endColumn": 16,
213
+ "lineCount": 1
214
+ }
215
+ },
216
+ {
217
+ "code": "reportDeprecated",
218
+ "range": {
219
+ "startColumn": 36,
220
+ "endColumn": 44,
221
+ "lineCount": 1
222
+ }
223
+ },
224
+ {
225
+ "code": "reportUnannotatedClassAttribute",
226
+ "range": {
227
+ "startColumn": 13,
228
+ "endColumn": 24,
229
+ "lineCount": 1
230
+ }
231
+ },
232
+ {
233
+ "code": "reportUnannotatedClassAttribute",
234
+ "range": {
235
+ "startColumn": 13,
236
+ "endColumn": 27,
237
+ "lineCount": 1
238
+ }
239
+ },
240
+ {
241
+ "code": "reportImplicitOverride",
242
+ "range": {
243
+ "startColumn": 8,
244
+ "endColumn": 16,
245
+ "lineCount": 1
246
+ }
247
+ }
248
+ ],
249
+ "./src/smallsteps/config_adapter.py": [
250
+ {
251
+ "code": "reportDeprecated",
252
+ "range": {
253
+ "startColumn": 19,
254
+ "endColumn": 23,
255
+ "lineCount": 1
256
+ }
257
+ },
258
+ {
259
+ "code": "reportDeprecated",
260
+ "range": {
261
+ "startColumn": 34,
262
+ "endColumn": 38,
263
+ "lineCount": 1
264
+ }
265
+ },
266
+ {
267
+ "code": "reportDeprecated",
268
+ "range": {
269
+ "startColumn": 31,
270
+ "endColumn": 35,
271
+ "lineCount": 1
272
+ }
273
+ },
274
+ {
275
+ "code": "reportUnusedCallResult",
276
+ "range": {
277
+ "startColumn": 12,
278
+ "endColumn": 77,
279
+ "lineCount": 1
280
+ }
281
+ },
282
+ {
283
+ "code": "reportAny",
284
+ "range": {
285
+ "startColumn": 17,
286
+ "endColumn": 22,
287
+ "lineCount": 1
288
+ }
289
+ },
290
+ {
291
+ "code": "reportUnusedCallResult",
292
+ "range": {
293
+ "startColumn": 16,
294
+ "endColumn": 35,
295
+ "lineCount": 1
296
+ }
297
+ }
298
+ ],
299
+ "./src/smallsteps/parsing.py": [
300
+ {
301
+ "code": "reportAny",
302
+ "range": {
303
+ "startColumn": 24,
304
+ "endColumn": 29,
305
+ "lineCount": 1
306
+ }
307
+ },
308
+ {
309
+ "code": "reportExplicitAny",
310
+ "range": {
311
+ "startColumn": 31,
312
+ "endColumn": 34,
313
+ "lineCount": 1
314
+ }
315
+ },
316
+ {
317
+ "code": "reportAny",
318
+ "range": {
319
+ "startColumn": 63,
320
+ "endColumn": 68,
321
+ "lineCount": 1
322
+ }
323
+ }
324
+ ],
325
+ "./src/smallsteps/prober.py": [
326
+ {
327
+ "code": "reportUnannotatedClassAttribute",
328
+ "range": {
329
+ "startColumn": 13,
330
+ "endColumn": 17,
331
+ "lineCount": 1
332
+ }
333
+ },
334
+ {
335
+ "code": "reportImplicitOverride",
336
+ "range": {
337
+ "startColumn": 8,
338
+ "endColumn": 16,
339
+ "lineCount": 1
340
+ }
341
+ }
342
+ ],
343
+ "./src/smallsteps/ratchet.py": [
344
+ {
345
+ "code": "reportUnannotatedClassAttribute",
346
+ "range": {
347
+ "startColumn": 4,
348
+ "endColumn": 16,
349
+ "lineCount": 1
350
+ }
351
+ }
352
+ ],
353
+ "./tests/helpers.py": [
354
+ {
355
+ "code": "reportUnknownParameterType",
356
+ "range": {
357
+ "startColumn": 21,
358
+ "endColumn": 27,
359
+ "lineCount": 1
360
+ }
361
+ },
362
+ {
363
+ "code": "reportMissingParameterType",
364
+ "range": {
365
+ "startColumn": 21,
366
+ "endColumn": 27,
367
+ "lineCount": 1
368
+ }
369
+ },
370
+ {
371
+ "code": "reportArgumentType",
372
+ "range": {
373
+ "startColumn": 21,
374
+ "endColumn": 40,
375
+ "lineCount": 1
376
+ }
377
+ },
378
+ {
379
+ "code": "reportArgumentType",
380
+ "range": {
381
+ "startColumn": 21,
382
+ "endColumn": 40,
383
+ "lineCount": 1
384
+ }
385
+ },
386
+ {
387
+ "code": "reportArgumentType",
388
+ "range": {
389
+ "startColumn": 21,
390
+ "endColumn": 40,
391
+ "lineCount": 1
392
+ }
393
+ },
394
+ {
395
+ "code": "reportArgumentType",
396
+ "range": {
397
+ "startColumn": 21,
398
+ "endColumn": 40,
399
+ "lineCount": 1
400
+ }
401
+ },
402
+ {
403
+ "code": "reportArgumentType",
404
+ "range": {
405
+ "startColumn": 21,
406
+ "endColumn": 40,
407
+ "lineCount": 1
408
+ }
409
+ },
410
+ {
411
+ "code": "reportArgumentType",
412
+ "range": {
413
+ "startColumn": 21,
414
+ "endColumn": 40,
415
+ "lineCount": 1
416
+ }
417
+ },
418
+ {
419
+ "code": "reportUnannotatedClassAttribute",
420
+ "range": {
421
+ "startColumn": 13,
422
+ "endColumn": 18,
423
+ "lineCount": 1
424
+ }
425
+ },
426
+ {
427
+ "code": "reportImplicitOverride",
428
+ "range": {
429
+ "startColumn": 8,
430
+ "endColumn": 16,
431
+ "lineCount": 1
432
+ }
433
+ }
434
+ ],
435
+ "./tests/test_command_runner.py": [
436
+ {
437
+ "code": "reportUnknownVariableType",
438
+ "range": {
439
+ "startColumn": 45,
440
+ "endColumn": 59,
441
+ "lineCount": 1
442
+ }
443
+ },
444
+ {
445
+ "code": "reportUnusedParameter",
446
+ "range": {
447
+ "startColumn": 21,
448
+ "endColumn": 24,
449
+ "lineCount": 1
450
+ }
451
+ }
452
+ ],
453
+ "./tests/test_prober.py": [
454
+ {
455
+ "code": "reportUnknownVariableType",
456
+ "range": {
457
+ "startColumn": 45,
458
+ "endColumn": 59,
459
+ "lineCount": 1
460
+ }
461
+ },
462
+ {
463
+ "code": "reportUnusedParameter",
464
+ "range": {
465
+ "startColumn": 27,
466
+ "endColumn": 34,
467
+ "lineCount": 1
468
+ }
469
+ }
470
+ ],
471
+ "./tests/test_ratchet.py": [
472
+ {
473
+ "code": "reportUnknownVariableType",
474
+ "range": {
475
+ "startColumn": 26,
476
+ "endColumn": 40,
477
+ "lineCount": 1
478
+ }
479
+ },
480
+ {
481
+ "code": "reportUnusedCallResult",
482
+ "range": {
483
+ "startColumn": 8,
484
+ "endColumn": 9,
485
+ "lineCount": 4
486
+ }
487
+ },
488
+ {
489
+ "code": "reportUnusedCallResult",
490
+ "range": {
491
+ "startColumn": 4,
492
+ "endColumn": 56,
493
+ "lineCount": 1
494
+ }
495
+ },
496
+ {
497
+ "code": "reportUnusedCallResult",
498
+ "range": {
499
+ "startColumn": 8,
500
+ "endColumn": 55,
501
+ "lineCount": 1
502
+ }
503
+ }
504
+ ]
505
+ }
506
+ }
@@ -4,6 +4,9 @@ inputs:
4
4
  SMALLSTEPS_PYTEST_COVERAGE:
5
5
  description: "Current live performance value for 'Pytest Coverage'"
6
6
  required: true
7
+ SMALLSTEPS_TYPE_ERRORS_BASELINE:
8
+ description: "Current live performance value for 'Type Errors Baseline'"
9
+ required: true
7
10
 
8
11
  runs:
9
12
  using: 'composite'
@@ -18,3 +21,4 @@ runs:
18
21
  run: uvx smallsteps check
19
22
  env:
20
23
  SMALLSTEPS_PYTEST_COVERAGE: ${{ inputs.SMALLSTEPS_PYTEST_COVERAGE }}
24
+ SMALLSTEPS_TYPE_ERRORS_BASELINE: ${{ inputs.SMALLSTEPS_TYPE_ERRORS_BASELINE }}
@@ -29,16 +29,22 @@ jobs:
29
29
  - name: Execute Test Suite with JSON Report
30
30
  run: uv run pytest --cov --cov-report=json
31
31
 
32
- - name: Parse Metrics
32
+ - name: basedpyright
33
+ run: uv run basedpyright
34
+
35
+ - name: Extract Metrics
33
36
  id: extract_metrics
34
37
  run: |
35
38
  COVERAGE_RAW=$(jq -r '.totals.percent_covered' coverage.json)
36
39
  echo "coverage=$COVERAGE_RAW" >> $GITHUB_OUTPUT
40
+ BASEDPYRIGHT_RAW=$(jq '[.files[]? | length] | add // 0' .basedpyright/baseline.json)
41
+ echo "basedpyright=$BASEDPYRIGHT_RAW" >> $GITHUB_OUTPUT
37
42
 
38
43
  - name: Enforce Monotonic Progress Guardrails
39
44
  uses: ./.github/actions/smallsteps
40
45
  with:
41
46
  SMALLSTEPS_PYTEST_COVERAGE: ${{ steps.extract_metrics.outputs.coverage }}
47
+ SMALLSTEPS_BASEDPYRIGHT: ${{ steps.extract_metrics.outputs.basedpyright }}
42
48
 
43
49
  publish:
44
50
  needs: test
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: smallsteps
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.12
6
6
  Requires-Dist: pydantic>=2.13.4
@@ -12,7 +12,7 @@ Description-Content-Type: text/markdown
12
12
  Smallsteps allows you to declare ratchets – metrics that must increase over time – and to enforce them via testing or CI pipelines.
13
13
 
14
14
  A typical situation: you want to add test coverage as a health check.
15
- Initially your coverage is at 42% so you create a CI gate that fails if it falls under 40%. Now you have your baseline secured – so far so good. You make a resolution to yourself that you will increase your coverage to bump up the percentage in your CI action frequently.
15
+ Initially your coverage is at 42% so you create a CI gate that fails if it falls under 40%. Now you have your baseline secured – so far so good. You make a resolution to yourself: you will increase your coverage and bump up the minimum percentage frequently.
16
16
  **Somehow that never happens and your coverage stays at 42%.**
17
17
 
18
18
  With smallsteps you declare your goal of 80% coverage and that you want to reach it in 100 days. Smallsteps computes the necessary percentage that must be met for each day (e.g. after 50 days you need 60% coverage) and fails if the goal is not met.
@@ -41,16 +41,17 @@ start = 2026-06-25
41
41
  end = 2026-10-01
42
42
  initial_value = 57.142857142857146
43
43
  goal_value = 80
44
- command = "uv run pytest --cov --cov-report=json > /dev/null && jq -r '.totals.percent_covered' coverage.json"
44
+ command = "uv run pytest --cov --cov-report=json > /dev/null 2>&1 && jq -r '.totals.percent_covered' coverage.json"
45
45
 
46
46
  ```
47
47
 
48
48
  **Note**
49
49
 
50
50
  - You don't need to memorize the command parameters, `smallsteps add` walks you through them interactively.
51
- - Ratchets can be increasing or decreasing. Percentages (56%) are parsed as floats (.56). So make sure that your goal matches the format of the command output.
51
+ - Ratchets can be increasing or decreasing. Percentages (56% with explicit "%") are parsed as floats (.56). So make sure that your goal format matches the command output: if the output is plain 56, the goal should also be 56. If its 56%, the goal must be 56% or .56.
52
+ - It's allways a good idea to mute your original commands output (using `> /dev/null 2>&1`) and write the value into a file to make the result parsing easier.
52
53
 
53
- You can inspect, add or modify the ratchets using the the toml file.
54
+ You can inspect, add or modify the ratchets using the toml file. There will find also another example using basedpyright.
54
55
 
55
56
  ### Checking your Ratchets
56
57
 
@@ -70,7 +71,7 @@ shows that on the goal date the check will fail if we do not achieve 80% test co
70
71
 
71
72
  ### CI and reading values from env
72
73
 
73
- When running `smallsteps check` all commands to gather your metrics are run by smallsteps. This may be not the desired behaviour in CI because you want to run the checks in different workflows / actions and do not want to use smallsteps as a central orchestrator.
74
+ By default, running smallsteps check executes the underlying shell commands to gather active metrics. In modern CI/CD, you may prefer to compute metrics once during separate pipeline steps rather than using Smallsteps as a heavy task orchestrator.
74
75
 
75
76
  By default smallsteps looks for environment variables matching the ratchets before running the command. E.g. if `SMALLSTEPS_PYTEST_COVERAGE` is present, the coverage is not re-computed. You can use this in CI to pass outputs from test workflow into the smallsteps action. To get a scaffolding github action with the required input vars for your ratchets run `uvx smallsteps ci`.
76
77
 
@@ -78,7 +79,7 @@ Have a look at [the action](.github/actions/smallsteps/action.yaml) and the whol
78
79
 
79
80
  ## Installation
80
81
 
81
- This documentaion assumes you are using `uv`, hence you don't need to do anything despite using the uv tool command (`ux`) to install and run smallsteps.
82
+ This documentation assumes you are using `uv`, hence you don't need to do anything despite using the uv tool command (`uvx`) to install and run smallsteps.
82
83
 
83
84
  # License
84
85
 
@@ -3,7 +3,7 @@
3
3
  Smallsteps allows you to declare ratchets – metrics that must increase over time – and to enforce them via testing or CI pipelines.
4
4
 
5
5
  A typical situation: you want to add test coverage as a health check.
6
- Initially your coverage is at 42% so you create a CI gate that fails if it falls under 40%. Now you have your baseline secured – so far so good. You make a resolution to yourself that you will increase your coverage to bump up the percentage in your CI action frequently.
6
+ Initially your coverage is at 42% so you create a CI gate that fails if it falls under 40%. Now you have your baseline secured – so far so good. You make a resolution to yourself: you will increase your coverage and bump up the minimum percentage frequently.
7
7
  **Somehow that never happens and your coverage stays at 42%.**
8
8
 
9
9
  With smallsteps you declare your goal of 80% coverage and that you want to reach it in 100 days. Smallsteps computes the necessary percentage that must be met for each day (e.g. after 50 days you need 60% coverage) and fails if the goal is not met.
@@ -32,16 +32,17 @@ start = 2026-06-25
32
32
  end = 2026-10-01
33
33
  initial_value = 57.142857142857146
34
34
  goal_value = 80
35
- command = "uv run pytest --cov --cov-report=json > /dev/null && jq -r '.totals.percent_covered' coverage.json"
35
+ command = "uv run pytest --cov --cov-report=json > /dev/null 2>&1 && jq -r '.totals.percent_covered' coverage.json"
36
36
 
37
37
  ```
38
38
 
39
39
  **Note**
40
40
 
41
41
  - You don't need to memorize the command parameters, `smallsteps add` walks you through them interactively.
42
- - Ratchets can be increasing or decreasing. Percentages (56%) are parsed as floats (.56). So make sure that your goal matches the format of the command output.
42
+ - Ratchets can be increasing or decreasing. Percentages (56% with explicit "%") are parsed as floats (.56). So make sure that your goal format matches the command output: if the output is plain 56, the goal should also be 56. If its 56%, the goal must be 56% or .56.
43
+ - It's allways a good idea to mute your original commands output (using `> /dev/null 2>&1`) and write the value into a file to make the result parsing easier.
43
44
 
44
- You can inspect, add or modify the ratchets using the the toml file.
45
+ You can inspect, add or modify the ratchets using the toml file. There will find also another example using basedpyright.
45
46
 
46
47
  ### Checking your Ratchets
47
48
 
@@ -61,7 +62,7 @@ shows that on the goal date the check will fail if we do not achieve 80% test co
61
62
 
62
63
  ### CI and reading values from env
63
64
 
64
- When running `smallsteps check` all commands to gather your metrics are run by smallsteps. This may be not the desired behaviour in CI because you want to run the checks in different workflows / actions and do not want to use smallsteps as a central orchestrator.
65
+ By default, running smallsteps check executes the underlying shell commands to gather active metrics. In modern CI/CD, you may prefer to compute metrics once during separate pipeline steps rather than using Smallsteps as a heavy task orchestrator.
65
66
 
66
67
  By default smallsteps looks for environment variables matching the ratchets before running the command. E.g. if `SMALLSTEPS_PYTEST_COVERAGE` is present, the coverage is not re-computed. You can use this in CI to pass outputs from test workflow into the smallsteps action. To get a scaffolding github action with the required input vars for your ratchets run `uvx smallsteps ci`.
67
68
 
@@ -69,7 +70,7 @@ Have a look at [the action](.github/actions/smallsteps/action.yaml) and the whol
69
70
 
70
71
  ## Installation
71
72
 
72
- This documentaion assumes you are using `uv`, hence you don't need to do anything despite using the uv tool command (`ux`) to install and run smallsteps.
73
+ This documentation assumes you are using `uv`, hence you don't need to do anything despite using the uv tool command (`uvx`) to install and run smallsteps.
73
74
 
74
75
  # License
75
76
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "smallsteps"
3
- version = "0.1.2"
3
+ version = "0.1.4"
4
4
  description = "Add your description here"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -11,6 +11,7 @@ dependencies = [
11
11
 
12
12
  [dependency-groups]
13
13
  dev = [
14
+ "basedpyright>=1.39.8",
14
15
  "bump-my-version>=1.4.1",
15
16
  "ruff>=0.15.19",
16
17
  ]
@@ -30,7 +31,7 @@ requires = ["hatchling"]
30
31
  build-backend = "hatchling.build"
31
32
 
32
33
  [tool.bumpversion]
33
- current_version = "0.1.2"
34
+ current_version = "0.1.4"
34
35
  commit = true
35
36
  tag = true
36
37
  tag_name = "v{new_version}"
@@ -0,0 +1,17 @@
1
+ # Smallsteps Configuration
2
+
3
+ [[ratchets]]
4
+ name = "Pytest Coverage"
5
+ start = 2026-06-25
6
+ end = 2026-10-01
7
+ initial_value = 57.142857142857146
8
+ goal_value = 80
9
+ command = "uv run pytest --cov --cov-report=json > /dev/null 2>&1 && jq -r '.totals.percent_covered' coverage.json"
10
+
11
+ [[ratchets]]
12
+ name = "basedpyright"
13
+ start = 2026-06-25
14
+ end = 2026-10-01
15
+ initial_value = 65
16
+ goal_value = 0
17
+ command = "uv run basedpyright > /dev/null 2>&1 && jq '[.files[]? | length] | add // 0' .basedpyright/baseline.json"
@@ -1,7 +1,5 @@
1
1
  import re
2
2
  from pathlib import Path
3
- from typing import List
4
-
5
3
  from smallsteps.ratchet import Ratchet
6
4
 
7
5
 
@@ -13,7 +11,7 @@ def ratchet_to_slug(ratchet: Ratchet) -> str:
13
11
  class GitHubCIAdapter:
14
12
  """Generates a custom local GitHub Composite Action matched to the project metrics."""
15
13
 
16
- def generate_action(self, ratchets: List[Ratchet]) -> str:
14
+ def generate_action(self, ratchets: list[Ratchet]) -> str:
17
15
  """Generates an action.yaml manifest string with dynamic inputs, setup stubs, and mapping."""
18
16
  yaml_lines = [
19
17
  "name: 'Smallsteps Ratchet Evaluation'",
@@ -33,6 +33,18 @@ wheels = [
33
33
  { url = "https://files.pythonhosted.org/packages/b0/7b/90df4a0a816d98d6ea26f559d87836d494a2cf1fcf063be67df50a7bcc30/anyio-4.14.1-py3-none-any.whl", hash = "sha256:4e5533c5b8ff0a24f5d7a176cbe6877129cd183893f66b537f8f227d10527d72", size = 124875, upload-time = "2026-06-24T20:56:04.413Z" },
34
34
  ]
35
35
 
36
+ [[package]]
37
+ name = "basedpyright"
38
+ version = "1.39.8"
39
+ source = { registry = "https://pypi.org/simple" }
40
+ dependencies = [
41
+ { name = "nodejs-wheel-binaries" },
42
+ ]
43
+ sdist = { url = "https://files.pythonhosted.org/packages/d2/62/8550c75850b2185df984d1de437b4805b039ba856cacbee2966236203133/basedpyright-1.39.8.tar.gz", hash = "sha256:bb1a86d4d71425d52d1501b317fe23d45527baed06bd5d5e1a07cd4b60d07b55", size = 25488230, upload-time = "2026-06-14T09:05:30.177Z" }
44
+ wheels = [
45
+ { url = "https://files.pythonhosted.org/packages/f5/94/878454aefe94328ba7ad808ecd63da8311aae1198da46cfb29f5cfe130a8/basedpyright-1.39.8-py3-none-any.whl", hash = "sha256:a79d89928064bd9023d429b50c625d87d023bacc2fe3932ef6c7bd13b5426048", size = 13182726, upload-time = "2026-06-14T09:05:26.368Z" },
46
+ ]
47
+
36
48
  [[package]]
37
49
  name = "bracex"
38
50
  version = "2.6"
@@ -229,6 +241,22 @@ wheels = [
229
241
  { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
230
242
  ]
231
243
 
244
+ [[package]]
245
+ name = "nodejs-wheel-binaries"
246
+ version = "24.16.0"
247
+ source = { registry = "https://pypi.org/simple" }
248
+ sdist = { url = "https://files.pythonhosted.org/packages/a3/22/2a5beb4e21417c73233d9f65cf6f3e96e891b80d2f550a8f630ebc6b88c6/nodejs_wheel_binaries-24.16.0.tar.gz", hash = "sha256:c973cb69dc5fd16e6f6dc6e579e2c3d5534e2a1f57619dddf5ba070efa7dde37", size = 8056, upload-time = "2026-05-30T16:52:09.807Z" }
249
+ wheels = [
250
+ { url = "https://files.pythonhosted.org/packages/83/d1/68b43b53cd0fa83ae6fd406705023ca988d9e0ca41c724d82e66fbeb2ef6/nodejs_wheel_binaries-24.16.0-py2.py3-none-macosx_13_0_arm64.whl", hash = "sha256:d9f8f677dcf30e37ac244f07869726abe043f01eb0f45722b1df31cc2af7093c", size = 55666374, upload-time = "2026-05-30T16:51:39.588Z" },
251
+ { url = "https://files.pythonhosted.org/packages/e9/b2/40a989159599080da485de966c4c2d207e852ac7aa7864702626d96c8bf5/nodejs_wheel_binaries-24.16.0-py2.py3-none-macosx_13_0_x86_64.whl", hash = "sha256:3d0370fe7120ce9697a4f60d40480d2bd8808d9f30131458d5afc0040d4e5a51", size = 55838487, upload-time = "2026-05-30T16:51:43.383Z" },
252
+ { url = "https://files.pythonhosted.org/packages/d7/a7/cd42174fb5ff6faff7fa8d326a18914d8f232098ab5de055b57c16fa13ca/nodejs_wheel_binaries-24.16.0-py2.py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:85dc92bbb79c851569c5925dcc2a4c915a034efab375f99e4e7e6bbe9cca8342", size = 60179540, upload-time = "2026-05-30T16:51:47.036Z" },
253
+ { url = "https://files.pythonhosted.org/packages/2b/95/c8a1f9ae140aa28df8744d984d01d4b3af7cdd6555af12127f40ceb45a7d/nodejs_wheel_binaries-24.16.0-py2.py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:2f3036292811514ba847b3708492644764f88a833ac425c5f55007014308ddfd", size = 60716262, upload-time = "2026-05-30T16:51:50.711Z" },
254
+ { url = "https://files.pythonhosted.org/packages/64/c9/7c35b3737f59e36d0249c265397b7bff570519b95301d6e16ea361e904ad/nodejs_wheel_binaries-24.16.0-py2.py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:db8a8a76ebd2b28ecbfc9ad464baa3707241b9e050a30e2efdf6f60c0f886502", size = 62230592, upload-time = "2026-05-30T16:51:55Z" },
255
+ { url = "https://files.pythonhosted.org/packages/04/96/d931255cf9d11a84d6b54d882dba7434646467d568ccf070ea3418638df3/nodejs_wheel_binaries-24.16.0-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f1a3d8f7b4491cbbd023ba3fc4e901fcca2d9fb80d57f24ba3890de8b1dbac03", size = 62841759, upload-time = "2026-05-30T16:51:59.407Z" },
256
+ { url = "https://files.pythonhosted.org/packages/a2/7b/8b7a3f41bc255411be30b6d7d288aab8ffd9ea2055db8555ced3548007b9/nodejs_wheel_binaries-24.16.0-py2.py3-none-win_amd64.whl", hash = "sha256:bb136be9944f0662dcf1120f45193a6b75b13fac378971a95cc42c9f879a81aa", size = 42027734, upload-time = "2026-05-30T16:52:03.348Z" },
257
+ { url = "https://files.pythonhosted.org/packages/17/66/1ed71f1f529b8ca727d42c7ceb9db0bef145ce4a13dfc86fb50aa44f3be6/nodejs_wheel_binaries-24.16.0-py2.py3-none-win_arm64.whl", hash = "sha256:8308940b5edd0a50dc5267ea36ba21c9f668e83fe0d9f293937174d3a7e31c36", size = 39714528, upload-time = "2026-05-30T16:52:06.421Z" },
258
+ ]
259
+
232
260
  [[package]]
233
261
  name = "packaging"
234
262
  version = "26.2"
@@ -374,7 +402,7 @@ wheels = [
374
402
 
375
403
  [[package]]
376
404
  name = "pytest"
377
- version = "9.0.3"
405
+ version = "9.1.1"
378
406
  source = { registry = "https://pypi.org/simple" }
379
407
  dependencies = [
380
408
  { name = "colorama", marker = "sys_platform == 'win32'" },
@@ -383,9 +411,9 @@ dependencies = [
383
411
  { name = "pluggy" },
384
412
  { name = "pygments" },
385
413
  ]
386
- sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" }
414
+ sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
387
415
  wheels = [
388
- { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" },
416
+ { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
389
417
  ]
390
418
 
391
419
  [[package]]
@@ -486,7 +514,7 @@ wheels = [
486
514
 
487
515
  [[package]]
488
516
  name = "smallsteps"
489
- version = "0.1.1"
517
+ version = "0.1.3"
490
518
  source = { editable = "." }
491
519
  dependencies = [
492
520
  { name = "pydantic" },
@@ -495,6 +523,7 @@ dependencies = [
495
523
 
496
524
  [package.dev-dependencies]
497
525
  dev = [
526
+ { name = "basedpyright" },
498
527
  { name = "bump-my-version" },
499
528
  { name = "ruff" },
500
529
  ]
@@ -511,6 +540,7 @@ requires-dist = [
511
540
 
512
541
  [package.metadata.requires-dev]
513
542
  dev = [
543
+ { name = "basedpyright", specifier = ">=1.39.8" },
514
544
  { name = "bump-my-version", specifier = ">=1.4.1" },
515
545
  { name = "ruff", specifier = ">=0.15.19" },
516
546
  ]
@@ -1,9 +0,0 @@
1
- # Smallsteps Configuration
2
-
3
- [[ratchets]]
4
- name = "Pytest Coverage"
5
- start = 2026-06-25
6
- end = 2026-10-01
7
- initial_value = 57.142857142857146
8
- goal_value = 80
9
- command = "uv run pytest --cov --cov-report=json > /dev/null && jq -r '.totals.percent_covered' coverage.json"
File without changes
File without changes
File without changes
File without changes
File without changes