@bensandee/tooling 0.70.0 → 0.72.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/README.md +22 -9
- package/dist/bin.mjs +3408 -2088
- package/package.json +7 -5
- package/tooling.schema.json +16 -1
package/README.md
CHANGED
|
@@ -28,17 +28,18 @@ The tool auto-detects project structure, CI platform, project type, and Docker p
|
|
|
28
28
|
|
|
29
29
|
### Project management
|
|
30
30
|
|
|
31
|
-
| Command | Description
|
|
32
|
-
| --------------------------------- |
|
|
33
|
-
| `tooling repo:sync [dir]` | Detect, generate, and sync project tooling (idempotent). First run prompts for release strategy, CI platform (if not detected), and formatter (if Prettier found). Subsequent runs are non-interactive.
|
|
34
|
-
| `tooling repo:sync --check [dir]` | Dry-run drift detection. Exits 1 if files would change. CI-friendly.
|
|
35
|
-
| `tooling checks:run` | Run project checks
|
|
31
|
+
| Command | Description |
|
|
32
|
+
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
33
|
+
| `tooling repo:sync [dir]` | Detect, generate, and sync project tooling (idempotent). First run prompts for release strategy, CI platform (if not detected), and formatter (if Prettier found). Subsequent runs are non-interactive. |
|
|
34
|
+
| `tooling repo:sync --check [dir]` | Dry-run drift detection. Exits 1 if files would change. CI-friendly. |
|
|
35
|
+
| `tooling checks:run` | Run project checks -- `bst checks:run --help` lists the ordered steps. Flags: `--skip`, `--add`, `--fail-fast`, `--verbose`, `--with-coverage`, `--coverage`, `--no-coverage`. |
|
|
36
|
+
| `tooling lint:types` | Type-aware linting (`oxlint --type-aware`, backed by `oxlint-tsgolint`). Flags: `--json`. See [Type-aware linting](#type-aware-linting) below. |
|
|
36
37
|
|
|
37
38
|
**Flags:** `--yes` (accept all defaults), `--no-ci` (negates `--ci`), `--no-prompt` (negates `--prompt`), `--eslint-plugin`
|
|
38
39
|
|
|
39
40
|
#### `checks:run`
|
|
40
41
|
|
|
41
|
-
Runs checks in order: build,
|
|
42
|
+
Runs checks in order: build, typecheck, lint, ascii:check (opt-in), lint:types, test, format (--check), knip, tooling:check, health:check (opt-in), docs:check, docker:build, docker:check. Checks without a matching script in `package.json` are silently skipped.
|
|
42
43
|
|
|
43
44
|
The `--skip` flag supports glob patterns via picomatch:
|
|
44
45
|
|
|
@@ -82,6 +83,16 @@ Because the decision is branch-aware, the generated CI workflow runs plain `pnpm
|
|
|
82
83
|
|
|
83
84
|
The generated `ci:check` script defaults to `pnpm check --skip 'docker:*'` since CI environments typically lack Docker support.
|
|
84
85
|
|
|
86
|
+
### Type-aware linting
|
|
87
|
+
|
|
88
|
+
For `stack: "typescript"` repos, `repo:sync` generates a `lint:types` script (`bst lint:types`, backed by a managed `oxlint-tsgolint` devDependency) and inserts a `lint:types` step into `checks:run` right after `lint`. It runs `oxlint --type-aware` and selects its findings by subtracting a plain `oxlint` run from it -- there is no maintained list of type-aware rule names, so a rule oxlint adds lands the day it ships.
|
|
89
|
+
|
|
90
|
+
**Two phases, and the tooling's own version carries them.** The **report** phase prints every finding, states plainly that they will block once a later tooling release flips to **enforce**, and exits 0. The flip is one constant in the tooling's source, so it reaches every consumer as an ordinary `@bensandee/tooling` version bump -- no coordinated migration, nothing to remember. `.tooling.json#lint.strictTypeAware` (default `false`) lets a repo opt into blocking during the report phase, ahead of the fleet-wide flip.
|
|
91
|
+
|
|
92
|
+
**The whole default rule set ships, and the tooling excludes nothing.** A repo's own `oxlint.config.ts` is the per-rule control -- turning a rule off there (`"typescript/<rule>": "off"`) is honored by the type-aware run, and since plain `oxlint` ignores type-aware rules entirely, such an entry never weakens `pnpm lint`. In increasing order of bluntness: turn off one rule in `oxlint.config.ts`, or skip the whole step with `.tooling.json#checks.skip: ["lint:types"]`.
|
|
93
|
+
|
|
94
|
+
A missing `oxlint-tsgolint` binary degrades to a notice at exit 0 in the report phase, and fails only when `lint.strictTypeAware` is set -- a repo that has not armed enforcement should not have CI broken by a platform gap, and a repo that has asked for the gate should not silently lose it.
|
|
95
|
+
|
|
85
96
|
### Custom blocks in workflows
|
|
86
97
|
|
|
87
98
|
Generated workflow files are regenerated on each `repo:sync` run. To preserve custom additions (extra steps, environment variables, etc.), wrap them in custom block markers:
|
|
@@ -268,7 +279,7 @@ pnpm test:coverage -> coverage:summary -> coverage:record -> coverage:stat
|
|
|
268
279
|
|
|
269
280
|
so every CI log ends with the trend table for the last 10 records.
|
|
270
281
|
|
|
271
|
-
The history file (`coverage-history.jsonl`) lives on a dedicated `bst/coverage-metrics` orphan branch -- never on `main`. This sidesteps branch protection (no privileged token needed beyond `contents: write`) and keeps `git log main` clean. `coverage:record` uses pure git plumbing (`hash-object` -> `mktree` -> `commit-tree` -> `push --force-with-lease`) so the working tree is never touched, and concurrent CI runs are handled safely via compare-and-swap with retry.
|
|
282
|
+
The history file (`coverage-history.jsonl`) lives on a dedicated `bst/coverage-metrics` orphan branch -- never on `main`. This sidesteps branch protection (no privileged token needed beyond `contents: write`) and keeps `git log main` clean. The `contents: write` workflow permission is a GitHub concern: on Forgejo the generated workflow declares no `permissions` block at all, and the push is authorized by the runner token's default access (or an Authorized Integration, where an instance restricts it). `coverage:record` uses pure git plumbing (`hash-object` -> `mktree` -> `commit-tree` -> `push --force-with-lease`) so the working tree is never touched, and concurrent CI runs are handled safely via compare-and-swap with retry.
|
|
272
283
|
|
|
273
284
|
#### The local ratchet
|
|
274
285
|
|
|
@@ -420,7 +431,7 @@ Each package is tagged independently using its own version, so packages in a mon
|
|
|
420
431
|
|
|
421
432
|
| Host | Username secret | Password secret |
|
|
422
433
|
| ------------------------- | --------------------------------- | --------------------------------- |
|
|
423
|
-
| `code.orangebikelabs.com` | `
|
|
434
|
+
| `code.orangebikelabs.com` | `OBL_REGISTRY_USERNAME` | `OBL_REGISTRY_PASSWORD` |
|
|
424
435
|
| `docker.io` | `DOCKERHUB_USERNAME` | `DOCKERHUB_PASSWORD` |
|
|
425
436
|
| `quay.io` | `QUAY_USERNAME` | `QUAY_PASSWORD` |
|
|
426
437
|
| `ghcr.io` | `GHCR_USERNAME` | `GHCR_PASSWORD` |
|
|
@@ -428,7 +439,9 @@ Each package is tagged independently using its own version, so packages in a mon
|
|
|
428
439
|
|
|
429
440
|
When `package.json#repository` and `.tooling.json#registryHost` are both absent the generator falls back to neutral `REGISTRY_USERNAME` / `REGISTRY_PASSWORD`.
|
|
430
441
|
|
|
431
|
-
|
|
442
|
+
Registry-specific names keep one credential per registry, so a repo publishing to more than one never has to decide which registry the generic pair belongs to.
|
|
443
|
+
|
|
444
|
+
**Names a forge will not accept.** A secret name must match `[A-Za-z_][A-Za-z0-9_]*` and must not start with `FORGEJO_`, `GITEA_`, `GITHUB_`, or a digit -- Forgejo answers `invalid secret name` and refuses to create it. The generator sanitizes every derived name against those rules, which is why `code.orangebikelabs.com` is `OBL_REGISTRY_*` rather than the `FORGEJO_*` the hostname would suggest, and why a host like `10.0.0.5:5000` or `forgejo.example.com` derives a `REGISTRY_`-prefixed name. `bst forgejo:secrets set` refuses an invalid name up front rather than passing it to the API.
|
|
432
445
|
|
|
433
446
|
**Forgejo setup:** On Forgejo, the username secret is your Forgejo account username, and the password secret can reuse the same token as `RELEASE_TOKEN`. The token needs write permissions on the org, package, and repository scopes. These permissions should be set for the **user** if the package is under a user namespace (e.g. `bensandee`), or the **organization** if it's under an org namespace (e.g. `orangebikelabs`). After migrating, the old `DOCKER_USERNAME` / `DOCKER_PASSWORD` user/org-level secrets can be deleted once every consumer has been regenerated.
|
|
434
447
|
|