@zjex/git-workflow 0.4.6 → 0.5.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/CHANGELOG.md +136 -377
- package/README.md +44 -6
- package/dist/index.js +675 -31
- package/docs/.vitepress/cache/deps/_metadata.json +10 -10
- package/docs/.vitepress/config.ts +4 -0
- package/docs/commands/index.md +4 -0
- package/docs/commands/review.md +142 -0
- package/docs/guide/ai-review.md +159 -0
- package/docs/guide/index.md +2 -0
- package/docs/index.md +26 -3
- package/package.json +1 -1
- package/scripts/generate-changelog-manual.js +15 -64
- package/src/commands/review.ts +759 -0
- package/src/commands/tag.ts +42 -10
- package/src/commands/update.ts +25 -9
- package/src/index.ts +29 -1
- package/src/utils.ts +3 -1
- package/tests/review.test.ts +1058 -0
- package/tests/update.test.ts +85 -69
- package/docs/.vitepress/cache/deps_temp_44e2fb0f/chunk-2CLQ7TTZ.js +0 -9719
- package/docs/.vitepress/cache/deps_temp_44e2fb0f/chunk-2CLQ7TTZ.js.map +0 -7
- package/docs/.vitepress/cache/deps_temp_44e2fb0f/chunk-LE5NDSFD.js +0 -12824
- package/docs/.vitepress/cache/deps_temp_44e2fb0f/chunk-LE5NDSFD.js.map +0 -7
- package/docs/.vitepress/cache/deps_temp_44e2fb0f/package.json +0 -3
- package/docs/.vitepress/cache/deps_temp_44e2fb0f/vitepress___@vue_devtools-api.js +0 -4505
- package/docs/.vitepress/cache/deps_temp_44e2fb0f/vitepress___@vue_devtools-api.js.map +0 -7
- package/docs/.vitepress/cache/deps_temp_44e2fb0f/vitepress___@vueuse_core.js +0 -583
- package/docs/.vitepress/cache/deps_temp_44e2fb0f/vitepress___@vueuse_core.js.map +0 -7
- package/docs/.vitepress/cache/deps_temp_44e2fb0f/vitepress___@vueuse_integrations_useFocusTrap.js +0 -1352
- package/docs/.vitepress/cache/deps_temp_44e2fb0f/vitepress___@vueuse_integrations_useFocusTrap.js.map +0 -7
- package/docs/.vitepress/cache/deps_temp_44e2fb0f/vitepress___mark__js_src_vanilla__js.js +0 -1665
- package/docs/.vitepress/cache/deps_temp_44e2fb0f/vitepress___mark__js_src_vanilla__js.js.map +0 -7
- package/docs/.vitepress/cache/deps_temp_44e2fb0f/vitepress___minisearch.js +0 -1813
- package/docs/.vitepress/cache/deps_temp_44e2fb0f/vitepress___minisearch.js.map +0 -7
- package/docs/.vitepress/cache/deps_temp_44e2fb0f/vue.js +0 -347
- package/docs/.vitepress/cache/deps_temp_44e2fb0f/vue.js.map +0 -7
package/src/commands/tag.ts
CHANGED
|
@@ -418,6 +418,29 @@ export async function createTag(inputPrefix?: string): Promise<void> {
|
|
|
418
418
|
async function doCreateTag(tagName: string): Promise<void> {
|
|
419
419
|
divider();
|
|
420
420
|
|
|
421
|
+
// 检查是否有提交
|
|
422
|
+
const hasCommits = execOutput("git rev-parse HEAD 2>/dev/null");
|
|
423
|
+
if (!hasCommits) {
|
|
424
|
+
console.log(colors.red("当前仓库没有任何提交"));
|
|
425
|
+
console.log("");
|
|
426
|
+
console.log(colors.dim(" 提示: 需要先创建至少一个提交才能打 tag:"));
|
|
427
|
+
console.log(colors.cyan(" git add ."));
|
|
428
|
+
console.log(colors.cyan(' git commit -m "Initial commit"'));
|
|
429
|
+
console.log(colors.cyan(" gw tag"));
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// 检查 tag 是否已存在
|
|
434
|
+
const existingTags = execOutput("git tag -l").split("\n").filter(Boolean);
|
|
435
|
+
if (existingTags.includes(tagName)) {
|
|
436
|
+
console.log(colors.red(`Tag ${tagName} 已存在`));
|
|
437
|
+
console.log("");
|
|
438
|
+
console.log(colors.dim(" 提示: 如需重新创建,请先删除旧 tag:"));
|
|
439
|
+
console.log(colors.cyan(` git tag -d ${tagName}`));
|
|
440
|
+
console.log(colors.cyan(` git push origin --delete ${tagName}`));
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
|
|
421
444
|
const spinner = ora(`正在创建 tag: ${tagName}`).start();
|
|
422
445
|
const success = await execWithSpinner(
|
|
423
446
|
`git tag -a "${tagName}" -m "Release ${tagName}"`,
|
|
@@ -614,9 +637,12 @@ export async function updateTag(): Promise<void> {
|
|
|
614
637
|
}
|
|
615
638
|
|
|
616
639
|
// 删除旧 tag
|
|
617
|
-
const
|
|
618
|
-
if (!
|
|
640
|
+
const deleteResult = await execAsync(`git tag -d "${oldTag}"`, spinner);
|
|
641
|
+
if (!deleteResult.success) {
|
|
619
642
|
spinner.fail("删除旧 tag 失败");
|
|
643
|
+
if (deleteResult.error) {
|
|
644
|
+
console.log(colors.dim(` ${deleteResult.error}`));
|
|
645
|
+
}
|
|
620
646
|
return;
|
|
621
647
|
}
|
|
622
648
|
|
|
@@ -635,26 +661,32 @@ export async function updateTag(): Promise<void> {
|
|
|
635
661
|
const pushSpinner = ora("正在同步到远程...").start();
|
|
636
662
|
|
|
637
663
|
// 推送新 tag
|
|
638
|
-
const
|
|
664
|
+
const pushNewResult = await execAsync(
|
|
639
665
|
`git push origin "${newTag}"`,
|
|
640
666
|
pushSpinner,
|
|
641
667
|
);
|
|
642
|
-
if (!
|
|
668
|
+
if (!pushNewResult.success) {
|
|
643
669
|
pushSpinner.warn(
|
|
644
670
|
`远程同步失败,可稍后手动执行:\n git push origin ${newTag}\n git push origin --delete ${oldTag}`,
|
|
645
671
|
);
|
|
672
|
+
if (pushNewResult.error) {
|
|
673
|
+
console.log(colors.dim(` ${pushNewResult.error}`));
|
|
674
|
+
}
|
|
646
675
|
return;
|
|
647
676
|
}
|
|
648
677
|
|
|
649
678
|
// 删除远程旧 tag
|
|
650
|
-
const
|
|
679
|
+
const deleteOldResult = await execAsync(
|
|
651
680
|
`git push origin --delete "${oldTag}"`,
|
|
652
681
|
pushSpinner,
|
|
653
682
|
);
|
|
654
|
-
if (!
|
|
683
|
+
if (!deleteOldResult.success) {
|
|
655
684
|
pushSpinner.warn(
|
|
656
685
|
`远程旧 tag 删除失败,可稍后手动执行: git push origin --delete ${oldTag}`,
|
|
657
686
|
);
|
|
687
|
+
if (deleteOldResult.error) {
|
|
688
|
+
console.log(colors.dim(` ${deleteOldResult.error}`));
|
|
689
|
+
}
|
|
658
690
|
return;
|
|
659
691
|
}
|
|
660
692
|
|
|
@@ -729,8 +761,8 @@ export async function cleanInvalidTags(): Promise<void> {
|
|
|
729
761
|
let localFailed = 0;
|
|
730
762
|
|
|
731
763
|
for (const tag of invalidTags) {
|
|
732
|
-
const
|
|
733
|
-
if (success) {
|
|
764
|
+
const result = await execAsync(`git tag -d "${tag}"`, localSpinner);
|
|
765
|
+
if (result.success) {
|
|
734
766
|
localSuccess++;
|
|
735
767
|
} else {
|
|
736
768
|
localFailed++;
|
|
@@ -761,11 +793,11 @@ export async function cleanInvalidTags(): Promise<void> {
|
|
|
761
793
|
let remoteFailed = 0;
|
|
762
794
|
|
|
763
795
|
for (const tag of invalidTags) {
|
|
764
|
-
const
|
|
796
|
+
const result = await execAsync(
|
|
765
797
|
`git push origin --delete "${tag}"`,
|
|
766
798
|
remoteSpinner,
|
|
767
799
|
);
|
|
768
|
-
if (success) {
|
|
800
|
+
if (result.success) {
|
|
769
801
|
remoteSuccess++;
|
|
770
802
|
} else {
|
|
771
803
|
remoteFailed++;
|
package/src/commands/update.ts
CHANGED
|
@@ -27,16 +27,32 @@ function clearUpdateCache(): void {
|
|
|
27
27
|
* 获取 npm 上的最新版本
|
|
28
28
|
*/
|
|
29
29
|
async function getLatestVersion(packageName: string): Promise<string | null> {
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
timeout:
|
|
34
|
-
stdio: ["pipe", "pipe", "ignore"],
|
|
30
|
+
return new Promise((resolve) => {
|
|
31
|
+
const npmView = spawn("npm", ["view", packageName, "version"], {
|
|
32
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
33
|
+
timeout: 5000,
|
|
35
34
|
});
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
|
|
36
|
+
let output = "";
|
|
37
|
+
|
|
38
|
+
if (npmView.stdout) {
|
|
39
|
+
npmView.stdout.on("data", (data) => {
|
|
40
|
+
output += data.toString();
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
npmView.on("close", (code) => {
|
|
45
|
+
if (code === 0 && output.trim()) {
|
|
46
|
+
resolve(output.trim());
|
|
47
|
+
} else {
|
|
48
|
+
resolve(null);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
npmView.on("error", () => {
|
|
53
|
+
resolve(null);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
40
56
|
}
|
|
41
57
|
|
|
42
58
|
/**
|
package/src/index.ts
CHANGED
|
@@ -31,6 +31,7 @@ import { update } from "./commands/update.js";
|
|
|
31
31
|
import { log, quickLog } from "./commands/log.js";
|
|
32
32
|
import { amendDate } from "./commands/amend-date.js";
|
|
33
33
|
import { amend } from "./commands/amend.js";
|
|
34
|
+
import { review } from "./commands/review.js";
|
|
34
35
|
|
|
35
36
|
// ========== 全局错误处理 ==========
|
|
36
37
|
|
|
@@ -171,7 +172,11 @@ async function mainMenu(): Promise<void> {
|
|
|
171
172
|
value: "amend",
|
|
172
173
|
},
|
|
173
174
|
{
|
|
174
|
-
name: `[e]
|
|
175
|
+
name: `[e] 🔍 AI 代码审查 ${colors.dim("gw review")}`,
|
|
176
|
+
value: "review",
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
name: `[f] ⚙️ 初始化配置 ${colors.dim("gw init")}`,
|
|
175
180
|
value: "init",
|
|
176
181
|
},
|
|
177
182
|
{ name: "[0] ❓ 帮助", value: "help" },
|
|
@@ -233,6 +238,10 @@ async function mainMenu(): Promise<void> {
|
|
|
233
238
|
checkGitRepo();
|
|
234
239
|
await amend();
|
|
235
240
|
break;
|
|
241
|
+
case "review":
|
|
242
|
+
checkGitRepo();
|
|
243
|
+
await review();
|
|
244
|
+
break;
|
|
236
245
|
case "init":
|
|
237
246
|
await init();
|
|
238
247
|
break;
|
|
@@ -413,6 +422,25 @@ cli
|
|
|
413
422
|
return amend(hash);
|
|
414
423
|
});
|
|
415
424
|
|
|
425
|
+
cli
|
|
426
|
+
.command("review [...hashes]", "AI 代码审查")
|
|
427
|
+
.alias("rw")
|
|
428
|
+
.option("-n, --last <number>", "审查最近 N 个 commits")
|
|
429
|
+
.option("-s, --staged", "审查暂存区的更改")
|
|
430
|
+
.option("-o, --output <path>", "指定输出文件路径")
|
|
431
|
+
.action(async (hashes: string[], options: any) => {
|
|
432
|
+
await checkForUpdates(version, "@zjex/git-workflow");
|
|
433
|
+
checkGitRepo();
|
|
434
|
+
return review(
|
|
435
|
+
hashes.length > 0 ? hashes : undefined,
|
|
436
|
+
{
|
|
437
|
+
last: options.last ? parseInt(options.last) : undefined,
|
|
438
|
+
staged: options.staged,
|
|
439
|
+
output: options.output,
|
|
440
|
+
}
|
|
441
|
+
);
|
|
442
|
+
});
|
|
443
|
+
|
|
416
444
|
cli
|
|
417
445
|
.command("clean", "清理缓存和临时文件")
|
|
418
446
|
.alias("cc")
|
package/src/utils.ts
CHANGED
|
@@ -166,7 +166,9 @@ export function execAsync(
|
|
|
166
166
|
console.log(colors.dim(`[DEBUG] 标准输出:\n${stdoutOutput}`));
|
|
167
167
|
}
|
|
168
168
|
if (errorOutput) {
|
|
169
|
-
|
|
169
|
+
// 根据退出码决定标签:成功时显示"输出信息",失败时显示"错误输出"
|
|
170
|
+
const label = code === 0 ? "输出信息" : "错误输出";
|
|
171
|
+
console.log(colors.dim(`[DEBUG] ${label}:\n${errorOutput}`));
|
|
170
172
|
}
|
|
171
173
|
}
|
|
172
174
|
|