@taraxvoid/voidflow 0.13.0 → 0.14.0-next

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 (3) hide show
  1. package/README.md +116 -24
  2. package/biome/base.json +63 -0
  3. package/package.json +11 -4
package/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # voidflow
2
2
 
3
- Shared CI and deploy pipeline for a small fleet of Astro sites on Cloudflare Workers. One set of reusable GitHub Actions workflows and composite actions keeps lint, type checks, license policy, Playwright and axe-core accessibility tests, Unlighthouse budgets, and deploys identical across every site.
3
+ Shared CI and deploy pipeline for a small fleet of Astro sites on Cloudflare Workers, and the bun tools around them. One set of reusable GitHub Actions workflows and composite actions keeps lint, type checks, license policy, Playwright and axe-core accessibility tests, Unlighthouse budgets, and deploys identical across every site.
4
4
 
5
5
  - **SHA-pinned.** Every third-party action in this repo is pinned to a full commit SHA with a version comment.
6
- - **Audited.** Workflows are checked with [zizmor](https://github.com/zizmorcore/zizmor), [actionlint](https://github.com/rhysd/actionlint), check-jsonschema and shellcheck on every change (see [Self-validation](#self-validation)).
6
+ - **Audited.** Workflows are checked with [zizmor](https://github.com/zizmorcore/zizmor), [jactionlint](https://github.com/jdx/jactionlint), check-jsonschema and shellcheck on every change (see [Self-validation](#self-validation)).
7
7
  - **In production.** It runs the pipelines for the sites listed under [Used by](#used-by), including the marketing site for [RavenFlight Industries, LLC](https://rvnflt.com/github).
8
8
 
9
9
  It is semi-opinionated: the defaults match how my own sites are built (bun, Astro, Playwright).
@@ -11,7 +11,7 @@ It is semi-opinionated: the defaults match how my own sites are built (bun, Astr
11
11
  ## Used by
12
12
 
13
13
  - [taraxvoid.net](https://taraxvoid.net), my portfolio
14
- - [Queer Omaha](https://queeromaha.net), [Synth Omaha](https://synthomaha.net) and [Soundry](https://soundryomaha.net), free community sites for Omaha's queer and music scenes
14
+ - [Queer Omaha](https://queeromaha.net), [Synth Omaha](https://synthomaha.net) and [Soundry](https://soundryomaha.org), free community sites for Omaha's queer and music scenes
15
15
  - [ravenflight.io](https://ravenflight.io), RavenFlight's marketing site
16
16
 
17
17
  ### Show you use it
@@ -95,8 +95,8 @@ jobs:
95
95
  build-env: ${{ format('{{"PUBLIC_SITE_URL":"https://example.com","GIT_SHA":"{0}"}}', github.sha) }}
96
96
  ```
97
97
 
98
- With `pnpm`, the pnpm version comes from `packageManager` and Node from `volta`
99
- or `engines` in `package.json`. The lockfile (`bun.lock` or `pnpm-lock.yaml`)
98
+ With `pnpm`, the pnpm version comes from `packageManager` and Node from
99
+ `engines` in `package.json`. The lockfile (`bun.lock` or `pnpm-lock.yaml`)
100
100
  follows the package manager. `build-env` is a JSON object, visible in logs, so
101
101
  no secrets.
102
102
 
@@ -146,6 +146,39 @@ Runs lint, typecheck, check for GPL licenses, e2e with Playwright.
146
146
  `live`), and `test:e2e:lighthouse` (`live`). A script the site does not define
147
147
  is skipped with a notice, so none of them is required.
148
148
 
149
+ ### Tool validation
150
+
151
+ `tool-ci.yml` is the validation job for bun tools and libraries (CLIs, TUIs,
152
+ packages): gitleaks over the full history, install (with the same Socket
153
+ scanner handling as `site-ci.yml`), tools from the repo's `mise.toml` when it
154
+ has one, then whichever of `lint`, `check`, `build` and `test` `package.json`
155
+ defines, and `check:licenses` when dependencies or `scripts/` changed. When
156
+ workflows change it also runs jactionlint (same profile handling as
157
+ `site-ci.yml`) and
158
+ [zizmor](https://github.com/zizmorcore/zizmor). The bun version comes from
159
+ `.bun-version` when present.
160
+
161
+ ```yaml
162
+ name: CI
163
+ on:
164
+ pull_request:
165
+ types: [opened, synchronize, reopened, ready_for_review]
166
+ push:
167
+ branches: [main]
168
+ workflow_dispatch:
169
+
170
+ permissions:
171
+ contents: read
172
+ pull-requests: read
173
+
174
+ jobs:
175
+ validate:
176
+ uses: taraxvoid/voidflow/.github/workflows/tool-ci.yml@<release SHA> # vX.Y.Z
177
+ ```
178
+
179
+ The job reports as `validate / Validate`, the check the `tool()` entry in
180
+ [`rulesets/index.ts`](#branch-rulesets-as-code) requires.
181
+
149
182
  ### Unlighthouse (performance / SEO budgets)
150
183
 
151
184
  `site-ci.yml` runs `bun run test:e2e:lighthouse` on PRs into `live`. Sites
@@ -191,6 +224,11 @@ the global `~/.bunfig.toml` rather than the site's, so a global
191
224
  locally (including in the pre-commit hook) for 3 days after every release.
192
225
  The devDependency's bins are installed under the site's own `bunfig.toml`.
193
226
 
227
+ Both bins (`check-licenses`, `unlighthouse-runner`) are TypeScript run by Bun
228
+ (`#!/usr/bin/env bun`), so `bun` must be on `PATH` even when the site uses
229
+ npm or pnpm. The `@taraxvoid/voidflow/playwright` export is plain ESM and runs
230
+ on Node 22+ without Bun.
231
+
194
232
  ### Playwright preview config
195
233
 
196
234
  Shared `playwright.config` for Astro sites that run e2e against
@@ -219,6 +257,31 @@ Options: `ciPort` (required in CI), `runner` (default `bun`, e.g. `pnpm`),
219
257
  `timeout` (default 30000), `projects` (default Pixel 7 and Desktop Chrome),
220
258
  `testDir` (default `./test/e2e`). Requires `@playwright/test` in the site.
221
259
 
260
+ ## Shared Biome config
261
+
262
+ [`biome/base.json`](biome/base.json) is the house style for the fleet: 4-space
263
+ indent, LF, width 80, single quotes, semicolons only where needed, trailing
264
+ commas, the `recommended` rule preset, organized imports, CSS lint off, and
265
+ unused-import/variable rules off in `.astro` files (Biome can't see template
266
+ usage). With `@taraxvoid/voidflow` as a devDependency, the site's `biome.json`
267
+ extends it and adds only what is specific to the site:
268
+
269
+ ```json
270
+ {
271
+ "$schema": "https://biomejs.dev/schemas/2.5.14/schema.json",
272
+ "extends": ["@taraxvoid/voidflow/biome"],
273
+ "files": {
274
+ "includes": ["**", "!**/bun.lock", "!public/admin/**"]
275
+ }
276
+ }
277
+ ```
278
+
279
+ Lists such as `files.includes` and `overrides` combine with the base's rather
280
+ than replace them; single values set in the site win. The base has no ignore
281
+ lists, so each site keeps its own. It needs Biome 2: the pre-commit hook and
282
+ `site-ci.yml` print a warning (they don't fail) when a site has Biome 1.x
283
+ installed.
284
+
222
285
  ## Dependency updates (Renovate)
223
286
 
224
287
  [`default.json`](default.json) is the shared Renovate preset. Sites add a
@@ -243,30 +306,43 @@ on the repo.
243
306
 
244
307
  ## Git hooks (lefthook)
245
308
 
246
- [`lefthook/site.yml`](lefthook/site.yml) is the shared hook set for the site
247
- stack, consumed as a lefthook remote. It calls the site's own `package.json`
248
- scripts (`<pm> run --if-present`, so a missing script is skipped; `<pm>` is pnpm
249
- when the repo has a `pnpm-lock.yaml`, bun otherwise):
309
+ [`lefthook/base.yml`](lefthook/base.yml) is the shared hook set for any bun
310
+ (or pnpm) repo, sites and tools alike, consumed as a lefthook remote. It calls
311
+ the repo's own `package.json` scripts (`<pm> run --if-present`, so a missing
312
+ script is skipped; `<pm>` is pnpm when the repo has a `pnpm-lock.yaml`, bun
313
+ otherwise):
250
314
 
251
- - `pre-commit`: dependency guard, `format` (formatted files are re-staged),
315
+ - `pre-commit`: dependency guard, Biome 1.x warning, `format` (formatted files are re-staged),
252
316
  `lint:actions`, `check`, `test:unit`, and `check:licenses` / `audit` when the
253
317
  lockfile changed.
254
318
  - `commit-msg`: advisory Conventional Commits hint (never blocks).
255
319
  - `pre-push`: bail if the remote branch is ahead, then `test:push`; skipped when
256
- there is nothing new to push.
320
+ the push carries no commit the remote lacks (branch deletes, and tags or
321
+ branches at already-pushed commits).
322
+
323
+ Before `test:unit` and `test:push`, the hooks unset the variables git exports to
324
+ hooks (`GIT_DIR`, `GIT_INDEX_FILE`, ...; the list comes from
325
+ `git rev-parse --local-env-vars`). Without that, a test that runs
326
+ `git -C <tmpdir> commit` operates on, and commits into, the repo being hooked.
257
327
 
258
328
  ```yaml
259
- # lefthook.yml in the site
329
+ # lefthook.yml in the repo
260
330
  remotes:
261
331
  - git_url: https://github.com/taraxvoid/voidflow
262
332
  ref: v0.10.0 # a tag or branch; lefthook passes it to `git clone --branch`
263
333
  configs:
264
- - lefthook/site.yml
334
+ - lefthook/base.yml
265
335
 
266
336
  ```
267
337
 
338
+ Upgrading from `lefthook/site.yml` (v0.13 and earlier): change the `configs`
339
+ entry to `lefthook/base.yml` when you bump `ref`. The hooks are otherwise the
340
+ same. `lefthook/site.yml` is now a stub whose `pre-commit` and `pre-push` fail
341
+ with that instruction, so a `ref` bump (for example from Renovate) that leaves
342
+ `configs` alone stops commits instead of turning the hooks off silently.
343
+
268
344
  Lefthook merges `lefthook.yml`, then remotes, then `lefthook-local.yml`, so a
269
- site's own `lefthook.yml` can add commands (for example image compression) but
345
+ repo's own `lefthook.yml` can add commands (for example image compression) but
270
346
  cannot override ones defined here. Differences go through `package.json`
271
347
  scripts: define `test:unit:precommit` (for example excluding tests that need a
272
348
  built `dist/`) and the pre-commit unit step runs it instead of `test:unit`.
@@ -283,13 +359,22 @@ locally. Common uses:
283
359
  as a recursive run, add `--filter '!{.}'` so it doesn't recurse.
284
360
 
285
361
  Hook-level options merge too. Don't set `parallel: true` under `pre-commit:` in
286
- the site's `lefthook.yml`: it applies to the merged hook, so every step,
362
+ the repo's `lefthook.yml`: it applies to the merged hook, so every step,
287
363
  including the shared ones, starts at once and their `priority` order is ignored
288
364
  (tests that share a database or build output can then time out).
289
365
 
290
- Install the binary through mise (`lefthook = "<version>"` in `mise.toml`) and
291
- set the `prepare` script so `bun install` wires the hooks, but make it tolerate a
292
- missing binary:
366
+ Install the binaries through mise. A starter `mise.toml` for a repo using
367
+ these hooks and voidflow CI:
368
+
369
+ ```toml
370
+ [tools]
371
+ lefthook = "2.2.1"
372
+ gitleaks = "8.30.1"
373
+ jactionlint = "2.1.0"
374
+ ```
375
+
376
+ Renovate bumps `mise.toml` natively. Set the `prepare` script so `bun install`
377
+ wires the hooks, but make it tolerate a missing binary:
293
378
 
294
379
  ```json
295
380
  "prepare": "lefthook install || echo 'lefthook not installed (run mise install); git hooks skipped'"
@@ -305,7 +390,10 @@ release tag.
305
390
  Branch protection for the fleet lives in [`rulesets/index.ts`](rulesets/index.ts):
306
391
  one canonical `main` / `next` / `live` definition (plus `prerelease` and `maintenance`
307
392
  tiers for repos with release channels) and a small per-repo table
308
- (Netlify or not, check names, CODEOWNERS, extra bypass actors). Hand-edited
393
+ (Netlify or not, check names, CODEOWNERS, extra bypass actors). Sites use
394
+ `site()` and tools use `tool()` (main only, no Netlify, requires
395
+ `validate / Validate` from `tool-ci.yml`). Private repos are left out: on a
396
+ plan without rulesets for private repos, the API returns 403. Hand-edited
309
397
  rulesets drift, and drift is how a `next` ruleset ends up requiring a check
310
398
  name that no workflow reports any more.
311
399
 
@@ -323,7 +411,11 @@ manages `main`, `prerelease` (`next`) and `maintenance` (`release/*`) and sets
323
411
  `linearHistory: false` so `next` can be promoted into `main` with a merge commit.
324
412
  Uses the `gh` CLI for auth (needs admin on the repos). Rulesets that are not in
325
413
  the config are reported and left alone; only `retire` entries are ever deleted,
326
- and only with `--prune`. It is repo tooling, not part of the published package.
414
+ and only with `--prune`. Private repos on a plan without rulesets (GitHub answers
415
+ 403, e.g. a free personal account) are skipped and listed at the end rather than
416
+ failing the run, so `--check` stays green and they pick up their rulesets once the
417
+ repo goes public or the plan changes. It is repo tooling, not part of the published
418
+ package.
327
419
 
328
420
  ## Deployments
329
421
 
@@ -397,16 +489,16 @@ Treat `@main` and `@next` as unstable.
397
489
 
398
490
  This repo validates its own workflows and composite actions (`.github/workflows/ci.yml`):
399
491
 
400
- - **actionlint**: workflow schema/logic; also shellchecks `run:` steps in `.github/workflows/*.yml` automatically (`shellcheck` ships on `ubuntu-latest`)
492
+ - **jactionlint**: workflow schema/logic; also shellchecks `run:` steps in `.github/workflows/*.yml` automatically (`shellcheck` ships on `ubuntu-latest`)
401
493
  - **check-jsonschema**: schema-checks `actions/**/action.yml` and the workflow files against [SchemaStore](https://www.schemastore.org/)'s `github-action.json` / `github-workflow.json`
402
- - **shellcheck** (`scripts/shellcheck-actions.ts`): checks `run:` steps inside `actions/**/action.yml`, which actionlint doesn't reach
494
+ - **shellcheck** (`scripts/shellcheck-actions.ts`): checks `run:` steps inside `actions/**/action.yml`, which jactionlint doesn't reach
403
495
  - **zizmor**: security audit (unpinned refs, script injection via `${{ }}` in `run:`, excess permissions, etc.)
404
496
 
405
497
  ### Local dev setup
406
498
 
407
499
  ```sh
408
- brew install just lefthook actionlint shellcheck bun act uv
409
- lefthook install
500
+ mise install # tools pinned in mise.toml
501
+ bun install # its prepare script runs `lefthook install`
410
502
  ```
411
503
 
412
504
  - `just validate`: run everything CI runs, locally
@@ -0,0 +1,63 @@
1
+ {
2
+ "vcs": {
3
+ "enabled": true,
4
+ "clientKind": "git",
5
+ "useIgnoreFile": true
6
+ },
7
+ "assist": {
8
+ "enabled": true,
9
+ "actions": {
10
+ "source": {
11
+ "organizeImports": "on"
12
+ }
13
+ }
14
+ },
15
+ "formatter": {
16
+ "enabled": true,
17
+ "indentStyle": "space",
18
+ "indentWidth": 4,
19
+ "lineEnding": "lf",
20
+ "lineWidth": 80,
21
+ "useEditorconfig": true
22
+ },
23
+ "javascript": {
24
+ "formatter": {
25
+ "arrowParentheses": "always",
26
+ "jsxQuoteStyle": "double",
27
+ "quoteProperties": "asNeeded",
28
+ "quoteStyle": "single",
29
+ "semicolons": "asNeeded",
30
+ "trailingCommas": "all"
31
+ }
32
+ },
33
+ "html": {
34
+ "formatter": {
35
+ "indentScriptAndStyle": false,
36
+ "selfCloseVoidElements": "always"
37
+ }
38
+ },
39
+ "css": {
40
+ "linter": {
41
+ "enabled": false
42
+ }
43
+ },
44
+ "linter": {
45
+ "enabled": true,
46
+ "rules": {
47
+ "preset": "recommended"
48
+ }
49
+ },
50
+ "overrides": [
51
+ {
52
+ "includes": ["**/*.astro"],
53
+ "linter": {
54
+ "rules": {
55
+ "correctness": {
56
+ "noUnusedImports": "off",
57
+ "noUnusedVariables": "off"
58
+ }
59
+ }
60
+ }
61
+ }
62
+ ]
63
+ }
package/package.json CHANGED
@@ -1,15 +1,17 @@
1
1
  {
2
2
  "name": "@taraxvoid/voidflow",
3
- "version": "0.13.0",
4
- "description": "Shared workflows, actions and tooling for @taraxvoid sites",
3
+ "version": "0.14.0-next",
4
+ "description": "Shared workflows, hooks and tooling for @taraxvoid repos",
5
5
  "license": "MIT",
6
6
  "keywords": [
7
7
  "github-actions",
8
8
  "ci",
9
9
  "reusable-workflows",
10
+ "lefthook",
11
+ "renovate",
12
+ "bun",
10
13
  "playwright",
11
14
  "unlighthouse",
12
- "astro",
13
15
  "cloudflare"
14
16
  ],
15
17
  "homepage": "https://github.com/taraxvoid/voidflow#readme",
@@ -33,17 +35,21 @@
33
35
  "types": "./playwright/index.d.mts",
34
36
  "default": "./playwright/index.mjs"
35
37
  },
38
+ "./biome": "./biome/base.json",
36
39
  "./package.json": "./package.json"
37
40
  },
38
41
  "files": [
42
+ "biome",
39
43
  "playwright",
40
44
  "scripts/unlighthouse",
41
45
  "scripts/check-licenses.ts"
42
46
  ],
43
47
  "engines": {
44
- "bun": ">=1.4.0"
48
+ "bun": ">=1.4.0",
49
+ "node": ">=22"
45
50
  },
46
51
  "scripts": {
52
+ "prepare": "lefthook install || echo 'lefthook not installed (run mise install); git hooks skipped'",
47
53
  "test": "bun test"
48
54
  },
49
55
  "peerDependencies": {
@@ -55,6 +61,7 @@
55
61
  }
56
62
  },
57
63
  "devDependencies": {
64
+ "@biomejs/biome": "2.5.14",
58
65
  "@playwright/test": "1.64.0",
59
66
  "@socketsecurity/bun-security-scanner": "1.1.3"
60
67
  },