@homeflare/config 0.10.0 → 0.11.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 +11 -41
- package/bin/hooks.ts +8 -4
- package/dist/hooks/activate.d.ts +7 -0
- package/dist/hooks/activate.d.ts.map +1 -0
- package/dist/hooks/gates.d.ts +7 -14
- package/dist/hooks/gates.d.ts.map +1 -1
- package/dist/hooks/install.d.ts +7 -1
- package/dist/hooks/install.d.ts.map +1 -1
- package/dist/hooks/oxfmt-config.d.ts +25 -0
- package/dist/hooks/oxfmt-config.d.ts.map +1 -0
- package/dist/hooks/push-plan.d.ts +59 -0
- package/dist/hooks/push-plan.d.ts.map +1 -0
- package/dist/hooks/push-range.d.ts +51 -0
- package/dist/hooks/push-range.d.ts.map +1 -0
- package/dist/hooks/report.d.ts +39 -2
- package/dist/hooks/report.d.ts.map +1 -1
- package/dist/hooks/secrets.d.ts +2 -0
- package/dist/hooks/secrets.d.ts.map +1 -0
- package/dist/hooks.d.ts +30 -6
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +408 -41
- package/dist/hooks.js.map +12 -7
- package/dist/repo-shape/yaml.d.ts +20 -3
- package/dist/repo-shape/yaml.d.ts.map +1 -1
- package/dist/repo-shape.js +8 -2
- package/dist/repo-shape.js.map +3 -3
- package/dist/versions.js +8 -2
- package/dist/versions.js.map +3 -3
- package/docs/hooks.md +118 -0
- package/package.json +1 -1
- package/src/hooks/activate.ts +71 -0
- package/src/hooks/gates.ts +156 -39
- package/src/hooks/install.ts +39 -20
- package/src/hooks/oxfmt-config.ts +67 -0
- package/src/hooks/push-plan.ts +167 -0
- package/src/hooks/push-range.ts +177 -0
- package/src/hooks/report.ts +46 -6
- package/src/hooks/secrets.ts +42 -0
- package/src/hooks.ts +30 -14
- package/src/repo-shape/yaml.ts +26 -4
package/src/hooks.ts
CHANGED
|
@@ -6,43 +6,59 @@
|
|
|
6
6
|
* notices, and two repos disagree about what a commit must satisfy. Here the repo
|
|
7
7
|
* commits a delegating wrapper and the behaviour ships with the package, so changing
|
|
8
8
|
* the rule is one release and a version bump rather than fourteen edits.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
9
|
+
* ★ TRACKED `.husky/`, RUN BY GIT THROUGH `core.hooksPath` — NOT husky's `.husky/_`. Since
|
|
10
|
+
* 2026-09-23 the mechanism is the one that reaches every worktree; activate.ts has the
|
|
11
|
+
* measurement. The files keep the directory name the estate already uses.
|
|
12
|
+
* ★ PRE-PUSH IS SCOPED TO THE PUSH (push-range.ts, push-plan.ts): the repository's own
|
|
13
|
+
* `check`, with `bun test` narrowed to the tests the pushed files can reach and the build
|
|
14
|
+
* and smoke test left to CI. Many agents push to many repositories at once; a pre-push
|
|
15
|
+
* that re-ran every suite was the one people learned to skip.
|
|
14
16
|
*
|
|
15
17
|
* Usage from a hook file — see `HUSKY_HOOK`:
|
|
16
18
|
*
|
|
17
19
|
* bun node_modules/@homeflare/config/bin/hooks.ts pre-commit
|
|
18
20
|
*/
|
|
21
|
+
import { activateHooks } from './hooks/activate.ts';
|
|
19
22
|
import { preCommit, prePush } from './hooks/gates.ts';
|
|
20
|
-
import { HOOK_NAMES, HUSKY_HOOK, installHooks, problemsInHooks } from './hooks/install.ts';
|
|
23
|
+
import { HOOK_NAMES, HUSKY_HOOK, PREPARE, installHooks, problemsInHooks } from './hooks/install.ts';
|
|
24
|
+
import { type Lane, planLanes } from './hooks/push-plan.ts';
|
|
21
25
|
import { type Hook, note, ok } from './hooks/report.ts';
|
|
22
26
|
|
|
23
|
-
export { HOOK_NAMES, HUSKY_HOOK, installHooks, problemsInHooks };
|
|
24
|
-
export type { Hook };
|
|
27
|
+
export { HOOK_NAMES, HUSKY_HOOK, PREPARE, activateHooks, installHooks, planLanes, problemsInHooks };
|
|
28
|
+
export type { Hook, Lane };
|
|
25
29
|
|
|
26
30
|
/** The commands `bin/hooks.ts` accepts. */
|
|
27
|
-
export type Command = Hook | 'install';
|
|
31
|
+
export type Command = Hook | 'install' | 'activate';
|
|
28
32
|
|
|
29
33
|
export function isCommand(value: string): value is Command {
|
|
30
|
-
return
|
|
34
|
+
return ['pre-commit', 'pre-push', 'install', 'activate'].includes(value);
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
/**
|
|
34
|
-
* Run one hook,
|
|
38
|
+
* Run one hook, write the wrappers, or activate them.
|
|
35
39
|
*
|
|
40
|
+
* `args` are git's own hook arguments (for `pre-push`: the remote name and URL) and
|
|
41
|
+
* `stdin` is what git wrote to the hook (for `pre-push`: the refs being pushed).
|
|
36
42
|
* ⛔ Never exits non-zero for a reason the caller cannot act on: an unknown command is a
|
|
37
43
|
* programming error in the wrapper and is reported as such, not as a failed commit.
|
|
38
44
|
*/
|
|
39
|
-
export async function runCommand(
|
|
45
|
+
export async function runCommand(
|
|
46
|
+
command: Command,
|
|
47
|
+
root: string,
|
|
48
|
+
args: readonly string[] = [],
|
|
49
|
+
stdin = '',
|
|
50
|
+
): Promise<void> {
|
|
40
51
|
if (command === 'install') {
|
|
41
52
|
const written = await installHooks(root);
|
|
42
53
|
ok(`wrote ${written.join(', ')} — commit them`);
|
|
43
|
-
note(
|
|
54
|
+
note(`then set "prepare": "${PREPARE}" so every install activates them`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (command === 'activate') {
|
|
58
|
+
const result = await activateHooks(root);
|
|
59
|
+
(result.active ? ok : note)(`homeflare hooks: ${result.message}`);
|
|
44
60
|
return;
|
|
45
61
|
}
|
|
46
62
|
if (command === 'pre-commit') return await preCommit(root);
|
|
47
|
-
return await prePush(root);
|
|
63
|
+
return await prePush(root, args, stdin);
|
|
48
64
|
}
|
package/src/repo-shape/yaml.ts
CHANGED
|
@@ -6,9 +6,15 @@
|
|
|
6
6
|
* this house are the product. The rendered workflows are written as text with holes;
|
|
7
7
|
* only the step lists, whose shape varies per repository, go through here.
|
|
8
8
|
*
|
|
9
|
-
* ⚠️ Bun
|
|
10
|
-
* against Bun 1.4.0 on 2026-09-
|
|
11
|
-
*
|
|
9
|
+
* ⚠️ Bun.YAML.stringify EXISTS (`Object.keys(Bun.YAML)` is `["parse", "stringify"]`,
|
|
10
|
+
* measured against Bun 1.4.0 on 2026-09-23) but its output does not fit these rules:
|
|
11
|
+
* (a) a multi-line `run:` comes out as a double-quoted string with `\n` escapes, e.g.
|
|
12
|
+
* `run: "echo a\necho b\n"`, not a `|` block scalar; (b) `09:00` comes out UNQUOTED,
|
|
13
|
+
* e.g. `cron: 09:00`, the YAML 1.1 sexagesimal trap the `scalar()` comment below guards
|
|
14
|
+
* against; (c) a mapping key is followed by a trailing space, e.g. `"steps: \n - ..."`;
|
|
15
|
+
* and (d) a plain JS object has nowhere to attach a comment, so it cannot carry one. The
|
|
16
|
+
* tests parse what this writes with `Bun.YAML.parse` and compare structures, so a
|
|
17
|
+
* malformed emission fails rather than shipping.
|
|
12
18
|
*/
|
|
13
19
|
import type { JobStep } from './shape.ts';
|
|
14
20
|
|
|
@@ -53,13 +59,29 @@ function renderMapping(
|
|
|
53
59
|
return Object.entries(entries).map(([key, value]) => `${indent(depth)}${key}: ${scalar(value)}`);
|
|
54
60
|
}
|
|
55
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Trim trailing `\n` characters the way `command.replace(/\n+$/, '')` used to, but
|
|
64
|
+
* linear instead of backtracking — the same pattern as `normalizeBaseUrl` in
|
|
65
|
+
* `packages/distilled-netbox/src/credentials.ts`. Exported so a test can compare it
|
|
66
|
+
* against the old regex directly.
|
|
67
|
+
*
|
|
68
|
+
* ⚠️ Linear on purpose: a `/\n+$/` regex backtracks polynomially on a long run of
|
|
69
|
+
* "\n" that is not at the end (CodeQL js/polynomial-redos), and `command` here is
|
|
70
|
+
* repository-configured step text.
|
|
71
|
+
*/
|
|
72
|
+
export function trimTrailingNewlines(value: string): string {
|
|
73
|
+
let end = value.length;
|
|
74
|
+
while (end > 0 && value.charCodeAt(end - 1) === 10) end--;
|
|
75
|
+
return value.slice(0, end);
|
|
76
|
+
}
|
|
77
|
+
|
|
56
78
|
/**
|
|
57
79
|
* ★ BLOCK SCALAR FOR EVERY MULTI-LINE `run:`. A folded or quoted form would join the
|
|
58
80
|
* lines, and a shell script whose `if` and `then` end up on one line is a syntax error
|
|
59
81
|
* at job time rather than at lint time. `|` keeps them exactly as written.
|
|
60
82
|
*/
|
|
61
83
|
function renderRun(command: string, depth: number): string[] {
|
|
62
|
-
const lines = command
|
|
84
|
+
const lines = trimTrailingNewlines(command).split('\n');
|
|
63
85
|
if (lines.length === 1) return [`${indent(depth)}run: ${scalar(lines[0] ?? '')}`];
|
|
64
86
|
return [`${indent(depth)}run: |`, ...lines.map((line) => `${indent(depth + 1)}${line}`)];
|
|
65
87
|
}
|