@avi2dg/checks 0.51.0 → 0.52.1
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/.bun-version +1 -0
- package/CHANGELOG.md +22 -0
- package/README.md +24 -249
- package/commitlint.config.ts +0 -1
- package/dist/presets/knip.d.ts +1 -1
- package/dist/presets/knip.js +1 -1
- package/dist/templates/how-to.md +1 -1
- package/dist/templates/readme.md +1 -1
- package/dist/templates/tutorial.md +1 -1
- package/docs/bins.md +67 -0
- package/docs/gates/checks-advisories.md +2 -2
- package/docs/gates/checks-browser.md +5 -1
- package/docs/gates/checks-ci-wiring.md +18 -9
- package/docs/gates/checks-commit-identity.md +3 -3
- package/docs/gates/checks-copy.md +4 -0
- package/docs/gates/checks-docs.md +24 -3
- package/docs/gates/checks-exports.md +1 -1
- package/docs/gates/checks-frontend-syntax.md +5 -1
- package/docs/gates/checks-lint.md +2 -2
- package/docs/gates/checks-mutation-baseline.md +9 -5
- package/docs/gates/checks-mutation-compare.md +3 -3
- package/docs/gates/checks-mutation.md +9 -5
- package/docs/gates/checks-night-run.md +1 -1
- package/docs/gates/checks-secrets.md +2 -2
- package/docs/gates/checks-unused.md +1 -1
- package/docs/how-to/set-up-a-repository.md +142 -0
- package/docs/how-to/turn-on-the-css-families.md +35 -0
- package/docs/how-to/upgrade-the-kit.md +42 -0
- package/docs/shipped-files.md +36 -0
- package/package.json +11 -1
- package/src/delivery/bun-pin.ts +19 -5
- package/src/delivery/ci-wiring.ts +11 -77
- package/src/delivery/commit-identity.ts +6 -5
- package/src/delivery/runner-policy.ts +385 -0
- package/src/delivery/workflow-references.ts +1 -1
- package/src/docs/doc-templates.ts +1 -1
- package/src/docs/doc-versions.ts +137 -0
- package/src/docs/docs.ts +7 -0
- package/src/quality/comment-matchers.ts +1 -1
- package/src/testing/mutation-baseline-full.ts +23 -47
- package/src/testing/mutation-baseline-saved.ts +1 -1
- package/src/testing/mutation-baseline.ts +10 -8
- package/src/testing/mutation-scope-graph.ts +10 -19
- package/src/testing/mutation-scope.ts +8 -41
package/.bun-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.4.3
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
Every release of `@avi2dg/checks`, newest first, written by the release from its conventional commits.
|
|
4
4
|
|
|
5
|
+
## 0.52.1
|
|
6
|
+
|
|
7
|
+
Released 2026-10-25.
|
|
8
|
+
|
|
9
|
+
### Fixes
|
|
10
|
+
|
|
11
|
+
- **quality:** stop refusing published RFC citations as record pointers [#207](https://github.com/avi2d/checks/pull/207)
|
|
12
|
+
|
|
13
|
+
## 0.52.0
|
|
14
|
+
|
|
15
|
+
Released 2026-10-25.
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
- **docs:** short front door README and refuse hand copied pinned versions [#206](https://github.com/avi2d/checks/pull/206)
|
|
20
|
+
- **testing:** add 28-day refresh window for restored mutation baselines [#205](https://github.com/avi2d/checks/pull/205)
|
|
21
|
+
|
|
22
|
+
### Fixes
|
|
23
|
+
|
|
24
|
+
- **delivery:** refuse fork-reachable self-hosted runners, read fleet pins from config [#204](https://github.com/avi2d/checks/pull/204)
|
|
25
|
+
- upgrade fast-uri and zod past the October advisories [#202](https://github.com/avi2d/checks/pull/202)
|
|
26
|
+
|
|
5
27
|
## 0.51.0
|
|
6
28
|
|
|
7
29
|
Released 2026-10-23.
|
package/README.md
CHANGED
|
@@ -1,276 +1,51 @@
|
|
|
1
1
|
# checks
|
|
2
2
|
|
|
3
|
-
`@avi2dg/checks`
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
Each repository owns its workflows and native tool configs, as [Native settings](docs/configs/native-settings.md) maps.
|
|
3
|
+
`@avi2dg/checks` turns each rule a reviewer would otherwise have to remember into a program that runs on every pull request.
|
|
4
|
+
One command, `checks-lint`, judges a TypeScript repository's code, tests, commits, CI wiring and docs, and each failure names the file or line to fix.
|
|
5
|
+
Every Bun repository it holds moves to a new rule by upgrading one package, rather than by copying configs between repositories.
|
|
7
6
|
|
|
8
7
|
## Before you begin
|
|
9
8
|
|
|
10
|
-
<!-- generated prerequisites: bun run build writes it from package.json, .bun-version and scripts/doc-blocks.ts -->
|
|
11
|
-
|
|
12
9
|
- A git repository, whose history the range gates read.
|
|
13
|
-
- Bun
|
|
14
|
-
- The peer dependencies, at the exact versions the kit pins:
|
|
15
|
-
- `@effect/tsgo` 0.45.0
|
|
16
|
-
- `@swc/core` 1.16.2
|
|
17
|
-
- `dependency-cruiser` 18.4.0
|
|
18
|
-
- `effect` 4.0.0
|
|
19
|
-
- `jscpd` 5.3.2
|
|
20
|
-
- `oxlint` 1.83.0
|
|
21
|
-
- `oxlint-tsgolint` 7.0.2002
|
|
22
|
-
- `typescript` 7.0.2
|
|
23
|
-
- The optional peers, which only an opt-in check loads, at the exact versions the kit pins:
|
|
24
|
-
- `@axe-core/playwright` 4.13.0
|
|
25
|
-
- `html-validate` 11.16.0
|
|
26
|
-
- `playwright-core` 1.63.0
|
|
27
|
-
- `postcss-html` 2.0.0
|
|
28
|
-
- `postcss-value-parser` 4.2.0
|
|
29
|
-
- `stylelint` 17.16.0
|
|
30
|
-
- `stylelint-config-standard` 40.0.0
|
|
31
|
-
- `stylelint-plugin-use-baseline` 1.4.7
|
|
32
|
-
|
|
33
|
-
<!-- end generated prerequisites -->
|
|
10
|
+
- Bun, at the version the kit's `.bun-version` pins.
|
|
34
11
|
|
|
35
12
|
## Install
|
|
36
13
|
|
|
37
|
-
To
|
|
14
|
+
To hold a repository to the kit:
|
|
38
15
|
|
|
39
|
-
1. Add the kit
|
|
40
|
-
|
|
41
|
-
<!-- generated install: bun run build writes it from package.json and scripts/doc-blocks.ts -->
|
|
16
|
+
1. Add the kit:
|
|
42
17
|
|
|
43
18
|
```sh
|
|
44
|
-
bun add -d @avi2dg/checks
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
<!-- end generated install -->
|
|
48
|
-
|
|
49
|
-
1. Write `oxlint.config.ts` with the kit's builder, saying whether the sources are Effect programs:
|
|
50
|
-
|
|
51
|
-
```ts
|
|
52
|
-
import { defineConfig } from "@avi2dg/checks/oxlint";
|
|
53
|
-
|
|
54
|
-
export default defineConfig({ effect: true });
|
|
19
|
+
bun add -d @avi2dg/checks
|
|
55
20
|
```
|
|
56
21
|
|
|
57
|
-
1.
|
|
58
|
-
|
|
59
|
-
```
|
|
60
|
-
node_modules/
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
1. Extend the tsconfig fragment in `tsconfig.json`:
|
|
64
|
-
|
|
65
|
-
```json
|
|
66
|
-
{
|
|
67
|
-
"extends": "@avi2dg/checks/tsconfig.effect.json"
|
|
68
|
-
}
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
1. Copy the bunfig preset:
|
|
22
|
+
1. Pin the Bun version the kit runs on:
|
|
72
23
|
|
|
73
24
|
```sh
|
|
74
|
-
cp node_modules/@avi2dg/checks
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
1. Name the files nothing imports in `knip.config.ts`:
|
|
78
|
-
|
|
79
|
-
```ts
|
|
80
|
-
import { defineConfig } from "@avi2dg/checks/knip";
|
|
81
|
-
|
|
82
|
-
export default defineConfig({ entry: ["src/index.ts"] });
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
1. Write `dependency-cruiser.config.ts` only when the kit's import rules need an entry point or a boundary of the repository's own:
|
|
86
|
-
|
|
87
|
-
```ts
|
|
88
|
-
import { defineConfig } from "@avi2dg/checks/dependency-cruiser";
|
|
89
|
-
|
|
90
|
-
export default defineConfig({ orphans: ["^src/bin[.]ts$"] });
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
1. Add scripts to `package.json`, replacing the build entry with the repository's own build command:
|
|
94
|
-
|
|
95
|
-
```json
|
|
96
|
-
"build": "bun build src/index.ts --outdir dist --target node && checks-effect-scope",
|
|
97
|
-
"lint": "oxlint && checks-lint",
|
|
98
|
-
"typecheck": "tsc --noEmit && effect-tsgo diagnostics --project tsconfig.json --format text --strict",
|
|
99
|
-
"test": "checks-test"
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
1. Write the Bun version [Before you begin](#before-you-begin) names to `.bun-version`, which [checks-ci-wiring](docs/gates/checks-ci-wiring.md#bun-version) holds every setup-bun step to.
|
|
103
|
-
|
|
104
|
-
1. Run the scripts on every pull request in `.github/workflows/ci.yml`, fetching the whole history the range needs:
|
|
105
|
-
|
|
106
|
-
```yaml
|
|
107
|
-
on:
|
|
108
|
-
pull_request:
|
|
109
|
-
jobs:
|
|
110
|
-
checks:
|
|
111
|
-
runs-on: ubuntu-latest
|
|
112
|
-
steps:
|
|
113
|
-
- uses: actions/checkout@v5
|
|
114
|
-
with:
|
|
115
|
-
fetch-depth: 0
|
|
116
|
-
- uses: oven-sh/setup-bun@v2
|
|
117
|
-
with:
|
|
118
|
-
bun-version-file: .bun-version
|
|
119
|
-
- run: bun install --frozen-lockfile
|
|
120
|
-
- run: bun run build
|
|
121
|
-
- run: git diff --exit-code
|
|
122
|
-
- run: bun run lint
|
|
123
|
-
- run: bun run typecheck
|
|
124
|
-
- run: bun run test
|
|
25
|
+
cp node_modules/@avi2dg/checks/.bun-version .bun-version
|
|
125
26
|
```
|
|
126
27
|
|
|
127
|
-
|
|
28
|
+
1. Run the gates:
|
|
128
29
|
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
name: lint the title
|
|
132
|
-
env:
|
|
133
|
-
PR_TITLE: ${{ github.event.pull_request.title }}
|
|
134
|
-
GH_TOKEN: ${{ github.token }}
|
|
135
|
-
run: bunx checks-commit-title
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
A repository whose branch protection requires `commitlint` keeps that required status name while `commitlint.yml` goes away.
|
|
139
|
-
The same job reports the title step's outcome under that name on every run, which needs `statuses: write`:
|
|
140
|
-
|
|
141
|
-
```yaml
|
|
142
|
-
- name: report the title as commitlint
|
|
143
|
-
if: always()
|
|
144
|
-
env:
|
|
145
|
-
GH_TOKEN: ${{ github.token }}
|
|
146
|
-
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
147
|
-
OUTCOME: ${{ steps.title.outcome }}
|
|
148
|
-
run: |
|
|
149
|
-
state=failure
|
|
150
|
-
if [ "$OUTCOME" = success ]; then state=success; fi
|
|
151
|
-
gh api "repos/$GITHUB_REPOSITORY/statuses/${HEAD_SHA:-$GITHUB_SHA}" -f state="$state" -f context=commitlint -f target_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" --silent
|
|
30
|
+
```sh
|
|
31
|
+
bunx checks-lint
|
|
152
32
|
```
|
|
153
33
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
`bun run lint` then ends with `checks-lint: <count> gate(s) pass`.
|
|
157
|
-
|
|
158
|
-
## What runs
|
|
159
|
-
|
|
160
|
-
`checks-lint` runs each of these gates that applies to the repository, and names every one that fails.
|
|
161
|
-
A gate reads either the working tree or the range `checks-lint` resolves.
|
|
162
|
-
The table groups the gates by vector, the part of a repository each one judges.
|
|
163
|
-
|
|
164
|
-
<!-- generated gates: bun run build writes it from KIT_GATES in src/core/gates.ts and scripts/doc-blocks.ts -->
|
|
165
|
-
|
|
166
|
-
| Vector | Gate | Reads | Runs in |
|
|
167
|
-
| --- | --- | --- | --- |
|
|
168
|
-
| complexity | [`checks-suppressions-ratchet`](docs/gates/checks-suppressions-ratchet.md) | the range | every repository |
|
|
169
|
-
| complexity | [`checks-repetition`](docs/gates/checks-repetition.md) | the range | a repository tracking `*.ts` or `*.tsx` |
|
|
170
|
-
| complexity | [`checks-unused`](docs/gates/checks-unused.md) | the working tree | a repository tracking `*.ts` or `*.tsx` or `*.astro` |
|
|
171
|
-
| complexity | [`checks-exports`](docs/gates/checks-exports.md) | the range | a repository tracking `*.ts` or `*.tsx` |
|
|
172
|
-
| quality | [`checks-lint-coverage`](docs/gates/checks-lint-coverage.md) | the working tree | a repository tracking `*.ts` or `*.tsx` or `*.astro` |
|
|
173
|
-
| quality | [`checks-comment-gate`](docs/gates/checks-comment-gate.md) | the range | every repository |
|
|
174
|
-
| quality | [`checks-effect-scope`](docs/gates/checks-effect-scope.md) | the working tree | a repository tracking `oxlint.config.ts` |
|
|
175
|
-
| quality | [`checks-frontend-syntax`](docs/gates/checks-frontend-syntax.md) | the working tree | a repository tracking `frontend-syntax.json` |
|
|
176
|
-
| quality | [`checks-css-size`](docs/gates/checks-css-size.md) | the working tree | a repository tracking `*.css` |
|
|
177
|
-
| quality | [`checks-no-plain-js`](docs/gates/checks-no-plain-js.md) | the working tree | a repository tracking `*.ts` or `*.tsx` |
|
|
178
|
-
| testing | [`checks-test-layout`](docs/gates/checks-test-layout.md) | the working tree | a repository tracking `*.ts` or `*.tsx` |
|
|
179
|
-
| testing | [`checks-quarantine-clock`](docs/gates/checks-quarantine-clock.md) | the range | every repository |
|
|
180
|
-
| docs | [`checks-docs`](docs/gates/checks-docs.md) | the range, and every agent file at the head commit | every repository |
|
|
181
|
-
| docs | [`checks-copy`](docs/gates/checks-copy.md) | the working tree | a repository tracking `copy.json` |
|
|
182
|
-
| delivery | [`checks-commit-identity`](docs/gates/checks-commit-identity.md) | the range | every repository |
|
|
183
|
-
| delivery | [`checks-ci-wiring`](docs/gates/checks-ci-wiring.md) | the working tree | every repository |
|
|
184
|
-
| delivery | [`checks-secrets`](docs/gates/checks-secrets.md) | the range | every repository |
|
|
185
|
-
| dependencies | [`checks-imports`](docs/gates/checks-imports.md) | the working tree | a repository tracking `*.ts` or `*.tsx` |
|
|
186
|
-
| dependencies | [`checks-advisories`](docs/gates/checks-advisories.md) | the range | a repository tracking `bun.lock` |
|
|
187
|
-
|
|
188
|
-
<!-- end generated gates -->
|
|
189
|
-
|
|
190
|
-
These bins run on their own:
|
|
191
|
-
|
|
192
|
-
- [`checks-test`](docs/gates/checks-test.md) runs the suite as `scripts.test` and refuses a skip without a reason at its test site.
|
|
193
|
-
- [`checks-flake`](docs/gates/checks-flake.md) runs the suite on a schedule and records the seeds a flaky test fails with.
|
|
194
|
-
- [`checks-mutation`](docs/gates/checks-mutation.md) runs Stryker for scoped checks and refuses a full run outside CI.
|
|
195
|
-
- [`checks-mutation-compare`](docs/gates/checks-mutation-compare.md) compares the mutants of two reports and lists each one that regresses.
|
|
196
|
-
- [`checks-mutation-baseline`](docs/gates/checks-mutation-baseline.md) restores the newest mutation baseline from `main`, saves it on a self-hosted runner's disk in place of an artifact, and deletes superseded baselines after a `main` run.
|
|
197
|
-
- [`checks-mutation-scope`](docs/gates/checks-mutation-scope.md) turns a branch's diff into the files its mutation runs mutate.
|
|
198
|
-
- [`checks-subsumed-tests`](docs/gates/checks-subsumed-tests.md) lists each test another test subsumes in a mutation run.
|
|
199
|
-
- [`checks-night-run`](docs/gates/checks-night-run.md) opens or comments on one GitHub issue per finding of a night run on `main`, each file whose mutation score fell and each failing test.
|
|
200
|
-
- [`checks-changelog`](docs/gates/checks-changelog.md) writes the pending release into `CHANGELOG.md` from the conventional commits since the last release.
|
|
201
|
-
- [`checks-release-notes`](docs/gates/checks-release-notes.md) writes one `CHANGELOG.md` section to a file for a GitHub release.
|
|
202
|
-
- [`checks-release-report`](docs/gates/checks-release-report.md) tells whether the history holds unreleased features or fixes since the last tag.
|
|
203
|
-
- [`checks-release-pr`](docs/gates/checks-release-pr.md) opens or refreshes the pull request that releases the next version, and dispatches its checks.
|
|
204
|
-
- [`checks-release-tag`](docs/gates/checks-release-tag.md) tags a landed release commit with its version and dispatches the release workflow on the tag.
|
|
205
|
-
- [`checks-vendor`](docs/gates/checks-vendor.md) pins each library its `prepare` arguments name to a shared read-only clone and links it under `repos/`.
|
|
206
|
-
- [`checks-browser`](docs/gates/checks-browser.md) opens a product's built pages in Chrome and fails on the layout, keyboard, motion, accessibility, nesting and asset checks its `browser-checks.json` declares.
|
|
207
|
-
- [`checks-commit-title`](docs/gates/checks-commit-title.md) lints the pull request title in one step of the `ci` job.
|
|
208
|
-
- [`checks-docs-only`](docs/gates/checks-docs-only.md) tells whether a change touches only top-level Markdown and Markdown under `docs/`, so a docs-only change skips the full run.
|
|
34
|
+
Each gate that fails names the file it needs, and [Set up a repository](docs/how-to/set-up-a-repository.md) writes every one.
|
|
35
|
+
A repository the kit holds ends with `checks-lint: <count> gate(s) pass`.
|
|
209
36
|
|
|
210
|
-
|
|
211
|
-
oxlint runs through its own tool, as the pages under Related topics say.
|
|
37
|
+
## Find the page you need
|
|
212
38
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
To move a repository to a newer release of the kit:
|
|
216
|
-
|
|
217
|
-
1. Run the install line again, which moves the kit to its newest release and the peers to the versions it pins.
|
|
218
|
-
A repository that opted in to `checks-browser`, `checks-frontend-syntax` or `checks-copy` also reruns the `bun add` line on its page.
|
|
219
|
-
1. Run `bun run build`, whose `checks-effect-scope` rewrites the Effect override and the kit's severities in `tsconfig.json` when a release changes them.
|
|
220
|
-
A severity key the release drops stays in `tsconfig.json` until the repository removes it.
|
|
221
|
-
1. Copy `node_modules/@avi2dg/checks/bunfig.toml` over `bunfig.toml` again, since `checks-test-layout` compares the copy with the installed preset.
|
|
222
|
-
1. Run `bun run lint`, `bun run typecheck` and `bun run test`.
|
|
223
|
-
|
|
224
|
-
The repository's lockfile pins the kit, so a repository moves only when it runs these steps.
|
|
225
|
-
[CHANGELOG.md](CHANGELOG.md), shipped in the package, lists what each release changed.
|
|
226
|
-
|
|
227
|
-
## Turn on the CSS families a repository needs
|
|
228
|
-
|
|
229
|
-
A repository that declares `frontend-syntax.json` writes `stylelint.config.ts` with the families it needs:
|
|
230
|
-
|
|
231
|
-
```ts
|
|
232
|
-
import { defineConfig } from "@avi2dg/checks/stylelint";
|
|
233
|
-
|
|
234
|
-
export default defineConfig({
|
|
235
|
-
baseline: "widely",
|
|
236
|
-
tokens: ["src/styles/tokens.css"],
|
|
237
|
-
bem: true,
|
|
238
|
-
flatSelectors: true,
|
|
239
|
-
noPageHas: true,
|
|
240
|
-
});
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
[checks-frontend-syntax](docs/gates/checks-frontend-syntax.md#what-it-reads) says what each key takes and which family it turns on.
|
|
244
|
-
`noPageHas` sees a `:has` nested under a page selector only together with `flatSelectors`, which refuses the nesting.
|
|
245
|
-
|
|
246
|
-
## Where things are
|
|
247
|
-
|
|
248
|
-
Every path is relative to the installed package, `node_modules/@avi2dg/checks/`.
|
|
249
|
-
|
|
250
|
-
<!-- generated shipped: bun run build writes it from package.json and scripts/doc-blocks.ts -->
|
|
251
|
-
|
|
252
|
-
| Path | What it holds |
|
|
39
|
+
| To | Read |
|
|
253
40
|
| --- | --- |
|
|
254
|
-
|
|
|
255
|
-
|
|
|
256
|
-
|
|
|
257
|
-
|
|
|
258
|
-
|
|
|
259
|
-
|
|
|
260
|
-
|
|
|
261
|
-
| `dist/` | the compiled oxlint plugins, the config builders `@avi2dg/checks/oxlint`, `@avi2dg/checks/knip`, `@avi2dg/checks/dependency-cruiser` and `@avi2dg/checks/stylelint` resolve to, and the doc templates, one template per kind of doc file |
|
|
262
|
-
| `oxlintrc.json` | the oxlint `base` as a config a `.oxlintrc.json` extends by path, which the build writes |
|
|
263
|
-
| `stryker.preset.js` | the Stryker mutation-testing preset, which refuses a full run outside CI |
|
|
264
|
-
| `tsconfig.effect.json` | the tsconfig fragment with the shared compiler options and the Effect language-service block |
|
|
265
|
-
| `ts-reset.d.ts` | the two ts-reset rules `tsconfig.effect.json` lists in `files` |
|
|
266
|
-
|
|
267
|
-
<!-- end generated shipped -->
|
|
41
|
+
| write every file the gates ask for | [Set up a repository](docs/how-to/set-up-a-repository.md) |
|
|
42
|
+
| move to a newer release | [Upgrade the kit](docs/how-to/upgrade-the-kit.md) |
|
|
43
|
+
| turn on the CSS checks | [Turn on the CSS families](docs/how-to/turn-on-the-css-families.md) |
|
|
44
|
+
| look up a gate or a bin | [The bins](docs/bins.md) |
|
|
45
|
+
| look up a shared config | [Native settings](docs/configs/native-settings.md) |
|
|
46
|
+
| find a file the package ships | [The shipped files](docs/shipped-files.md) |
|
|
47
|
+
| learn why the kit is shaped this way | [Why it is shaped this way](docs/design.md) |
|
|
268
48
|
|
|
269
49
|
## Related topics
|
|
270
50
|
|
|
271
|
-
- [
|
|
272
|
-
- [The Effect rules](docs/configs/effect-rules.md)
|
|
273
|
-
- [The TypeScript rules](docs/configs/typescript-rules.md)
|
|
274
|
-
- [The dependency rules](docs/configs/dependency-rules.md)
|
|
275
|
-
- [The commit message lint](docs/configs/commit-messages.md)
|
|
276
|
-
- [Why it is shaped this way](docs/design.md)
|
|
51
|
+
- [CHANGELOG.md](CHANGELOG.md)
|
package/commitlint.config.ts
CHANGED
package/dist/presets/knip.d.ts
CHANGED
|
@@ -2,5 +2,5 @@ import type { KnipConfiguration } from "knip";
|
|
|
2
2
|
export type ChecksKnipConfig = Omit<KnipConfiguration, "entry" | "include"> & {
|
|
3
3
|
readonly entry: readonly string[];
|
|
4
4
|
};
|
|
5
|
-
export declare const DEFAULT_ENTRY: readonly ["tests/**/*.test.ts", "dependency-cruiser.config.ts"];
|
|
5
|
+
export declare const DEFAULT_ENTRY: readonly ["tests/**/*.test.ts", "dependency-cruiser.config.ts", "oxlint.config.ts"];
|
|
6
6
|
export declare function defineConfig({ entry, ...rest }: ChecksKnipConfig): KnipConfiguration;
|
package/dist/presets/knip.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/quality/presets/knip.ts
|
|
2
|
-
var DEFAULT_ENTRY = ["tests/**/*.test.ts", "dependency-cruiser.config.ts"];
|
|
2
|
+
var DEFAULT_ENTRY = ["tests/**/*.test.ts", "dependency-cruiser.config.ts", "oxlint.config.ts"];
|
|
3
3
|
var REFUSED_ENTRY = "@avi2dg/checks/knip: set entry to the files nothing imports, or [] when package.json scripts and tests name them all";
|
|
4
4
|
function isGlobList(value) {
|
|
5
5
|
return Array.isArray(value) && value.every((glob) => typeof glob === "string" && glob !== "");
|
package/dist/templates/how-to.md
CHANGED
package/dist/templates/readme.md
CHANGED
package/docs/bins.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
kind: reference
|
|
3
|
+
audience: consumers
|
|
4
|
+
---
|
|
5
|
+
# The bins
|
|
6
|
+
|
|
7
|
+
The kit ships one bin per check, each named `checks-` and called from a package script.
|
|
8
|
+
|
|
9
|
+
## What runs
|
|
10
|
+
|
|
11
|
+
`checks-lint` runs each of these gates that applies to the repository, and names every one that fails.
|
|
12
|
+
A gate reads either the working tree or the range `checks-lint` resolves.
|
|
13
|
+
The table groups the gates by vector, the part of a repository each one judges.
|
|
14
|
+
|
|
15
|
+
<!-- generated gates: bun run build writes it from KIT_GATES in src/core/gates.ts and scripts/doc-blocks.ts -->
|
|
16
|
+
|
|
17
|
+
| Vector | Gate | Reads | Runs in |
|
|
18
|
+
| --- | --- | --- | --- |
|
|
19
|
+
| complexity | [`checks-suppressions-ratchet`](gates/checks-suppressions-ratchet.md) | the range | every repository |
|
|
20
|
+
| complexity | [`checks-repetition`](gates/checks-repetition.md) | the range | a repository tracking `*.ts` or `*.tsx` |
|
|
21
|
+
| complexity | [`checks-unused`](gates/checks-unused.md) | the working tree | a repository tracking `*.ts` or `*.tsx` or `*.astro` |
|
|
22
|
+
| complexity | [`checks-exports`](gates/checks-exports.md) | the range | a repository tracking `*.ts` or `*.tsx` |
|
|
23
|
+
| quality | [`checks-lint-coverage`](gates/checks-lint-coverage.md) | the working tree | a repository tracking `*.ts` or `*.tsx` or `*.astro` |
|
|
24
|
+
| quality | [`checks-comment-gate`](gates/checks-comment-gate.md) | the range | every repository |
|
|
25
|
+
| quality | [`checks-effect-scope`](gates/checks-effect-scope.md) | the working tree | a repository tracking `oxlint.config.ts` |
|
|
26
|
+
| quality | [`checks-frontend-syntax`](gates/checks-frontend-syntax.md) | the working tree | a repository tracking `frontend-syntax.json` |
|
|
27
|
+
| quality | [`checks-css-size`](gates/checks-css-size.md) | the working tree | a repository tracking `*.css` |
|
|
28
|
+
| quality | [`checks-no-plain-js`](gates/checks-no-plain-js.md) | the working tree | a repository tracking `*.ts` or `*.tsx` |
|
|
29
|
+
| testing | [`checks-test-layout`](gates/checks-test-layout.md) | the working tree | a repository tracking `*.ts` or `*.tsx` |
|
|
30
|
+
| testing | [`checks-quarantine-clock`](gates/checks-quarantine-clock.md) | the range | every repository |
|
|
31
|
+
| docs | [`checks-docs`](gates/checks-docs.md) | the range, and every agent file at the head commit | every repository |
|
|
32
|
+
| docs | [`checks-copy`](gates/checks-copy.md) | the working tree | a repository tracking `copy.json` |
|
|
33
|
+
| delivery | [`checks-commit-identity`](gates/checks-commit-identity.md) | the range | every repository |
|
|
34
|
+
| delivery | [`checks-ci-wiring`](gates/checks-ci-wiring.md) | the working tree | every repository |
|
|
35
|
+
| delivery | [`checks-secrets`](gates/checks-secrets.md) | the range | every repository |
|
|
36
|
+
| dependencies | [`checks-imports`](gates/checks-imports.md) | the working tree | a repository tracking `*.ts` or `*.tsx` |
|
|
37
|
+
| dependencies | [`checks-advisories`](gates/checks-advisories.md) | the range | a repository tracking `bun.lock` |
|
|
38
|
+
|
|
39
|
+
<!-- end generated gates -->
|
|
40
|
+
|
|
41
|
+
These bins run on their own:
|
|
42
|
+
|
|
43
|
+
- [`checks-test`](gates/checks-test.md) runs the suite as `scripts.test` and refuses a skip without a reason at its test site.
|
|
44
|
+
- [`checks-flake`](gates/checks-flake.md) runs the suite on a schedule and records the seeds a flaky test fails with.
|
|
45
|
+
- [`checks-mutation`](gates/checks-mutation.md) runs Stryker for scoped checks and refuses a full run outside CI.
|
|
46
|
+
- [`checks-mutation-compare`](gates/checks-mutation-compare.md) compares the mutants of two reports and lists each one that regresses.
|
|
47
|
+
- [`checks-mutation-baseline`](gates/checks-mutation-baseline.md) restores the newest mutation baseline from `main`, saves it on a self-hosted runner's disk in place of an artifact, and deletes superseded baselines after a `main` run.
|
|
48
|
+
- [`checks-mutation-scope`](gates/checks-mutation-scope.md) turns a branch's diff into the files its mutation runs mutate.
|
|
49
|
+
- [`checks-subsumed-tests`](gates/checks-subsumed-tests.md) lists each test another test subsumes in a mutation run.
|
|
50
|
+
- [`checks-night-run`](gates/checks-night-run.md) opens or comments on one GitHub issue per finding of a night run on `main`, each file whose mutation score fell and each failing test.
|
|
51
|
+
- [`checks-changelog`](gates/checks-changelog.md) writes the pending release into `CHANGELOG.md` from the conventional commits since the last release.
|
|
52
|
+
- [`checks-release-notes`](gates/checks-release-notes.md) writes one `CHANGELOG.md` section to a file for a GitHub release.
|
|
53
|
+
- [`checks-release-report`](gates/checks-release-report.md) tells whether the history holds unreleased features or fixes since the last tag.
|
|
54
|
+
- [`checks-release-pr`](gates/checks-release-pr.md) opens or refreshes the pull request that releases the next version, and dispatches its checks.
|
|
55
|
+
- [`checks-release-tag`](gates/checks-release-tag.md) tags a landed release commit with its version and dispatches the release workflow on the tag.
|
|
56
|
+
- [`checks-vendor`](gates/checks-vendor.md) pins each library its `prepare` arguments name to a shared read-only clone and links it under `repos/`.
|
|
57
|
+
- [`checks-browser`](gates/checks-browser.md) opens a product's built pages in Chrome and fails on the layout, keyboard, motion, accessibility, nesting and asset checks its `browser-checks.json` declares.
|
|
58
|
+
- [`checks-commit-title`](gates/checks-commit-title.md) lints the pull request title in one step of the `ci` job.
|
|
59
|
+
- [`checks-docs-only`](gates/checks-docs-only.md) tells whether a change touches only top-level Markdown and Markdown under `docs/`, so a docs-only change skips the full run.
|
|
60
|
+
|
|
61
|
+
`checks-lint` has [its own page](gates/checks-lint.md), which says which range it resolves.
|
|
62
|
+
oxlint runs through its own tool, as [Native settings](configs/native-settings.md) says.
|
|
63
|
+
|
|
64
|
+
## Related topics
|
|
65
|
+
|
|
66
|
+
- [Set up a repository](how-to/set-up-a-repository.md)
|
|
67
|
+
- [Native settings](configs/native-settings.md)
|
|
@@ -22,8 +22,8 @@ It reads `bun.lock` at the base and at the head of the range from git, not from
|
|
|
22
22
|
It scans copies of both in a scratch directory with an empty config, so a repository's own `osv-scanner.toml` takes no part.
|
|
23
23
|
It reads the advisories OSV.dev exports for npm, which hold GitHub's reviewed advisories and OpenSSF's reports of malicious packages.
|
|
24
24
|
|
|
25
|
-
It runs OSV-Scanner
|
|
26
|
-
On first use it downloads the build from the scanner's GitHub release into `~/.cache/avi2dg-checks/osv-scanner
|
|
25
|
+
It runs the OSV-Scanner release `src/dependencies/osv-scanner.ts` pins, by the SHA-256 of each platform's build.
|
|
26
|
+
On first use it downloads the build from the scanner's GitHub release into `~/.cache/avi2dg-checks/osv-scanner/<version>/`.
|
|
27
27
|
It checks the SHA-256 again on every run and exits 2 on a copy that differs.
|
|
28
28
|
Builds are pinned for macOS and Linux, each on x64 and arm64.
|
|
29
29
|
On any other platform it exits 2, and no setting runs a scanner other than the pinned build.
|
|
@@ -156,10 +156,14 @@ So are a `motion` check with no state whose `reducedMotion` is `reduce`, a `keyb
|
|
|
156
156
|
It drives the Chrome the machine has, which `CHROME_PATH` names, or Chrome's standard install when it is unset.
|
|
157
157
|
The product installs the optional peers the runner loads, at the versions the kit pins:
|
|
158
158
|
|
|
159
|
+
<!-- generated install: bun run build writes it from package.json and scripts/doc-blocks.ts -->
|
|
160
|
+
|
|
159
161
|
```sh
|
|
160
|
-
bun add -d
|
|
162
|
+
bun add -d @axe-core/playwright@4.13.0 html-validate@11.16.0 playwright-core@1.63.0
|
|
161
163
|
```
|
|
162
164
|
|
|
165
|
+
<!-- end generated install -->
|
|
166
|
+
|
|
163
167
|
## Arguments
|
|
164
168
|
|
|
165
169
|
```sh
|
|
@@ -47,10 +47,18 @@ The call counts as a command of its own or inside a command substitution, never
|
|
|
47
47
|
A here-document that `sh`, `bash`, `dash`, `ksh` or `zsh` reads is a script, and its calls count.
|
|
48
48
|
The text of any other here-document is data, so a call there counts only inside a command substitution when the delimiter is unquoted.
|
|
49
49
|
A mutation job never names `CI_RUNS_ON` directly in `runs-on`, as `vars.CI_RUNS_ON` or `vars['CI_RUNS_ON']`, so an override for an outage cannot send its mutation runs to hosted runners.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
In a private repository any other job that names `CI_RUNS_ON` in `runs-on` carries exactly the hosted-default expression `${{ vars.CI_RUNS_ON || 'ubuntu-latest' }}`.
|
|
51
|
+
A public repository carries no self-hosted runner on a job a fork can reach, because a pull request from a fork would run its own code on that runner.
|
|
52
|
+
A fork reaches a job through `pull_request`, `pull_request_target`, `pull_request_review`, `pull_request_review_comment` or `issue_comment`, directly, through a local reusable workflow a reached job calls, or through a `workflow_run` trigger that names a reached workflow.
|
|
53
|
+
Such a job refuses a literal `self-hosted` label, a label that interpolates an expression, a label in a set declared under `checks.mutationRunner` or `checks.selfHostedRunners`, a runner `group` and any other expression.
|
|
54
|
+
A `runs-on` that is exactly `${{ matrix.<key> }}` judges each matrix value as its own labels.
|
|
55
|
+
The values for the key are the combinations its axis values form, without combinations an `exclude` entry removes, plus its `include` rows, which merge into the original combinations they match and otherwise run as their own combinations.
|
|
56
|
+
It refuses a value that names `self-hosted` or falls inside a label set declared under `checks.mutationRunner` or `checks.selfHostedRunners`.
|
|
57
|
+
Any other expression refuses as unresolvable.
|
|
58
|
+
A job on `push` or another trigger no fork reaches may still name self-hosted labels.
|
|
59
|
+
In a private repository each mutation job carries exactly the labels the consumer declares in `package.json` under `checks.mutationRunner`.
|
|
60
|
+
Every other job there carries exactly the hosted-default expression, or exactly one of the label sets the consumer declares under `checks.selfHostedRunners`.
|
|
61
|
+
A repository without those declarations fails each job they would pin until it declares them.
|
|
54
62
|
The check knows a repository is private only from GitHub's event, so a run outside CI judges only the rules that hold in either.
|
|
55
63
|
|
|
56
64
|
### Bun version
|
|
@@ -68,18 +76,19 @@ Else the `package.json` at the workspace root reads the same way.
|
|
|
68
76
|
Else setup-bun installs latest.
|
|
69
77
|
A blank version counts as none.
|
|
70
78
|
A repository passes by writing the fleet version to `.bun-version` and naming that file in each step's `with.bun-version-file`.
|
|
79
|
+
The fleet version is the version the kit ships in its own `.bun-version`.
|
|
71
80
|
The step fails the check when the version is missing or differs from the fleet bun version.
|
|
72
81
|
A range fails because it differs from the fleet version.
|
|
73
82
|
A version built from an expression fails because it cannot be shown equal before the run.
|
|
74
83
|
This rule skips a repository with no setup-bun step.
|
|
75
|
-
|
|
76
|
-
A bump moves both together, so a kit release that moves the fleet version turns each consumer red until its pin follows.
|
|
84
|
+
A kit release that moves the fleet version turns each consumer red until its pin follows.
|
|
77
85
|
Each refusal names the workflow file and line, the version found and where it was read, and the fleet version.
|
|
78
86
|
|
|
79
87
|
## What it reads
|
|
80
88
|
|
|
81
|
-
The bin reads `.github/workflows/*.yml`, `*.yaml`, the `scripts` in `package.json` and the shell scripts those steps and scripts run from the working tree.
|
|
89
|
+
The bin reads `.github/workflows/*.yml`, `*.yaml`, the `scripts` and `checks` runners in `package.json` and the shell scripts those steps and scripts run from the working tree.
|
|
82
90
|
It reads each file a setup-bun step names for its version.
|
|
91
|
+
It reads the fleet pin from the kit's own `.bun-version`.
|
|
83
92
|
It reads the target branch from `GITHUB_BASE_REF`, then from `refs/remotes/origin/HEAD` and then from the event file `GITHUB_EVENT_PATH` names.
|
|
84
93
|
It reads whether the repository is private from `repository.private` in that event file.
|
|
85
94
|
It parses the workflows with `Bun.YAML` without executing them.
|
|
@@ -94,7 +103,7 @@ It takes no arguments.
|
|
|
94
103
|
| --- | --- |
|
|
95
104
|
| 0 | Every required command has a reachable step. |
|
|
96
105
|
| 1 | A required command is missing or blocked, a job runs on the wrong runner, a workflow names a missing workflow or job, or a setup-bun step drifts from the fleet bun version. |
|
|
97
|
-
| 2 | A workflow or `package.json` cannot be decoded. |
|
|
106
|
+
| 2 | A workflow or `package.json` cannot be decoded, or the kit's own `.bun-version` is missing, unreadable or blank. |
|
|
98
107
|
|
|
99
108
|
## Sample output
|
|
100
109
|
|
|
@@ -110,7 +119,7 @@ A mutation job that names `CI_RUNS_ON` in `runs-on` produces a report like this:
|
|
|
110
119
|
|
|
111
120
|
```
|
|
112
121
|
ci-wiring: 1 job(s) run on the wrong runner:
|
|
113
|
-
.github/workflows/mutation-compare.yml job mutation-compare: a mutation job reads CI_RUNS_ON, so an override moves its mutation runs off
|
|
122
|
+
.github/workflows/mutation-compare.yml job mutation-compare: a mutation job reads CI_RUNS_ON, so an override moves its mutation runs off [self-hosted, gpu, x64]; set runs-on: [self-hosted, gpu, x64]
|
|
114
123
|
```
|
|
115
124
|
|
|
116
125
|
A reference to a missing workflow produces a report like this:
|
|
@@ -24,7 +24,7 @@ Such a commit may carry a `Co-authored-by` trailer naming that bot, since GitHub
|
|
|
24
24
|
Each person can be any form npm allows, an object with `name` and optional `email` and `url`, or a string such as `Avi <avi@example.com> (https://example.com)`.
|
|
25
25
|
A person with both a name and an email is an allowed author.
|
|
26
26
|
A person without an email is ignored.
|
|
27
|
-
When no person carries an email, the
|
|
27
|
+
When no person carries an email, no identity is allowed, so the check fails every commit until the repository declares its owners.
|
|
28
28
|
The bin reads commits from git and parses their trailer blocks.
|
|
29
29
|
|
|
30
30
|
## Arguments
|
|
@@ -42,7 +42,7 @@ With one argument, it checks that commit alone.
|
|
|
42
42
|
| Code | Result |
|
|
43
43
|
| --- | --- |
|
|
44
44
|
| 0 | Every commit carries an allowed identity. |
|
|
45
|
-
| 1 | A commit carries a foreign identity. |
|
|
45
|
+
| 1 | A commit carries a foreign identity, or `package.json` declares no authors. |
|
|
46
46
|
| 2 | A ref, argument or `package.json` cannot be decoded. |
|
|
47
47
|
|
|
48
48
|
## Sample output
|
|
@@ -51,7 +51,7 @@ With one argument, it checks that commit alone.
|
|
|
51
51
|
commit-identity: 1 of 1 commit(s) in HEAD carry a foreign identity:
|
|
52
52
|
79fa94f9f027 feat: foreign
|
|
53
53
|
author someone <someone@example.com>
|
|
54
|
-
allowed:
|
|
54
|
+
allowed: Repo Owner <owner@example.com>
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
## When it runs
|
|
@@ -66,10 +66,14 @@ It reads the working tree, so an uncommitted file is judged like a committed one
|
|
|
66
66
|
|
|
67
67
|
A repository that declares an HTML file installs the optional peer the gate loads for it, at the version the kit pins:
|
|
68
68
|
|
|
69
|
+
<!-- generated install: bun run build writes it from package.json and scripts/doc-blocks.ts -->
|
|
70
|
+
|
|
69
71
|
```sh
|
|
70
72
|
bun add -d html-validate@11.16.0
|
|
71
73
|
```
|
|
72
74
|
|
|
75
|
+
<!-- end generated install -->
|
|
76
|
+
|
|
73
77
|
## Arguments
|
|
74
78
|
|
|
75
79
|
```sh
|