supercov 4.4.0 → 4.5.0
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.
- package/README.md +23 -0
- package/docs/cli.md +88 -1
- package/docs/workspace-isolation.md +46 -2
- package/package.json +17 -16
- package/runtime/javascript/register.mjs +3 -2
package/README.md
CHANGED
|
@@ -344,6 +344,29 @@ npx supercov report
|
|
|
344
344
|
|
|
345
345
|
Collections accept `--limit` and `--offset` and print a copyable next-page command. Machine-readable output is available with `--json` when an integration needs it.
|
|
346
346
|
|
|
347
|
+
## Comment on pull requests
|
|
348
|
+
|
|
349
|
+
In GitHub Actions, one step runs your tests and tells the pull request which
|
|
350
|
+
changed lines no test ran:
|
|
351
|
+
|
|
352
|
+
```yaml
|
|
353
|
+
permissions:
|
|
354
|
+
contents: read
|
|
355
|
+
pull-requests: write
|
|
356
|
+
|
|
357
|
+
steps:
|
|
358
|
+
- uses: actions/checkout@v6
|
|
359
|
+
- run: npm ci
|
|
360
|
+
- uses: supercorp-ai/supercov@v4
|
|
361
|
+
with:
|
|
362
|
+
command: npm test
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
It works with every supported language, keeps one comment up to date, marks the
|
|
366
|
+
lines in the diff, and can fail the job below a floor (`min-changed-lines: 90`).
|
|
367
|
+
No account, no upload token and no server: the report never leaves the runner.
|
|
368
|
+
See [Comment on a pull request](docs/cli.md#comment-on-a-pull-request).
|
|
369
|
+
|
|
347
370
|
## Local, private, and zero-edit
|
|
348
371
|
|
|
349
372
|
Everything Supercov writes lives under one hidden `.supercov/` directory: run evidence in `.supercov/runs/<run-id>/` and the isolated build cache in `.supercov/workspaces/`. It ignores itself in Git, so there is nothing to add to your `.gitignore`.
|
package/docs/cli.md
CHANGED
|
@@ -279,6 +279,62 @@ code nothing ran.
|
|
|
279
279
|
adjacent misses into one range and capping the total (`--max-annotations`). It
|
|
280
280
|
needs no token and posts no comment.
|
|
281
281
|
|
|
282
|
+
## Comment on a pull request
|
|
283
|
+
|
|
284
|
+
In GitHub Actions, one step runs the tests, says in a comment which changed
|
|
285
|
+
lines no test ran, and marks them in the diff:
|
|
286
|
+
|
|
287
|
+
```yaml
|
|
288
|
+
on: pull_request
|
|
289
|
+
|
|
290
|
+
permissions:
|
|
291
|
+
contents: read
|
|
292
|
+
pull-requests: write
|
|
293
|
+
|
|
294
|
+
jobs:
|
|
295
|
+
test:
|
|
296
|
+
runs-on: ubuntu-latest
|
|
297
|
+
steps:
|
|
298
|
+
- uses: actions/checkout@v6
|
|
299
|
+
- run: npm ci
|
|
300
|
+
- uses: supercorp-ai/supercov@v4
|
|
301
|
+
with:
|
|
302
|
+
command: npm test
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
`command` is the test command in any supported language: `pytest`,
|
|
306
|
+
`cargo test`, `go test ./...`, `bundle exec rspec`, `mvn test`. The step takes
|
|
307
|
+
the place of the one that ran the tests, and fails when they fail. It needs no
|
|
308
|
+
account and no server: the comment is written with the workflow's own token,
|
|
309
|
+
and everything else stays on the runner.
|
|
310
|
+
|
|
311
|
+
The comment gives the coverage of the changed lines, the run's line, branch and
|
|
312
|
+
MC/DC coverage, and each changed file with the lines no test ran, linked to the
|
|
313
|
+
commit. A later push rewrites the same comment. The job summary holds the same
|
|
314
|
+
report, which is what a pull request from a fork gets: its token cannot write a
|
|
315
|
+
comment.
|
|
316
|
+
|
|
317
|
+
| Input | Default | |
|
|
318
|
+
| --- | --- | --- |
|
|
319
|
+
| `command` | required | The test command. One command; put several in a script. |
|
|
320
|
+
| `working-directory` | `.` | Where to run it. |
|
|
321
|
+
| `min-changed-lines` | none | Fail below this percentage of changed lines covered. |
|
|
322
|
+
| `min-lines`, `min-branches`, `min-mcdc` | none | Fail below this percentage for the whole run. |
|
|
323
|
+
| `title` | `Coverage` | The comment's heading. Give each job its own when several comment on one pull request. |
|
|
324
|
+
| `base` | the pull request's base | What the change is compared with. |
|
|
325
|
+
| `comment`, `annotate` | `true` | Turn the comment or the marks in the diff off. |
|
|
326
|
+
| `version` | the action's release | The Supercov release to run. |
|
|
327
|
+
| `binary` | none | A `supercov` already on the runner, used instead of downloading one. |
|
|
328
|
+
|
|
329
|
+
The default checkout fetches one commit; the step fetches the history between
|
|
330
|
+
it and the base itself. It puts `supercov` on the `PATH` and sets the outputs
|
|
331
|
+
`run-id`, `lines`, `branches` and `changed-lines`, so later steps can read the
|
|
332
|
+
same run:
|
|
333
|
+
|
|
334
|
+
```yaml
|
|
335
|
+
- run: supercov runs report --format html --output coverage/report
|
|
336
|
+
```
|
|
337
|
+
|
|
282
338
|
## Export for other tools
|
|
283
339
|
|
|
284
340
|
```sh supercov-example
|
|
@@ -300,7 +356,13 @@ one to fill a field.
|
|
|
300
356
|
|
|
301
357
|
MC/DC conditions are not exported as ordinary branches. A consumer would then
|
|
302
358
|
show condition obligations as branch coverage, which is a different
|
|
303
|
-
measurement
|
|
359
|
+
measurement. The LCOV export writes them as LCOV 2's own records, `MCDC:` for
|
|
360
|
+
each condition with `MCF:` and `MCH:` for a file, so `lcov --mcdc-coverage` and
|
|
361
|
+
`genhtml --mcdc-coverage` show a per-file MC/DC figure from the export alone.
|
|
362
|
+
LCOV counts a condition twice, once for each way it can turn the outcome, and
|
|
363
|
+
Supercov's covered condition is both: hit over found is the run's MC/DC. A
|
|
364
|
+
reader of the older format passes the records over. Cobertura has no such
|
|
365
|
+
record; there the evidence stays in the JSON view and the HTML report. A report
|
|
304
366
|
from a failed or stale run is still written, with a warning on stderr — only
|
|
305
367
|
`check` refuses to pass on one.
|
|
306
368
|
|
|
@@ -516,12 +578,37 @@ assessment, each commit cost under a cent.
|
|
|
516
578
|
|
|
517
579
|
```sh supercov
|
|
518
580
|
npx supercov merge <shard-a> <shard-b> <shard-c>
|
|
581
|
+
npx supercov merge
|
|
519
582
|
```
|
|
520
583
|
|
|
521
584
|
Merge creates a new run. The inputs must describe the same source,
|
|
522
585
|
configuration, toolchain, schema, and coverage denominator. Supercov rejects an
|
|
523
586
|
incompatible merge rather than publishing a misleading aggregate.
|
|
524
587
|
|
|
588
|
+
With no run named, `merge` takes the runs recorded on the source as it is now:
|
|
589
|
+
the newest of each command, leaving out runs that are themselves a merge. It
|
|
590
|
+
prints the runs it took. This is what a script uses after measuring its
|
|
591
|
+
suites, one after another or side by side, without knowing what each run was
|
|
592
|
+
called. Asked again with nothing new, it names the merge already made.
|
|
593
|
+
|
|
594
|
+
A test that is in two of the runs is one test in the merge. If it failed in
|
|
595
|
+
either, it is failed, which is why a command run again replaces its earlier
|
|
596
|
+
run and is not merged with it.
|
|
597
|
+
|
|
598
|
+
The runs may differ in their tests when the later ones have only gained test
|
|
599
|
+
files. Measuring a new test alone and adding it to the runs before it is
|
|
600
|
+
then the whole suite's figure, without the whole suite's time:
|
|
601
|
+
|
|
602
|
+
```sh supercov-example
|
|
603
|
+
npx supercov -- npm test # the suite, once
|
|
604
|
+
npx supercov -- npx vitest run test/new.test.ts # a test added since, alone
|
|
605
|
+
npx supercov merge
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
A run is left out, and named, when a file of its own tests has changed since
|
|
609
|
+
it ran, or a file tests load that is not itself a test's: what it recorded is
|
|
610
|
+
then of other tests. Measure those again to count them.
|
|
611
|
+
|
|
525
612
|
`assertions assess` assesses a merged run across every suite merged into it,
|
|
526
613
|
reusing the answers saved when its parts were assessed. `tests affected` is
|
|
527
614
|
asked of the runs that were merged, which hold the record of what each test
|
|
@@ -114,12 +114,56 @@ partial output.
|
|
|
114
114
|
|
|
115
115
|
## Interrupted and overlapping commands
|
|
116
116
|
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
Runs of one project can be started at the same moment. Each takes a copy of
|
|
118
|
+
the project to itself: a run alone always has the first,
|
|
119
|
+
`.supercov/workspaces/workspace/<name>`, and one started while that is in use
|
|
120
|
+
has `workspace-2`, the next `workspace-3`. None waits and none is refused:
|
|
121
|
+
|
|
122
|
+
```sh
|
|
123
|
+
npx supercov -- npm run test:unit &
|
|
124
|
+
npx supercov -- npm run test:integration &
|
|
125
|
+
npx supercov -- npm run test:e2e &
|
|
126
|
+
wait
|
|
127
|
+
npx supercov merge
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`merge` with no run named adds up the runs recorded on the source as it is
|
|
131
|
+
now, so a script does not have to know what each was called.
|
|
132
|
+
|
|
133
|
+
A copy past the first is kept for a day after its last run, so that runs that
|
|
134
|
+
overlap again start from what they left, and is removed after that. Rust runs
|
|
135
|
+
build into one directory, as two `cargo test` do, and Cargo makes the second
|
|
136
|
+
wait while the first compiles.
|
|
137
|
+
|
|
138
|
+
Suites can also be started from one command. They are then one run with
|
|
139
|
+
nothing to merge, and each test keeps the kind its own process was given:
|
|
140
|
+
|
|
141
|
+
```sh
|
|
142
|
+
npx supercov -- sh -c '
|
|
143
|
+
SUPERCOV_TEST_KIND=integration npm run test:integration & integration=$!
|
|
144
|
+
SUPERCOV_TEST_KIND=e2e npm run test:e2e & e2e=$!
|
|
145
|
+
wait $integration; first=$?
|
|
146
|
+
wait $e2e && exit $first
|
|
147
|
+
'
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
`wait` with no argument ends with 0 whatever the suites did, which would turn a
|
|
151
|
+
failing suite green; waiting for each by its id keeps the status.
|
|
152
|
+
|
|
153
|
+
`runs clean` wants the store to itself. While a run is active it ends with
|
|
154
|
+
status 2 and names the run; a run started while it works is told so, and no
|
|
155
|
+
test of it runs.
|
|
119
156
|
|
|
120
157
|
After interruption or host restart, the next command recovers unpublished
|
|
121
158
|
staging state. Completed runs remain immutable.
|
|
122
159
|
|
|
160
|
+
Ctrl-C ends the test command and the run: nothing is recorded, and the exit
|
|
161
|
+
status is 130. A test command that reads the keyboard (a debugger at a
|
|
162
|
+
breakpoint, a watch mode, a question before an install) is given the terminal
|
|
163
|
+
when it first reads, on macOS and Linux. From then on Ctrl-C and Ctrl-Z go to
|
|
164
|
+
it, as they do without Supercov, and a command that Ctrl-C ended is still a
|
|
165
|
+
run that was interrupted.
|
|
166
|
+
|
|
123
167
|
## Clean up local data
|
|
124
168
|
|
|
125
169
|
Preview cleanup before removing anything:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "supercov",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.0",
|
|
4
4
|
"description": "Coverage, security and code quality for coding agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"coverage",
|
|
@@ -70,6 +70,7 @@
|
|
|
70
70
|
"test:react": "cargo build -p supercov && node scripts/rust-vitest-projects-integration.mjs && npm --prefix examples/react-verification ci && npm --prefix examples/react-verification run demo && node scripts/react-hydration-compatibility.mjs",
|
|
71
71
|
"test:release-tooling": "node --test tests/release/*.test.mjs",
|
|
72
72
|
"test:runtime": "node --test tests/runtime/*.test.mjs",
|
|
73
|
+
"test:action": "cargo build -p supercov && node --test tests/action/*.test.mjs",
|
|
73
74
|
"test:fixture": "cargo build -p supercov && node scripts/rust-fixture-matrix.mjs",
|
|
74
75
|
"test:packed-npx": "cargo build --release -p supercov && node scripts/packed-npx-integration.mjs",
|
|
75
76
|
"test:isolation": "cargo build -p supercov && node scripts/isolation-integration.mjs",
|
|
@@ -82,7 +83,7 @@
|
|
|
82
83
|
"eval:skill": "claude plugin eval plugins/supercov --scaffold --trust-plugin --no-publish --model claude-sonnet-5 --judge-model claude-haiku-4-5 --threshold 0.66 --tag behavior trigger --allow-tools Bash Edit Write --max-cost-usd 15",
|
|
83
84
|
"eval:skill-triggers": "claude plugin eval plugins/supercov --scaffold --trust-plugin --no-publish --model claude-sonnet-5 --judge-model claude-haiku-4-5 --threshold 0.66 --tag trigger --ablation none --max-cost-usd 5",
|
|
84
85
|
"test:engine": "cargo fmt --all -- --check && cargo clippy --workspace --all-targets -- -D warnings && cargo test --workspace && npm run test:runtime && npm run test:rust-assets && npm run test:engine-integrations",
|
|
85
|
-
"test:engine-integrations": "cargo build -p supercov && node scripts/html-report-integration.mjs && node scripts/rust-process-supervision.mjs && node scripts/rust-direct-node-integration.mjs && node scripts/rust-public-run-integration.mjs && node scripts/rust-embedded-runtime-integration.mjs && node scripts/rust-direct-vitest-integration.mjs && node scripts/rust-direct-jest-integration.mjs && node scripts/mocha-failure-output.mjs && node scripts/failure-output.mjs node ava tap && node scripts/rust-direct-playwright-integration.mjs && node scripts/rust-custom-browser-playwright-integration.mjs && node scripts/rust-classic-browser-integration.mjs && node scripts/rust-top-packages-integration.mjs && node scripts/rust-generic-esbuild-integration.mjs && node scripts/rust-generic-tsc-integration.mjs && node scripts/rust-generic-build-matrix.mjs && node scripts/rust-vite-playwright-integration.mjs",
|
|
86
|
+
"test:engine-integrations": "cargo build -p supercov && node scripts/html-report-integration.mjs && node scripts/rust-process-supervision.mjs && node scripts/rust-direct-node-integration.mjs && node scripts/rust-public-run-integration.mjs && node scripts/rust-embedded-runtime-integration.mjs && node scripts/rust-direct-vitest-integration.mjs && node scripts/rust-direct-jest-integration.mjs && node scripts/mocha-failure-output.mjs && node scripts/failure-output.mjs node ava tap && node scripts/side-by-side.mjs node && node scripts/rust-direct-playwright-integration.mjs && node scripts/rust-custom-browser-playwright-integration.mjs && node scripts/rust-classic-browser-integration.mjs && node scripts/rust-top-packages-integration.mjs && node scripts/rust-generic-esbuild-integration.mjs && node scripts/rust-generic-tsc-integration.mjs && node scripts/rust-generic-build-matrix.mjs && node scripts/rust-vite-playwright-integration.mjs",
|
|
86
87
|
"test:platform": "cargo test --workspace && cargo build -p supercov && node scripts/rust-process-supervision.mjs && node scripts/workspace-crash-integration.mjs",
|
|
87
88
|
"test:native-package": "cargo build --release -p supercov && node scripts/native-package-integration.mjs && node scripts/native-release-set-integration.mjs",
|
|
88
89
|
"test:pypi-wheel": "node scripts/pypi-wheel-integration.mjs",
|
|
@@ -95,7 +96,7 @@
|
|
|
95
96
|
"test:test262": "cargo build --release -p supercov && node scripts/test262-equivalence.mjs",
|
|
96
97
|
"benchmark:check": "cargo build --release -p supercov && node scripts/rust-transform-benchmark.mjs",
|
|
97
98
|
"benchmark:python": "cargo build -p supercov && node scripts/python-benchmark.mjs",
|
|
98
|
-
"check": "cargo fmt --all -- --check && cargo clippy --workspace --all-targets -- -D warnings && npm run test && npm run test:release-tooling && npm run test:runtime && npm run test:rust-assets && npm run test:agent-commands && npm run test:assertions && npm run test:sweep-target && npm run test:skip-guard && npm run test:windows-tls && node scripts/package-preflight.mjs && node scripts/verify-binstall-metadata.mjs --offline",
|
|
99
|
+
"check": "cargo fmt --all -- --check && cargo clippy --workspace --all-targets -- -D warnings && npm run test && npm run test:release-tooling && npm run test:runtime && npm run test:action && npm run test:rust-assets && npm run test:agent-commands && npm run test:assertions && npm run test:sweep-target && npm run test:skip-guard && npm run test:windows-tls && node scripts/package-preflight.mjs && node scripts/verify-binstall-metadata.mjs --offline",
|
|
99
100
|
"release:check": "cargo clean && node scripts/sweep-target.mjs && npm run check && npm run test:engine && npm run test:go && npm run test:jvm && npm run test:launcher && npm run test:fixture && npm run test:watchdog && npm run test:engine-contract && npm run test:agent && npm run test:child-attribution && npm run test:host-loader && npm run test:python && npm run test:ruby-coverage && npm run test:rust-public-cargo && npm run test:packed-npx && npm run test:clang-mcdc && npm run benchmark:check",
|
|
100
101
|
"release:bump": "node scripts/bump-version.mjs",
|
|
101
102
|
"sweep": "node scripts/sweep-target.mjs",
|
|
@@ -104,11 +105,11 @@
|
|
|
104
105
|
"prepublishOnly": "npm run release:check",
|
|
105
106
|
"test:child-attribution": "cargo build -p supercov && node scripts/rust-child-attribution-integration.mjs",
|
|
106
107
|
"test:host-loader": "cargo build -p supercov && node scripts/rust-host-loader-integration.mjs",
|
|
107
|
-
"test:python": "cargo build -p supercov && node scripts/python-integration.mjs && node scripts/failure-output.mjs python",
|
|
108
|
-
"test:ruby-coverage": "cargo build -p supercov && node scripts/ruby-coverage-integration.mjs && node scripts/failure-output.mjs ruby",
|
|
109
|
-
"test:go": "cargo test --no-fail-fast -p supercov-engine --test go_frontend --test go_run && cargo build -p supercov && node scripts/failure-output.mjs go",
|
|
110
|
-
"test:jvm": "cargo test --no-fail-fast -p supercov-engine --test jvm_frontend --test jvm_run -- --include-ignored --test-threads=1",
|
|
111
|
-
"test:rust-public-cargo": "cargo build -p supercov && node scripts/rust-public-cargo-integration.mjs && node scripts/failure-output.mjs rust",
|
|
108
|
+
"test:python": "cargo build -p supercov && node scripts/python-integration.mjs && node scripts/failure-output.mjs python && node scripts/side-by-side.mjs python",
|
|
109
|
+
"test:ruby-coverage": "cargo build -p supercov && node scripts/ruby-coverage-integration.mjs && node scripts/failure-output.mjs ruby && node scripts/side-by-side.mjs ruby",
|
|
110
|
+
"test:go": "cargo test --no-fail-fast -p supercov-engine --test go_frontend --test go_run && cargo build -p supercov && node scripts/failure-output.mjs go && node scripts/side-by-side.mjs go",
|
|
111
|
+
"test:jvm": "cargo test --no-fail-fast -p supercov-engine --test jvm_frontend --test jvm_run -- --include-ignored --test-threads=1 && cargo build -p supercov && node scripts/side-by-side.mjs jvm",
|
|
112
|
+
"test:rust-public-cargo": "cargo build -p supercov && node scripts/rust-public-cargo-integration.mjs && node scripts/failure-output.mjs rust && node scripts/side-by-side.mjs rust",
|
|
112
113
|
"test:assertions": "cargo build -p supercov && node scripts/assertions-integration.mjs",
|
|
113
114
|
"docs:sync": "node scripts/sync-docs.mjs",
|
|
114
115
|
"docs:check": "node scripts/sync-docs.mjs --check",
|
|
@@ -119,14 +120,14 @@
|
|
|
119
120
|
"test:windows-tls": "node scripts/windows-tls-test.mjs"
|
|
120
121
|
},
|
|
121
122
|
"optionalDependencies": {
|
|
122
|
-
"@supercov/cli-darwin-arm64": "4.
|
|
123
|
-
"@supercov/cli-darwin-x64": "4.
|
|
124
|
-
"@supercov/cli-linux-arm64-gnu": "4.
|
|
125
|
-
"@supercov/cli-linux-arm64-musl": "4.
|
|
126
|
-
"@supercov/cli-linux-x64-gnu": "4.
|
|
127
|
-
"@supercov/cli-linux-x64-musl": "4.
|
|
128
|
-
"@supercov/cli-win32-arm64": "4.
|
|
129
|
-
"@supercov/cli-win32-x64": "4.
|
|
123
|
+
"@supercov/cli-darwin-arm64": "4.5.0",
|
|
124
|
+
"@supercov/cli-darwin-x64": "4.5.0",
|
|
125
|
+
"@supercov/cli-linux-arm64-gnu": "4.5.0",
|
|
126
|
+
"@supercov/cli-linux-arm64-musl": "4.5.0",
|
|
127
|
+
"@supercov/cli-linux-x64-gnu": "4.5.0",
|
|
128
|
+
"@supercov/cli-linux-x64-musl": "4.5.0",
|
|
129
|
+
"@supercov/cli-win32-arm64": "4.5.0",
|
|
130
|
+
"@supercov/cli-win32-x64": "4.5.0"
|
|
130
131
|
},
|
|
131
132
|
"peerDependencies": {
|
|
132
133
|
"@playwright/test": ">=1.55.0",
|
|
@@ -280,9 +280,10 @@ process.__SUPERCOV_FAILURE_OUTPUT__ ??= function supercovFailureOutput(runner) {
|
|
|
280
280
|
return [copy];
|
|
281
281
|
}
|
|
282
282
|
})();
|
|
283
|
-
// The copy lies in the project at .supercov/workspaces/workspace/<name
|
|
283
|
+
// The copy lies in the project at .supercov/workspaces/workspace/<name>,
|
|
284
|
+
// or at workspace-2 where it is one of several runs at once.
|
|
284
285
|
const projects = copies
|
|
285
|
-
.filter((copy) => /[\\/]\.supercov[\\/]workspaces[\\/]workspace[\\/][^\\/]+[\\/]$/.test(copy))
|
|
286
|
+
.filter((copy) => /[\\/]\.supercov[\\/]workspaces[\\/]workspace(?:-\d+)?[\\/][^\\/]+[\\/]$/.test(copy))
|
|
286
287
|
.map((copy) => resolve(copy, "../../../..") + sep);
|
|
287
288
|
// The path inside the copy of a rewritten file that lies under one of `roots`.
|
|
288
289
|
const rewrittenUnder = (roots, file) => {
|