ai-project-manage-cli 6.0.80 → 6.0.81
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 +1 -0
- package/dist/index.js +66 -32
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -1180,22 +1180,47 @@ async function ensureGitRepo2(cwd) {
|
|
|
1180
1180
|
async function getCurrentBranch2(cwd) {
|
|
1181
1181
|
return (await execGit3(cwd, ["rev-parse", "--abbrev-ref", "HEAD"], true)).trim();
|
|
1182
1182
|
}
|
|
1183
|
-
async function
|
|
1183
|
+
async function resolveBaselineBranch(cwd, api) {
|
|
1184
|
+
const workdirPath = resolveWorkdirPath(cwd);
|
|
1185
|
+
const baseline = await api.cli.workspaceBaseline({ workdirPath });
|
|
1186
|
+
if (!baseline.repositoryId) {
|
|
1187
|
+
const detail = baseline.diagnostic?.message ?? `\u672A\u5728\u5E73\u53F0\u627E\u5230\u4E0E\u5F53\u524D\u76EE\u5F55\u5339\u914D\u7684\u5DE5\u4F5C\u76EE\u5F55\u767B\u8BB0\uFF1A${workdirPath}\uFF08\u89C4\u8303\u5316\uFF1A${baseline.workdirPath}\uFF09
|
|
1188
|
+
\u8BF7\u5148\u5728\u5E73\u53F0\u767B\u8BB0\u8BE5\u8DEF\u5F84\u5BF9\u5E94\u7684\u5DE5\u4F5C\u76EE\u5F55\u4E0E\u4ED3\u5E93\u3002`;
|
|
1189
|
+
throw new Error(`[apm] ${detail}`);
|
|
1190
|
+
}
|
|
1191
|
+
const baselineBranch = (baseline.defaultBranch ?? "").trim();
|
|
1192
|
+
if (!baselineBranch) {
|
|
1193
|
+
throw new Error("[apm] \u5E73\u53F0\u8FD4\u56DE\u7684\u57FA\u7EBF\u5206\u652F\u540D\u4E3A\u7A7A");
|
|
1194
|
+
}
|
|
1195
|
+
await execGit3(cwd, ["fetch", "origin", baselineBranch], true);
|
|
1196
|
+
if (!await remoteBranchExists(cwd, baselineBranch)) {
|
|
1197
|
+
throw new Error(
|
|
1198
|
+
`[apm] \u8FDC\u7A0B\u4E0D\u5B58\u5728\u57FA\u7EBF\u5206\u652F origin/${baselineBranch}\uFF0C\u8BF7\u786E\u8BA4\u4ED3\u5E93\u9ED8\u8BA4\u5206\u652F\u5DF2\u63A8\u9001\u5230 origin`
|
|
1199
|
+
);
|
|
1200
|
+
}
|
|
1201
|
+
return baselineBranch;
|
|
1202
|
+
}
|
|
1203
|
+
async function isBranchBasedOnBaseline(cwd, branch, baselineBranch) {
|
|
1204
|
+
const ref = await localBranchExists2(cwd, branch) ? branch : `origin/${branch}`;
|
|
1184
1205
|
try {
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1206
|
+
await execGit3(
|
|
1207
|
+
cwd,
|
|
1208
|
+
["merge-base", "--is-ancestor", `origin/${baselineBranch}`, ref],
|
|
1209
|
+
true
|
|
1210
|
+
);
|
|
1211
|
+
return true;
|
|
1190
1212
|
} catch {
|
|
1213
|
+
return false;
|
|
1191
1214
|
}
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
const
|
|
1195
|
-
if (
|
|
1196
|
-
|
|
1215
|
+
}
|
|
1216
|
+
async function listCandidateSessionBranches(cwd, includeRemote) {
|
|
1217
|
+
const names = new Set(await listLocalSessionBranches(cwd));
|
|
1218
|
+
if (includeRemote) {
|
|
1219
|
+
for (const branch of await listRemoteSessionBranches(cwd)) {
|
|
1220
|
+
names.add(branch);
|
|
1221
|
+
}
|
|
1197
1222
|
}
|
|
1198
|
-
|
|
1223
|
+
return [...names].sort((a, b) => a.localeCompare(b));
|
|
1199
1224
|
}
|
|
1200
1225
|
async function listLocalSessionBranches(cwd) {
|
|
1201
1226
|
const out = await execGit3(
|
|
@@ -1268,20 +1293,27 @@ async function isBranchMergedIntoDefault(cwd, branch, defaultBranch) {
|
|
|
1268
1293
|
async function runCleanBranches(options = {}) {
|
|
1269
1294
|
const cwd = options.cwd ?? process.cwd();
|
|
1270
1295
|
const dryRun = options.dryRun ?? false;
|
|
1296
|
+
const includeRemote = options.includeRemote ?? false;
|
|
1271
1297
|
await ensureGitRepo2(cwd);
|
|
1272
1298
|
await execGit3(cwd, ["fetch", "--prune", "origin"], true);
|
|
1273
1299
|
const cfg = await ensureLoggedConfig();
|
|
1274
1300
|
const api = createApmApiClient(cfg);
|
|
1301
|
+
const baselineBranch = await resolveBaselineBranch(cwd, api);
|
|
1275
1302
|
const { sessions } = await api.cli.listSessionsForBranchCleanup({});
|
|
1276
1303
|
const sessionStatusById = new Map(
|
|
1277
1304
|
sessions.map((item) => [item.sessionId, item.taskStatus])
|
|
1278
1305
|
);
|
|
1279
|
-
const
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1306
|
+
const candidates = await listCandidateSessionBranches(cwd, includeRemote);
|
|
1307
|
+
const branchNames = [];
|
|
1308
|
+
for (const branch of candidates) {
|
|
1309
|
+
if (await isBranchBasedOnBaseline(cwd, branch, baselineBranch)) {
|
|
1310
|
+
branchNames.push(branch);
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
if (branchNames.length === 0) {
|
|
1314
|
+
console.log(
|
|
1315
|
+
`[apm] \u672A\u53D1\u73B0\u4ECE ${baselineBranch} \u884D\u751F\u7684\u672C\u5730 feat/session-* \u5206\u652F${includeRemote ? "\uFF08\u542B\u8FDC\u7A0B\uFF09" : ""}`
|
|
1316
|
+
);
|
|
1285
1317
|
return;
|
|
1286
1318
|
}
|
|
1287
1319
|
const toDelete = [...branchNames].map((branch) => {
|
|
@@ -1300,10 +1332,6 @@ async function runCleanBranches(options = {}) {
|
|
|
1300
1332
|
return;
|
|
1301
1333
|
}
|
|
1302
1334
|
let currentBranch = await getCurrentBranch2(cwd);
|
|
1303
|
-
let defaultBranch = null;
|
|
1304
|
-
if (dryRun) {
|
|
1305
|
-
defaultBranch = await resolveDefaultBranch(cwd);
|
|
1306
|
-
}
|
|
1307
1335
|
for (const item of toDelete) {
|
|
1308
1336
|
const { branch, sessionId, reason } = item;
|
|
1309
1337
|
const label = `${branch} (${sessionId}: ${reason})`;
|
|
@@ -1311,16 +1339,15 @@ async function runCleanBranches(options = {}) {
|
|
|
1311
1339
|
const merged = await isBranchMergedIntoDefault(
|
|
1312
1340
|
cwd,
|
|
1313
1341
|
branch,
|
|
1314
|
-
|
|
1342
|
+
baselineBranch
|
|
1315
1343
|
);
|
|
1316
1344
|
const mergeTag = merged ? "\u5DF2\u5408\u5E76" : "\u672A\u5408\u5E76";
|
|
1317
1345
|
console.log(`[apm] [dry-run] \u5C06\u5220\u9664 ${label} [${mergeTag}]`);
|
|
1318
1346
|
continue;
|
|
1319
1347
|
}
|
|
1320
1348
|
if (currentBranch === branch) {
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
currentBranch = defaultBranch;
|
|
1349
|
+
await execGit3(cwd, ["checkout", baselineBranch], true);
|
|
1350
|
+
currentBranch = baselineBranch;
|
|
1324
1351
|
}
|
|
1325
1352
|
if (await localBranchExists2(cwd, branch)) {
|
|
1326
1353
|
await execGit3(cwd, ["branch", "-D", branch], true);
|
|
@@ -6147,17 +6174,24 @@ function buildProgram() {
|
|
|
6147
6174
|
lines: Number.isFinite(lines) && lines > 0 ? lines : 100
|
|
6148
6175
|
});
|
|
6149
6176
|
});
|
|
6150
|
-
program.command("branch").description("\
|
|
6177
|
+
const branch = program.command("branch").description("\u4F1A\u8BDD\u5206\u652F feat/session-<sessionId>");
|
|
6178
|
+
branch.command("prune").description(
|
|
6179
|
+
"\u6E05\u7406\u672C\u5730\u4E0E\u8FDC\u7A0B feat/session-* \u5206\u652F\uFF08\u7C7B\u4F3C git fetch --prune\uFF09\uFF1A\u6C9F\u901A\u7FA4\u4E0D\u5728\u4EFB\u52A1\u5217\u8868\u4E2D\uFF0C\u6216\u5173\u8054\u4EFB\u52A1\u5DF2\u5B8C\u6210\u65F6\u5220\u9664"
|
|
6180
|
+
).option("--dry-run", "\u4EC5\u5217\u51FA\u5C06\u88AB\u5220\u9664\u7684\u5206\u652F\uFF0C\u4E0D\u5B9E\u9645\u6267\u884C").option(
|
|
6181
|
+
"-A, --all",
|
|
6182
|
+
"\u5305\u542B\u4EC5\u5B58\u5728\u4E8E\u8FDC\u7A0B\u3001\u672C\u5730\u672A checkout \u7684 feat/session-* \u5206\u652F\uFF08\u9ED8\u8BA4\u4EC5\u5904\u7406\u672C\u5730\u5206\u652F\uFF09"
|
|
6183
|
+
).action(async (opts) => {
|
|
6184
|
+
await runCleanBranches({
|
|
6185
|
+
dryRun: opts.dryRun,
|
|
6186
|
+
includeRemote: opts.all
|
|
6187
|
+
});
|
|
6188
|
+
});
|
|
6189
|
+
branch.description("\u5207\u6362\u6216\u521B\u5EFA\u4F1A\u8BDD\u5206\u652F feat/session-<sessionId>").argument("<sessionId>", "\u6C9F\u901A\u7FA4 ID").option(
|
|
6151
6190
|
"-m, --message <text>",
|
|
6152
6191
|
"\u5DF2\u5728\u76EE\u6807\u5206\u652F\u4E14\u9700\u63D0\u4EA4\u672C\u5730\u6539\u52A8\u65F6\u4F7F\u7528\u7684\u63D0\u4EA4\u8BF4\u660E"
|
|
6153
6192
|
).action(async (sessionId, opts) => {
|
|
6154
6193
|
await runBranch(sessionId, { message: opts.message });
|
|
6155
6194
|
});
|
|
6156
|
-
program.command("clean-branches").description(
|
|
6157
|
-
"\u6E05\u7406\u672C\u5730\u4E0E\u8FDC\u7A0B feat/session-* \u5206\u652F\uFF1A\u6C9F\u901A\u7FA4\u4E0D\u5728\u4EFB\u52A1\u5217\u8868\u4E2D\uFF0C\u6216\u5173\u8054\u4EFB\u52A1\u5DF2\u5B8C\u6210\u65F6\u5220\u9664"
|
|
6158
|
-
).option("--dry-run", "\u4EC5\u5217\u51FA\u5C06\u88AB\u5220\u9664\u7684\u5206\u652F\uFF0C\u4E0D\u5B9E\u9645\u6267\u884C").action(async (opts) => {
|
|
6159
|
-
await runCleanBranches({ dryRun: opts.dryRun });
|
|
6160
|
-
});
|
|
6161
6195
|
program.command("create-pr").description(
|
|
6162
6196
|
"\u4E3A\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u7684\u4F1A\u8BDD\u7279\u6027\u5206\u652F\u521B\u5EFA PR\uFF08\u6807\u9898\u81EA\u52A8\u52A0 [AI] \u6807\u8BC6\uFF1B\u8FDC\u7A0B\u521B\u5EFA\u5931\u8D25\u65F6\u5E73\u53F0\u6570\u636E\u56DE\u6EDA\uFF09"
|
|
6163
6197
|
).requiredOption("--session <sessionId>", "\u6C9F\u901A\u7FA4 ID").requiredOption("--title <title>", "PR \u6807\u9898").option("--content <content>", "PR \u6B63\u6587\uFF08Markdown\uFF09", "").action(
|