@bensandee/tooling 0.69.0 → 0.71.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 +33 -19
- package/dist/bin.mjs +8794 -5991
- package/package.json +7 -6
- package/tooling.schema.json +32 -0
package/README.md
CHANGED
|
@@ -32,13 +32,14 @@ The tool auto-detects project structure, CI platform, project type, and Docker p
|
|
|
32
32
|
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
33
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
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
|
|
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
|
-
**Flags:** `--yes` (accept all defaults), `--no-ci
|
|
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
|
|
|
@@ -61,6 +62,7 @@ tooling checks:run --add e2e
|
|
|
61
62
|
Explicit flags always win, regardless of branch:
|
|
62
63
|
|
|
63
64
|
- `--with-coverage` -- force the `test` step to run with coverage.
|
|
65
|
+
- `--coverage` -- the same thing, spelled as the positive of `--no-coverage`.
|
|
64
66
|
- `--no-coverage` -- force it to run without coverage.
|
|
65
67
|
|
|
66
68
|
If both are passed, `--no-coverage` wins.
|
|
@@ -81,6 +83,16 @@ Because the decision is branch-aware, the generated CI workflow runs plain `pnpm
|
|
|
81
83
|
|
|
82
84
|
The generated `ci:check` script defaults to `pnpm check --skip 'docker:*'` since CI environments typically lack Docker support.
|
|
83
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
|
+
|
|
84
96
|
### Custom blocks in workflows
|
|
85
97
|
|
|
86
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:
|
|
@@ -125,24 +137,24 @@ Opt out entirely with `"pnpmWorkspace": false` in `.tooling.json`; the generator
|
|
|
125
137
|
|
|
126
138
|
### Repository setup
|
|
127
139
|
|
|
128
|
-
| Command | Description
|
|
129
|
-
| ------------------------- |
|
|
130
|
-
| `tooling setup:secrets` | Configure CI secrets (Forgejo or GitHub). Auto-detects platform from `package.json` repository URL. Flags: `--dry-run`, `--no-docker
|
|
131
|
-
| `tooling forgejo:secrets` | Manage Forgejo Actions secrets directly. Subcommands: `set`, `list`, `delete`.
|
|
140
|
+
| Command | Description |
|
|
141
|
+
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
142
|
+
| `tooling setup:secrets` | Configure CI secrets (Forgejo or GitHub). Auto-detects platform from `package.json` repository URL. Flags: `--dry-run`, `--no-docker` (negates `--docker`). |
|
|
143
|
+
| `tooling forgejo:secrets` | Manage Forgejo Actions secrets directly. Subcommands: `set`, `list`, `delete`. |
|
|
132
144
|
|
|
133
145
|
`setup:secrets` detects the hosting platform from the `repository` field in `package.json`. For Forgejo repositories, it prompts for username and password, creates an access token with appropriate scopes, then sets `RELEASE_TOKEN` (and Docker secrets if Docker packages are detected). For GitHub repositories, it prompts for an existing Personal Access Token and uses `gh secret set` to configure secrets.
|
|
134
146
|
|
|
135
147
|
### Release management
|
|
136
148
|
|
|
137
|
-
| Command | Description
|
|
138
|
-
| -------------------------------- |
|
|
139
|
-
| `tooling release:changesets` | Changesets version/publish for Forgejo CI. Flags: `--dry-run`, `--verbose`. Env: `FORGEJO_SERVER_URL`, `FORGEJO_REPOSITORY`, `RELEASE_TOKEN`.
|
|
140
|
-
| `tooling release:simple` | Streamlined release using commit-and-tag-version. Flags: `--release-as`, `--first-release`, `--prerelease`, `--verbose`. Env: `RELEASE_TOKEN` (required on every platform).
|
|
141
|
-
| `tooling release:trigger` | Trigger a release workflow.
|
|
142
|
-
| `tooling workflow:dispatch` | Dispatch a `workflow_dispatch` event for any workflow in any repo on the same git host. Flags: `--repo`, `--workflow` (required), `--ref`, `--input key=value` (repeatable).
|
|
143
|
-
| `tooling forgejo:create-release` | Create a Forgejo release from a tag.
|
|
144
|
-
| `tooling changesets:merge` | Merge a changesets version PR. Gated on a live read of the PR; refuses an empty version PR.
|
|
145
|
-
| `tooling webhook:send <url>` | POST a structured JSON release payload with HMAC-SHA256 auth. Flags: `--tag`, `--repository`, `--server-url`, `--actor`, `--prerelease`. Secret from `WEBHOOK_SECRET` env var.
|
|
149
|
+
| Command | Description |
|
|
150
|
+
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
151
|
+
| `tooling release:changesets` | Changesets version/publish for Forgejo CI. Flags: `--dry-run`, `--verbose`. Env: `FORGEJO_SERVER_URL`, `FORGEJO_REPOSITORY`, `RELEASE_TOKEN`. |
|
|
152
|
+
| `tooling release:simple` | Streamlined release using commit-and-tag-version. Flags: `--release-as`, `--first-release`, `--prerelease`, `--verbose`. Env: `RELEASE_TOKEN` (required on every platform). |
|
|
153
|
+
| `tooling release:trigger` | Trigger a release workflow. |
|
|
154
|
+
| `tooling workflow:dispatch` | Dispatch a `workflow_dispatch` event for any workflow in any repo on the same git host. Flags: `--repo`, `--workflow` (required), `--ref`, `--input key=value` (repeatable). |
|
|
155
|
+
| `tooling forgejo:create-release` | Create a Forgejo release from a tag. |
|
|
156
|
+
| `tooling changesets:merge` | Merge a changesets version PR. Gated on a live read of the PR; refuses an empty version PR. On Forgejo, a first `mergeable: false` re-reads once after a short delay before refusing, since the forge reports `false` both for a conflict and while still checking. |
|
|
157
|
+
| `tooling webhook:send <url>` | POST a structured JSON release payload with HMAC-SHA256 auth. Flags: `--tag`, `--repository`, `--server-url`, `--actor`, `--prerelease`. Secret from `WEBHOOK_SECRET` env var. |
|
|
146
158
|
|
|
147
159
|
#### `release:simple`
|
|
148
160
|
|
|
@@ -267,7 +279,7 @@ pnpm test:coverage -> coverage:summary -> coverage:record -> coverage:stat
|
|
|
267
279
|
|
|
268
280
|
so every CI log ends with the trend table for the last 10 records.
|
|
269
281
|
|
|
270
|
-
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.
|
|
271
283
|
|
|
272
284
|
#### The local ratchet
|
|
273
285
|
|
|
@@ -419,7 +431,7 @@ Each package is tagged independently using its own version, so packages in a mon
|
|
|
419
431
|
|
|
420
432
|
| Host | Username secret | Password secret |
|
|
421
433
|
| ------------------------- | --------------------------------- | --------------------------------- |
|
|
422
|
-
| `code.orangebikelabs.com` | `
|
|
434
|
+
| `code.orangebikelabs.com` | `OBL_REGISTRY_USERNAME` | `OBL_REGISTRY_PASSWORD` |
|
|
423
435
|
| `docker.io` | `DOCKERHUB_USERNAME` | `DOCKERHUB_PASSWORD` |
|
|
424
436
|
| `quay.io` | `QUAY_USERNAME` | `QUAY_PASSWORD` |
|
|
425
437
|
| `ghcr.io` | `GHCR_USERNAME` | `GHCR_PASSWORD` |
|
|
@@ -427,7 +439,9 @@ Each package is tagged independently using its own version, so packages in a mon
|
|
|
427
439
|
|
|
428
440
|
When `package.json#repository` and `.tooling.json#registryHost` are both absent the generator falls back to neutral `REGISTRY_USERNAME` / `REGISTRY_PASSWORD`.
|
|
429
441
|
|
|
430
|
-
|
|
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.
|
|
431
445
|
|
|
432
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.
|
|
433
447
|
|