@verndale/ai-commit 2.5.2 → 2.5.3
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 +3 -1
- package/bin/cli.js +8 -0
- package/lib/init-workspace.js +87 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ pnpm exec ai-commit init
|
|
|
47
47
|
| Husky | Runs **`npx husky@9 init`** at the **git root** if **`husky.sh`** is missing under the resolved hooks directory. |
|
|
48
48
|
| Hooks directory | **`core.hooksPath`** relative to the git root when set; otherwise **`<git-root>/.husky`**. Falls back to **`.husky`** at the git root with a warning if the config path is invalid or outside the repo. |
|
|
49
49
|
| `package.json` | Adds missing **`commit`**, **`prepare`**, **`husky`** entries when **`package.json`** exists at the package root. |
|
|
50
|
-
| Hooks | Writes **`prepare-commit-msg`** and **`commit-msg`** in the hooks directory. If package root ≠ git root, each hook **`cd`s** into the package directory before **`pnpm exec ai-commit`** / **`npx`**. |
|
|
50
|
+
| Hooks | Writes **`prepare-commit-msg`** and **`commit-msg`** in the hooks directory. If package root ≠ git root, each hook **`cd`s** into the package directory before **`pnpm exec ai-commit`** / **`npx`**. Removes a **stock** **`.husky/pre-commit`** that is only **`npm`**/**`pnpm`**/**`yarn`** **`test`** (Husky’s **`init`** default) so that hook does not block commits; custom **pre-commit** files are kept. |
|
|
51
51
|
|
|
52
52
|
If **`package.json`** changed, run **`pnpm install`** (or `npm install`) again.
|
|
53
53
|
|
|
@@ -171,6 +171,8 @@ pnpm exec ai-commit lint --edit "$1"
|
|
|
171
171
|
|
|
172
172
|
Hooks from **`init`** use **`pnpm exec ai-commit`** when **`pnpm-lock.yaml`** exists in the **package root**; otherwise **`npx --no ai-commit`**. In a monorepo, generated hooks **`cd`** from the git root into that package directory first. Edit the files if you use another runner.
|
|
173
173
|
|
|
174
|
+
**`pre-commit`:** Husky’s **`init`** often adds **`.husky/pre-commit`** with only **`pnpm test`** (or **`npm test`** / **`yarn test`**). That can block **`git commit`** when tests fail. On each **`ai-commit init`**, **`init`** removes **only** that stock one-liner (or the same command behind a minimal **`husky.sh`** wrapper). If you add other lines (e.g. **lint-staged**), the file is left unchanged. Add your own **pre-commit** or rely on **CI** if you still want tests on every commit.
|
|
175
|
+
|
|
174
176
|
**Already using Husky?** If **`.husky/_/husky.sh`** exists, **`init`** does not run **`npx husky@9 init`**. **`package.json`** is only amended for missing **`commit`**, **`prepare`**, or **`devDependencies.husky`**. Existing **`.husky/prepare-commit-msg`** and **`.husky/commit-msg`** are not overwritten unless you use **`ai-commit init --force`**.
|
|
175
177
|
|
|
176
178
|
---
|
package/bin/cli.js
CHANGED
|
@@ -22,6 +22,7 @@ const {
|
|
|
22
22
|
detectPackageExec,
|
|
23
23
|
hookScript,
|
|
24
24
|
runHuskyInit,
|
|
25
|
+
removeHuskyDefaultPreCommitIfPresent,
|
|
25
26
|
mergePackageJsonForAiCommit,
|
|
26
27
|
warnIfPrepareMissingHusky,
|
|
27
28
|
} = require("../lib/init-workspace.js");
|
|
@@ -229,6 +230,13 @@ function cmdInit(argv) {
|
|
|
229
230
|
fs.mkdirSync(huskyDir, { recursive: true });
|
|
230
231
|
}
|
|
231
232
|
|
|
233
|
+
for (const abs of removeHuskyDefaultPreCommitIfPresent(gitRoot, huskyDir)) {
|
|
234
|
+
const rel = path.relative(cwd, abs) || path.basename(abs);
|
|
235
|
+
process.stdout.write(
|
|
236
|
+
`Removed Husky default pre-commit (${rel}); add your own .husky/pre-commit or use CI if you want tests on every commit.\n`,
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
232
240
|
const execPrefix = detectPackageExec(packageRoot);
|
|
233
241
|
const preparePath = path.join(huskyDir, "prepare-commit-msg");
|
|
234
242
|
const commitMsgPath = path.join(huskyDir, "commit-msg");
|
package/lib/init-workspace.js
CHANGED
|
@@ -61,6 +61,92 @@ function runHuskyInit(cwd) {
|
|
|
61
61
|
return { ok: status === 0, status };
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Husky `init` writes `.husky/pre-commit` with only `(npm|pnpm|yarn) test` (see husky bin.js).
|
|
66
|
+
* That often breaks commits when tests fail or are slow. Match that template and optional
|
|
67
|
+
* minimal shebang + husky.sh wrapper so we do not delete custom hooks.
|
|
68
|
+
* @param {string} raw
|
|
69
|
+
* @returns {boolean}
|
|
70
|
+
*/
|
|
71
|
+
function isHuskyDefaultPreCommitContent(raw) {
|
|
72
|
+
const text = raw.replace(/\r\n/g, "\n").trim();
|
|
73
|
+
const nonEmpty = text
|
|
74
|
+
.split("\n")
|
|
75
|
+
.map((l) => l.trim())
|
|
76
|
+
.filter((l) => {
|
|
77
|
+
if (l.length === 0) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
if (/^#!\//.test(l)) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
return !/^\s*#/.test(l);
|
|
84
|
+
});
|
|
85
|
+
if (nonEmpty.length === 0) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
if (nonEmpty.length === 1) {
|
|
89
|
+
return /^(npm|pnpm|yarn)\s+test$/i.test(nonEmpty[0]);
|
|
90
|
+
}
|
|
91
|
+
const last = nonEmpty[nonEmpty.length - 1];
|
|
92
|
+
if (!/^(npm|pnpm|yarn)\s+test$/i.test(last)) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
const head = nonEmpty.slice(0, -1);
|
|
96
|
+
const shebang = /^#!\/usr\/bin\/env\s+sh$/.test(head[0]);
|
|
97
|
+
const huskySource = head.some((l) => {
|
|
98
|
+
if (/\bhusky\.sh\b/.test(l)) {
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
if (l.includes("$(dirname") && (l.includes("_/husky.sh") || l.includes('_/h"'))) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
return false;
|
|
105
|
+
});
|
|
106
|
+
return shebang && huskySource && head.length <= 3;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Remove Husky’s stock `pre-commit` (e.g. `pnpm test`) from common paths. Custom hooks are kept.
|
|
111
|
+
* @param {string} gitRoot
|
|
112
|
+
* @param {string} huskyDir Resolved hooks directory (from `core.hooksPath` or `.husky`)
|
|
113
|
+
* @returns {string[]} Absolute paths of removed files
|
|
114
|
+
*/
|
|
115
|
+
function removeHuskyDefaultPreCommitIfPresent(gitRoot, huskyDir) {
|
|
116
|
+
const candidates = [
|
|
117
|
+
path.join(huskyDir, "pre-commit"),
|
|
118
|
+
path.join(gitRoot, ".husky", "pre-commit"),
|
|
119
|
+
];
|
|
120
|
+
const seen = new Set();
|
|
121
|
+
const removed = [];
|
|
122
|
+
for (const filePath of candidates) {
|
|
123
|
+
const abs = path.resolve(filePath);
|
|
124
|
+
if (seen.has(abs)) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
seen.add(abs);
|
|
128
|
+
if (!fs.existsSync(abs)) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
let raw;
|
|
132
|
+
try {
|
|
133
|
+
raw = fs.readFileSync(abs, "utf8");
|
|
134
|
+
} catch {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (!isHuskyDefaultPreCommitContent(raw)) {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
fs.unlinkSync(abs);
|
|
142
|
+
removed.push(abs);
|
|
143
|
+
} catch {
|
|
144
|
+
// ignore
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return removed;
|
|
148
|
+
}
|
|
149
|
+
|
|
64
150
|
/**
|
|
65
151
|
* Ensure `commit` script, `prepare` for husky, and `devDependencies.husky`. Does not remove existing scripts.
|
|
66
152
|
* @param {string} packageJsonPath
|
|
@@ -117,6 +203,7 @@ module.exports = {
|
|
|
117
203
|
detectPackageExec,
|
|
118
204
|
hookScript,
|
|
119
205
|
runHuskyInit,
|
|
206
|
+
removeHuskyDefaultPreCommitIfPresent,
|
|
120
207
|
mergePackageJsonForAiCommit,
|
|
121
208
|
warnIfPrepareMissingHusky,
|
|
122
209
|
};
|