@regardio/dev 2.6.2 → 2.7.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.
|
@@ -97,27 +97,45 @@ Schema tests run against a real Postgres so policies and triggers behave as they
|
|
|
97
97
|
|
|
98
98
|
## Coverage
|
|
99
99
|
|
|
100
|
-
Library packages hold a floor
|
|
100
|
+
Library packages hold a floor of 80% for statements, branches, functions, and lines. The floor is a minimum, not a target — the goal is meaningful tests, not arithmetic.
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
## Branch quality gates
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
Different branches carry different promises, and the gates match those promises.
|
|
105
|
+
|
|
106
|
+
| Branch | Gate | What runs |
|
|
107
|
+
|--------|------|-----------|
|
|
108
|
+
| `main` | commit | lint, typecheck |
|
|
109
|
+
| `staging` | CI | lint, typecheck, test, coverage |
|
|
110
|
+
| `production` | CI + ship | lint, typecheck, test, coverage |
|
|
111
|
+
| `feature/*` | none | — |
|
|
112
|
+
| `hotfix/*` | none | — |
|
|
113
|
+
|
|
114
|
+
**`main` is the development branch.** Commits to `main` must be syntactically sound — lint and typecheck pass — but tests and coverage are not required to succeed. Work in progress lives here.
|
|
115
|
+
|
|
116
|
+
**`staging` and `production` promise correctness.** The full QA chain runs before anything lands there. The ship commands enforce this before merging, and CI enforces it again on push.
|
|
117
|
+
|
|
118
|
+
**Feature and hotfix branches are free.** Commit at will. The gate is applied when the branch merges into its target — feature → main applies main's gate, hotfix → production applies production's gate.
|
|
119
|
+
|
|
120
|
+
Coverage is enforced at:
|
|
121
|
+
|
|
122
|
+
- `pnpm report` — fails locally if coverage drops below the floor (run before shipping)
|
|
123
|
+
- `ship:staging` and `ship:production` — run the full quality suite before merging
|
|
124
|
+
- CI on `staging` and `production` — re-runs the suite on push
|
|
107
125
|
|
|
108
126
|
## Quality gates
|
|
109
127
|
|
|
110
|
-
Before a package
|
|
128
|
+
Before a package ships to `staging` or `production`:
|
|
111
129
|
|
|
112
130
|
1. Build succeeds
|
|
113
131
|
2. Type check passes
|
|
114
|
-
3.
|
|
115
|
-
4.
|
|
132
|
+
3. Tests pass — no skipped or failing
|
|
133
|
+
4. Coverage meets the floor
|
|
116
134
|
|
|
117
135
|
## Continuous integration
|
|
118
136
|
|
|
119
|
-
- Pre-commit hooks run
|
|
120
|
-
- CI
|
|
137
|
+
- Pre-commit hooks run lint (Biome, markdownlint) and typecheck on staged files
|
|
138
|
+
- CI on `staging` and `production` runs the full suite including coverage
|
|
121
139
|
- Release workflow blocks publishing on any failure
|
|
122
140
|
|
|
123
141
|
## Test maintenance
|
package/docs/en/tools/husky.md
CHANGED
|
@@ -27,6 +27,24 @@ Husky configures itself through the `prepare` script:
|
|
|
27
27
|
|
|
28
28
|
This runs after `pnpm install` and sets up the `.husky` directory.
|
|
29
29
|
|
|
30
|
+
Copy the hook templates from `@regardio/dev`:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
mkdir -p .husky
|
|
34
|
+
cp node_modules/@regardio/dev/templates/husky/pre-commit .husky/pre-commit
|
|
35
|
+
cp node_modules/@regardio/dev/templates/husky/commit-msg .husky/commit-msg
|
|
36
|
+
cp node_modules/@regardio/dev/templates/husky/pre-push .husky/pre-push
|
|
37
|
+
chmod +x .husky/pre-commit .husky/commit-msg .husky/pre-push
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## What the hooks enforce
|
|
41
|
+
|
|
42
|
+
The pre-commit hook enforces **syntax correctness**, not behavioural correctness. The distinction is intentional and matches the branch model:
|
|
43
|
+
|
|
44
|
+
- **`main`** is the development branch. Commits to `main` must pass lint and typecheck, but tests and coverage are not required. Work in progress belongs here.
|
|
45
|
+
- **`staging` and `production`** promise correctness. The full QA chain (typecheck, test, coverage) runs on every push to those branches via the `pre-push` hook, and again inside the `ship:*` commands as a second gate.
|
|
46
|
+
- **`feature/*` and `hotfix/*`** branches carry no gate. Commit freely — the gate applies when merging into the target branch.
|
|
47
|
+
|
|
30
48
|
## Hooks
|
|
31
49
|
|
|
32
50
|
### `commit-msg`
|
|
@@ -35,25 +53,83 @@ Validates commit messages against the conventional-commit format:
|
|
|
35
53
|
|
|
36
54
|
```bash
|
|
37
55
|
#!/bin/sh
|
|
38
|
-
|
|
39
|
-
commitlint --edit $1
|
|
56
|
+
pnpm exec commitlint --edit "$1"
|
|
40
57
|
```
|
|
41
58
|
|
|
42
|
-
### `pre-
|
|
59
|
+
### `pre-push`
|
|
43
60
|
|
|
44
|
-
|
|
61
|
+
Branch-aware: runs typecheck on every branch except `feature/*` and `hotfix/*`; runs the full QA chain before any push to `staging` or `production`.
|
|
45
62
|
|
|
46
63
|
```bash
|
|
47
64
|
#!/bin/sh
|
|
48
|
-
|
|
65
|
+
set -eu
|
|
66
|
+
|
|
67
|
+
BRANCH="$(git symbolic-ref --short HEAD 2>/dev/null || echo 'HEAD')"
|
|
68
|
+
|
|
69
|
+
# Feature and hotfix branches carry no push gate.
|
|
70
|
+
case "$BRANCH" in
|
|
71
|
+
feature/*|hotfix/*) exit 0 ;;
|
|
72
|
+
esac
|
|
73
|
+
|
|
74
|
+
pnpm run --if-present typecheck
|
|
75
|
+
|
|
76
|
+
# Staging and production must pass the full QA chain.
|
|
77
|
+
case "$BRANCH" in
|
|
78
|
+
staging|production)
|
|
79
|
+
pnpm run --if-present test
|
|
80
|
+
pnpm run --if-present report
|
|
81
|
+
;;
|
|
82
|
+
esac
|
|
49
83
|
```
|
|
50
84
|
|
|
85
|
+
### `pre-commit`
|
|
86
|
+
|
|
87
|
+
Branch-aware: lints staged files and runs typecheck; full QA on `staging`/`production` commits.
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
#!/bin/sh
|
|
91
|
+
set -eu
|
|
92
|
+
|
|
93
|
+
BRANCH="$(git symbolic-ref --short HEAD 2>/dev/null || echo 'HEAD')"
|
|
94
|
+
|
|
95
|
+
# Feature and hotfix branches carry no commit gate.
|
|
96
|
+
case "$BRANCH" in
|
|
97
|
+
feature/*|hotfix/*) exit 0 ;;
|
|
98
|
+
esac
|
|
99
|
+
|
|
100
|
+
STAGED_FILES="$(git diff --cached --name-only --diff-filter=ACMR)"
|
|
101
|
+
[ -z "$STAGED_FILES" ] && exit 0
|
|
102
|
+
|
|
103
|
+
STAGED_BIOME_FILES="$(echo "$STAGED_FILES" | grep -E '\.(cjs|cts|js|jsx|mjs|mts|ts|tsx|json|jsonc)$' || true)"
|
|
104
|
+
STAGED_MD_FILES="$(echo "$STAGED_FILES" | grep -E '\.(md|mdoc|mdx)$' | grep -v 'CHANGELOG\.md' || true)"
|
|
105
|
+
|
|
106
|
+
if [ -n "$STAGED_BIOME_FILES" ]; then
|
|
107
|
+
echo "$STAGED_BIOME_FILES" | xargs pnpm exec biome check --no-errors-on-unmatched
|
|
108
|
+
fi
|
|
109
|
+
if [ -n "$STAGED_MD_FILES" ]; then
|
|
110
|
+
echo "$STAGED_MD_FILES" | xargs pnpm exec markdownlint-cli2 --config .markdownlint-cli2.jsonc
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
pnpm run --if-present typecheck
|
|
114
|
+
|
|
115
|
+
# Staging and production must pass the full QA chain.
|
|
116
|
+
case "$BRANCH" in
|
|
117
|
+
staging|production)
|
|
118
|
+
pnpm run --if-present test
|
|
119
|
+
pnpm run --if-present report
|
|
120
|
+
;;
|
|
121
|
+
esac
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`--if-present` means repos that don't define a given script skip that step silently.
|
|
125
|
+
|
|
51
126
|
## Bypassing hooks
|
|
52
127
|
|
|
53
|
-
In the rare case where a hook truly has to be skipped:
|
|
128
|
+
In the rare case where a hook truly has to be skipped, `--no-verify` works for both commit and push:
|
|
54
129
|
|
|
55
130
|
```bash
|
|
56
131
|
git commit --no-verify -m "emergency fix"
|
|
132
|
+
git push --no-verify origin main
|
|
57
133
|
```
|
|
58
134
|
|
|
59
135
|
Use sparingly. A bypass that becomes habit stops being a bypass.
|
|
@@ -82,4 +158,6 @@ chmod +x .husky/*
|
|
|
82
158
|
|
|
83
159
|
- [Commitlint](./commitlint.md) — commit-message validation
|
|
84
160
|
- [Biome](./biome.md) — linting and formatting
|
|
161
|
+
- [Release Workflow](./releases.md) — how branches, ship commands, and CI enforce quality gates
|
|
162
|
+
- [Testing](../standards/testing.md) — branch gate model explained
|
|
85
163
|
- [Husky Documentation](https://typicode.github.io/husky/)
|
|
@@ -143,7 +143,28 @@ pnpm ship:hotfix finish
|
|
|
143
143
|
|
|
144
144
|
## Adoption
|
|
145
145
|
|
|
146
|
-
### 1.
|
|
146
|
+
### 1. Set up Husky hooks
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
mkdir -p .husky
|
|
150
|
+
cp node_modules/@regardio/dev/templates/husky/pre-commit .husky/pre-commit
|
|
151
|
+
cp node_modules/@regardio/dev/templates/husky/commit-msg .husky/commit-msg
|
|
152
|
+
chmod +x .husky/pre-commit .husky/commit-msg
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Add the `prepare` script so Husky installs itself after `pnpm install`:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{
|
|
159
|
+
"scripts": {
|
|
160
|
+
"prepare": "husky"
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
The `pre-commit` template is branch-aware: feature and hotfix branches commit freely, `main` enforces lint and typecheck, and `staging`/`production` enforce the full QA chain. See [Husky](./husky.md) for details.
|
|
166
|
+
|
|
167
|
+
### 2. Add ship scripts to `package.json`
|
|
147
168
|
|
|
148
169
|
```json
|
|
149
170
|
{
|
|
@@ -210,12 +231,22 @@ CI publishes subsequent versions; the very first one requires a local publish be
|
|
|
210
231
|
|
|
211
232
|
## Quality Gates
|
|
212
233
|
|
|
213
|
-
|
|
234
|
+
Gates differ by branch. The ship commands enforce the appropriate gate before any merge.
|
|
235
|
+
|
|
236
|
+
| Context | What runs |
|
|
237
|
+
|---------|-----------|
|
|
238
|
+
| Commit to `main` (pre-commit hook) | lint, typecheck |
|
|
239
|
+
| Commit to `feature/*` or `hotfix/*` | nothing |
|
|
240
|
+
| `ship:staging` / `ship:production` / `ship:hotfix finish` | build, typecheck, test, coverage |
|
|
241
|
+
| CI on `staging` / `production` | build, typecheck, test, coverage |
|
|
242
|
+
|
|
243
|
+
Ship commands run:
|
|
214
244
|
|
|
215
245
|
```bash
|
|
216
246
|
pnpm build # Must succeed
|
|
217
247
|
pnpm typecheck # Must succeed
|
|
218
248
|
pnpm test # Must succeed
|
|
249
|
+
pnpm report # Coverage must meet the floor
|
|
219
250
|
```
|
|
220
251
|
|
|
221
252
|
## Publishing vs Non-Publishing Repos
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://www.schemastore.org/package.json",
|
|
3
3
|
"name": "@regardio/dev",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.7.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Regardio development presets: biome, typescript, commitlint, markdownlint, vitest, playwright, sqlfluff, husky, and GitLab-flow ship tooling",
|
|
7
7
|
"keywords": [
|
|
@@ -74,10 +74,10 @@
|
|
|
74
74
|
],
|
|
75
75
|
"devDependencies": {
|
|
76
76
|
"@total-typescript/ts-reset": "0.6.1",
|
|
77
|
-
"@types/node": "25.
|
|
78
|
-
"@vitest/coverage-v8": "4.1.
|
|
77
|
+
"@types/node": "25.7.0",
|
|
78
|
+
"@vitest/coverage-v8": "4.1.6",
|
|
79
79
|
"tsdown": "0.22.0",
|
|
80
|
-
"vitest": "4.1.
|
|
80
|
+
"vitest": "4.1.6"
|
|
81
81
|
},
|
|
82
82
|
"peerDependencies": {
|
|
83
83
|
"@biomejs/biome": ">=2",
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -eu
|
|
3
|
+
|
|
4
|
+
BRANCH="$(git symbolic-ref --short HEAD 2>/dev/null || echo 'HEAD')"
|
|
5
|
+
|
|
6
|
+
# Feature and hotfix branches carry no commit gate.
|
|
7
|
+
case "$BRANCH" in
|
|
8
|
+
feature/*|hotfix/*) exit 0 ;;
|
|
9
|
+
esac
|
|
10
|
+
|
|
11
|
+
STAGED_FILES="$(git diff --cached --name-only --diff-filter=ACMR)"
|
|
12
|
+
[ -z "$STAGED_FILES" ] && exit 0
|
|
13
|
+
|
|
14
|
+
STAGED_BIOME_FILES="$(echo "$STAGED_FILES" | grep -E '\.(cjs|cts|js|jsx|mjs|mts|ts|tsx|json|jsonc)$' || true)"
|
|
15
|
+
STAGED_MD_FILES="$(echo "$STAGED_FILES" | grep -E '\.(md|mdoc|mdx)$' | grep -v 'CHANGELOG\.md' || true)"
|
|
16
|
+
|
|
17
|
+
if [ -n "$STAGED_BIOME_FILES" ]; then
|
|
18
|
+
echo "$STAGED_BIOME_FILES" | xargs pnpm exec biome check --no-errors-on-unmatched
|
|
19
|
+
fi
|
|
20
|
+
if [ -n "$STAGED_MD_FILES" ]; then
|
|
21
|
+
echo "$STAGED_MD_FILES" | xargs pnpm exec markdownlint-cli2 --config .markdownlint-cli2.jsonc
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
pnpm run --if-present typecheck
|
|
25
|
+
|
|
26
|
+
# Staging and production must pass the full QA chain.
|
|
27
|
+
case "$BRANCH" in
|
|
28
|
+
staging|production)
|
|
29
|
+
pnpm run --if-present test
|
|
30
|
+
pnpm run --if-present report
|
|
31
|
+
;;
|
|
32
|
+
esac
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -eu
|
|
3
|
+
|
|
4
|
+
BRANCH="$(git symbolic-ref --short HEAD 2>/dev/null || echo 'HEAD')"
|
|
5
|
+
|
|
6
|
+
# Feature and hotfix branches carry no push gate.
|
|
7
|
+
case "$BRANCH" in
|
|
8
|
+
feature/*|hotfix/*) exit 0 ;;
|
|
9
|
+
esac
|
|
10
|
+
|
|
11
|
+
pnpm run --if-present typecheck
|
|
12
|
+
|
|
13
|
+
# Staging and production must pass the full QA chain.
|
|
14
|
+
case "$BRANCH" in
|
|
15
|
+
staging|production)
|
|
16
|
+
pnpm run --if-present test
|
|
17
|
+
pnpm run --if-present report
|
|
18
|
+
;;
|
|
19
|
+
esac
|