@d5render/cli 0.1.31 → 0.1.33
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 +2 -2
- package/bin/copilot.js +1 -1
- package/bin/d5cli +112 -120
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
for devops,
|
|
1
|
+
for devops, please refer [.skills/devops](.skills/devops)
|
|
2
2
|
|
|
3
|
-
for codereview,
|
|
3
|
+
for codereview, please refer[.skills/review/SKILL.md](.skills/review/SKILL.md)
|
package/bin/copilot.js
CHANGED
|
@@ -18872,7 +18872,7 @@ const NAME = name$1.replaceAll("/", "_");
|
|
|
18872
18872
|
const RUNTIME_CWD = join(dirname(fileURLToPath(import.meta.url)), "../");
|
|
18873
18873
|
const HOME = env.USERPROFILE ?? env.HOME ?? env.HOMEPATH;
|
|
18874
18874
|
if (!HOME) throw new Error("cannot find `USERPROFILE` directory");
|
|
18875
|
-
const TEMP = env.CI_PROJECT_DIR + NAME;
|
|
18875
|
+
const TEMP = env.CI_PROJECT_DIR + "." + NAME;
|
|
18876
18876
|
|
|
18877
18877
|
//#endregion
|
|
18878
18878
|
//#region copilot/server/config.ts
|
package/bin/d5cli
CHANGED
|
@@ -7,7 +7,59 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
|
|
8
8
|
//#region package.json
|
|
9
9
|
var name$1 = "@d5render/cli";
|
|
10
|
-
var version = "0.1.
|
|
10
|
+
var version = "0.1.33";
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region copilot/server/config.ts
|
|
14
|
+
const name = "d5_mcp_review_builtin";
|
|
15
|
+
const report = "report";
|
|
16
|
+
const getHash = "hash";
|
|
17
|
+
const file = "bin/copilot.js";
|
|
18
|
+
const serveFile = join(RUNTIME_CWD, file);
|
|
19
|
+
const envJson = buildEnv();
|
|
20
|
+
const envUsed = {
|
|
21
|
+
CI_SERVER_URL: toEnv("CI_SERVER_URL"),
|
|
22
|
+
CI_PROJECT_PATH: toEnv("CI_PROJECT_PATH"),
|
|
23
|
+
CI_PROJECT_ID: toEnv("CI_PROJECT_ID"),
|
|
24
|
+
CI_PROJECT_NAME: toEnv("CI_PROJECT_NAME"),
|
|
25
|
+
CI_COMMIT_SHA: toEnv("CI_COMMIT_SHA"),
|
|
26
|
+
CI_COMMIT_BEFORE_SHA: toEnv("CI_COMMIT_BEFORE_SHA"),
|
|
27
|
+
CI_MERGE_REQUEST_IID: toEnv("CI_MERGE_REQUEST_IID"),
|
|
28
|
+
CI_MERGE_REQUEST_TITLE: toEnv("CI_MERGE_REQUEST_TITLE"),
|
|
29
|
+
CI_MERGE_REQUEST_DESCRIPTION: toEnv("CI_MERGE_REQUEST_DESCRIPTION"),
|
|
30
|
+
JIRA_BASE_URL: toEnv("JIRA_BASE_URL", "http://jira.d5techs.com.cn"),
|
|
31
|
+
DINGTALK_WEBHOOK: toEnv("DINGTALK_WEBHOOK"),
|
|
32
|
+
GITLAB_TOKEN: toEnv("GITLAB_TOKEN"),
|
|
33
|
+
JIRA_PAT: toEnv("JIRA_PAT"),
|
|
34
|
+
JIRA_COOKIE: toEnv("JIRA_COOKIE"),
|
|
35
|
+
JIRA_USERNAME: toEnv("JIRA_USERNAME"),
|
|
36
|
+
JIRA_PASSWORD: toEnv("JIRA_PASSWORD")
|
|
37
|
+
};
|
|
38
|
+
const tools = [
|
|
39
|
+
"--additional-mcp-config",
|
|
40
|
+
JSON.stringify({ mcpServers: { [name]: {
|
|
41
|
+
type: "local",
|
|
42
|
+
command: "node",
|
|
43
|
+
args: [serveFile, `--customizenv=${JSON.stringify(envUsed)}`],
|
|
44
|
+
tools: ["*"]
|
|
45
|
+
} } }),
|
|
46
|
+
"--allow-all-paths",
|
|
47
|
+
"--allow-all-tools",
|
|
48
|
+
"--deny-tool",
|
|
49
|
+
"write",
|
|
50
|
+
"--deny-tool",
|
|
51
|
+
"github-mcp-server"
|
|
52
|
+
];
|
|
53
|
+
tools.push("--model", "claude-sonnet-4.5");
|
|
54
|
+
function toEnv(key, defaultValue) {
|
|
55
|
+
return envJson[key] || process.env[key] || defaultValue;
|
|
56
|
+
}
|
|
57
|
+
function buildEnv() {
|
|
58
|
+
const envArg = argv.find((arg) => arg.startsWith("--customizenv="));
|
|
59
|
+
let envJson$1 = {};
|
|
60
|
+
if (envArg) envJson$1 = JSON.parse(envArg.replace("--customizenv=", ""));
|
|
61
|
+
return envJson$1;
|
|
62
|
+
}
|
|
11
63
|
|
|
12
64
|
//#endregion
|
|
13
65
|
//#region packages/gitlab/url.ts
|
|
@@ -71,8 +123,16 @@ const VERSION = version;
|
|
|
71
123
|
const RUNTIME_CWD = join(dirname(fileURLToPath(import.meta.url)), "../");
|
|
72
124
|
const HOME = env.USERPROFILE ?? env.HOME ?? env.HOMEPATH;
|
|
73
125
|
if (!HOME) throw new Error("cannot find `USERPROFILE` directory");
|
|
74
|
-
const TEMP = env.CI_PROJECT_DIR + NAME;
|
|
75
|
-
|
|
126
|
+
const TEMP = env.CI_PROJECT_DIR + "." + NAME;
|
|
127
|
+
const dingding = async (...args) => {
|
|
128
|
+
try {
|
|
129
|
+
const msg = await (await sendding(...args)).text();
|
|
130
|
+
console.log(msg);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
console.error(error);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
async function deploy() {
|
|
76
136
|
if (!env.CI) return;
|
|
77
137
|
const config = join(HOME, ".copilot/config.json"), dir = join(HOME, ".copilot/skills/codereview");
|
|
78
138
|
console.log("deploy...");
|
|
@@ -82,6 +142,14 @@ function deploy() {
|
|
|
82
142
|
}
|
|
83
143
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
84
144
|
const versiono = readFileSync(join(RUNTIME_CWD, ".skills/review/version"), "utf8");
|
|
145
|
+
const changelog = readFileSync(join(RUNTIME_CWD, "CHANGELOG.md"), "utf8");
|
|
146
|
+
const cachepath = join(TEMP, "CHANGELOG");
|
|
147
|
+
if (changelog !== (existsSync(cachepath) ? readFileSync(cachepath, "utf8") : "")) {
|
|
148
|
+
if (!existsSync(TEMP)) mkdirSync(TEMP, { recursive: true });
|
|
149
|
+
writeFileSync(cachepath, changelog, "utf8");
|
|
150
|
+
console.log("updated CHANGELOG cache.");
|
|
151
|
+
await dingding("NOTICE", `codereview skills has been updated to version ${versiono}\n\nfor more details, please refer to [ONLINE](https://www.npmjs.com/package/@d5render/cli?activeTab=readme)`);
|
|
152
|
+
}
|
|
85
153
|
const versionnPath = join(dir, "version");
|
|
86
154
|
if ((existsSync(versionnPath) ? readFileSync(versionnPath, "utf8") : "") === versiono) return;
|
|
87
155
|
const skillRoot = join(RUNTIME_CWD, ".skills/review");
|
|
@@ -89,25 +157,16 @@ function deploy() {
|
|
|
89
157
|
const instructionsRoot = join(RUNTIME_CWD, ".github/instructions");
|
|
90
158
|
readdirSync(instructionsRoot).forEach((instruction) => copyFileSync(join(instructionsRoot, instruction), join(dir, instruction)));
|
|
91
159
|
console.log("to new skill.");
|
|
92
|
-
const changelog = readFileSync(join(RUNTIME_CWD, "CHANGELOG.md"), "utf8");
|
|
93
|
-
const cachepath = join(TEMP, "CHANGELOG");
|
|
94
|
-
if (!existsSync(TEMP)) mkdirSync(TEMP, { recursive: true });
|
|
95
|
-
if (changelog !== (existsSync(cachepath) ? readFileSync(cachepath, "utf8") : "")) {
|
|
96
|
-
if (!existsSync(cachepath)) mkdirSync(cachepath, { recursive: true });
|
|
97
|
-
writeFileSync(cachepath, changelog, "utf8");
|
|
98
|
-
console.log("updated CHANGELOG cache.");
|
|
99
|
-
sendding("NOTICE", `NOTICE: codereview skills has been updated to version ${versiono}\n\nfor more details, please refer to [ONLINE](https://www.npmjs.com/package/@d5render/cli?activeTab=readme)`);
|
|
100
|
-
}
|
|
101
160
|
}
|
|
102
|
-
function need() {
|
|
161
|
+
async function need() {
|
|
103
162
|
if (!env.CI) return;
|
|
104
|
-
if (!existsSync(TEMP)) mkdirSync(TEMP, { recursive: true });
|
|
105
163
|
const { CI_MERGE_REQUEST_IID, CI_COMMIT_SHA } = env;
|
|
106
164
|
const file$1 = join(TEMP, "CODEREVIEW");
|
|
107
165
|
if (CI_MERGE_REQUEST_IID) {
|
|
108
166
|
let appended = `${existsSync(file$1) ? readFileSync(file$1, "utf8") : ""}\n${CI_MERGE_REQUEST_IID}`.split("\n");
|
|
109
167
|
const max = 1e4;
|
|
110
168
|
if (appended.length > max) appended = appended.slice(-max);
|
|
169
|
+
if (!existsSync(TEMP)) mkdirSync(TEMP, { recursive: true });
|
|
111
170
|
writeFileSync(file$1, appended.join("\n"), "utf8");
|
|
112
171
|
console.log("merge pipeline, recorded IID:", CI_MERGE_REQUEST_IID, "to:", file$1);
|
|
113
172
|
return true;
|
|
@@ -125,70 +184,18 @@ function need() {
|
|
|
125
184
|
console.warn(`Merge Request !${iid} has been AI reviewed before.`);
|
|
126
185
|
const mergeURL = visitPipeline(iid).url;
|
|
127
186
|
const url = `${commits()}/${CI_COMMIT_SHA}/comments`;
|
|
128
|
-
fetch(url, {
|
|
187
|
+
await fetch(url, {
|
|
129
188
|
method: "POST",
|
|
130
189
|
headers: buildHeaders(),
|
|
131
190
|
body: JSON.stringify({
|
|
132
191
|
note: `请查看管道评论:${mergeURL}#note`,
|
|
133
192
|
line_type: "new"
|
|
134
193
|
})
|
|
135
|
-
}).then((res) => res.text());
|
|
194
|
+
}).then((res) => res.text()).then((v) => console.log(v)).catch((e) => console.error(e));
|
|
136
195
|
}
|
|
137
196
|
return !yes;
|
|
138
197
|
}
|
|
139
198
|
|
|
140
|
-
//#endregion
|
|
141
|
-
//#region copilot/server/config.ts
|
|
142
|
-
const name = "d5_mcp_review_builtin";
|
|
143
|
-
const report = "report";
|
|
144
|
-
const getHash = "hash";
|
|
145
|
-
const file = "bin/copilot.js";
|
|
146
|
-
const serveFile = join(RUNTIME_CWD, file);
|
|
147
|
-
const envJson = buildEnv();
|
|
148
|
-
const envUsed = {
|
|
149
|
-
CI_SERVER_URL: toEnv("CI_SERVER_URL"),
|
|
150
|
-
CI_PROJECT_PATH: toEnv("CI_PROJECT_PATH"),
|
|
151
|
-
CI_PROJECT_ID: toEnv("CI_PROJECT_ID"),
|
|
152
|
-
CI_PROJECT_NAME: toEnv("CI_PROJECT_NAME"),
|
|
153
|
-
CI_COMMIT_SHA: toEnv("CI_COMMIT_SHA"),
|
|
154
|
-
CI_COMMIT_BEFORE_SHA: toEnv("CI_COMMIT_BEFORE_SHA"),
|
|
155
|
-
CI_MERGE_REQUEST_IID: toEnv("CI_MERGE_REQUEST_IID"),
|
|
156
|
-
CI_MERGE_REQUEST_TITLE: toEnv("CI_MERGE_REQUEST_TITLE"),
|
|
157
|
-
CI_MERGE_REQUEST_DESCRIPTION: toEnv("CI_MERGE_REQUEST_DESCRIPTION"),
|
|
158
|
-
JIRA_BASE_URL: toEnv("JIRA_BASE_URL", "http://jira.d5techs.com.cn"),
|
|
159
|
-
DINGTALK_WEBHOOK: toEnv("DINGTALK_WEBHOOK"),
|
|
160
|
-
GITLAB_TOKEN: toEnv("GITLAB_TOKEN"),
|
|
161
|
-
JIRA_PAT: toEnv("JIRA_PAT"),
|
|
162
|
-
JIRA_COOKIE: toEnv("JIRA_COOKIE"),
|
|
163
|
-
JIRA_USERNAME: toEnv("JIRA_USERNAME"),
|
|
164
|
-
JIRA_PASSWORD: toEnv("JIRA_PASSWORD")
|
|
165
|
-
};
|
|
166
|
-
const tools = [
|
|
167
|
-
"--additional-mcp-config",
|
|
168
|
-
JSON.stringify({ mcpServers: { [name]: {
|
|
169
|
-
type: "local",
|
|
170
|
-
command: "node",
|
|
171
|
-
args: [serveFile, `--customizenv=${JSON.stringify(envUsed)}`],
|
|
172
|
-
tools: ["*"]
|
|
173
|
-
} } }),
|
|
174
|
-
"--allow-all-paths",
|
|
175
|
-
"--allow-all-tools",
|
|
176
|
-
"--deny-tool",
|
|
177
|
-
"write",
|
|
178
|
-
"--deny-tool",
|
|
179
|
-
"github-mcp-server"
|
|
180
|
-
];
|
|
181
|
-
tools.push("--model", "claude-sonnet-4.5");
|
|
182
|
-
function toEnv(key, defaultValue) {
|
|
183
|
-
return envJson[key] || process.env[key] || defaultValue;
|
|
184
|
-
}
|
|
185
|
-
function buildEnv() {
|
|
186
|
-
const envArg = argv.find((arg) => arg.startsWith("--customizenv="));
|
|
187
|
-
let envJson$1 = {};
|
|
188
|
-
if (envArg) envJson$1 = JSON.parse(envArg.replace("--customizenv=", ""));
|
|
189
|
-
return envJson$1;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
199
|
//#endregion
|
|
193
200
|
//#region copilot/bin/install.ts
|
|
194
201
|
function install() {
|
|
@@ -247,13 +254,13 @@ function logImmediate(message) {
|
|
|
247
254
|
try {
|
|
248
255
|
codereview();
|
|
249
256
|
} catch (error) {
|
|
250
|
-
|
|
257
|
+
dingding("CRITICAL", "CI ERROR: 未知错误,请自行检查日志");
|
|
251
258
|
throw error;
|
|
252
259
|
}
|
|
253
|
-
function codereview() {
|
|
254
|
-
deploy();
|
|
255
|
-
if (!need()) {
|
|
256
|
-
|
|
260
|
+
async function codereview() {
|
|
261
|
+
await deploy();
|
|
262
|
+
if (!await need()) {
|
|
263
|
+
console.log("重复提交,进程跳过");
|
|
257
264
|
return;
|
|
258
265
|
}
|
|
259
266
|
install();
|
|
@@ -280,7 +287,6 @@ Otherwise, use chinese as default language to call the mcp tool '${name}-${repor
|
|
|
280
287
|
},
|
|
281
288
|
...platform === "win32" && { windowsHide: true }
|
|
282
289
|
});
|
|
283
|
-
console.log(`node ${findCopilopt()} ${tools.join(" ")} --stream off -p ${prompt}`);
|
|
284
290
|
copilot.stdout.setEncoding("utf8");
|
|
285
291
|
copilot.stderr.setEncoding("utf8");
|
|
286
292
|
copilot.stdout.on("data", (chunk) => {
|
|
@@ -290,61 +296,41 @@ Otherwise, use chinese as default language to call the mcp tool '${name}-${repor
|
|
|
290
296
|
process.stderr.write(chunk);
|
|
291
297
|
});
|
|
292
298
|
copilot.on("close", (code) => {
|
|
293
|
-
|
|
299
|
+
if (!code) dingding("CRITICAL", "CI ERROR: 代码审查任务失败,请自行检查日志");
|
|
294
300
|
exit(code);
|
|
295
301
|
});
|
|
296
302
|
}
|
|
297
303
|
/**
|
|
298
|
-
*
|
|
299
|
-
* @returns
|
|
304
|
+
* 根据操作系统和架构获取对应的 copilot 包名
|
|
305
|
+
* @returns 平台特定的包名数组,按优先级排序
|
|
300
306
|
*/
|
|
301
|
-
function
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
arm64: "arm64"
|
|
310
|
-
};
|
|
311
|
-
const platformName = platformMap[platform];
|
|
312
|
-
const archName = archMap[arch];
|
|
313
|
-
if (platformName && archName) {
|
|
314
|
-
const specificPackage = `@github/copilot-${platformName}-${archName}`;
|
|
315
|
-
try {
|
|
316
|
-
if (execSync(`npm list ${specificPackage} -g -p`, {
|
|
317
|
-
encoding: "utf8",
|
|
318
|
-
stdio: "pipe"
|
|
319
|
-
}).trim()) {
|
|
320
|
-
logImmediate(`[调试] 使用平台特定包: ${specificPackage}`);
|
|
321
|
-
return specificPackage;
|
|
322
|
-
}
|
|
323
|
-
} catch {}
|
|
324
|
-
}
|
|
325
|
-
logImmediate(`[调试] 使用通用包: @github/copilot`);
|
|
326
|
-
return "@github/copilot";
|
|
307
|
+
function getCopilotPackageNames() {
|
|
308
|
+
const packages = [];
|
|
309
|
+
if (platform === "win32" && arch === "x64") packages.push("@github/copilot-win32-x64");
|
|
310
|
+
else if (platform === "linux" && arch === "x64") packages.push("@github/copilot-linux-x64");
|
|
311
|
+
else if (platform === "linux" && arch === "arm64") packages.push("@github/copilot-linux-arm64");
|
|
312
|
+
else if (platform === "darwin" && arch === "arm64") packages.push("@github/copilot-darwin-arm64");
|
|
313
|
+
packages.push("@github/copilot");
|
|
314
|
+
return packages;
|
|
327
315
|
}
|
|
328
316
|
function findCopilopt() {
|
|
329
|
-
const
|
|
317
|
+
const packageNames = getCopilotPackageNames();
|
|
330
318
|
let copilot = "";
|
|
331
|
-
try {
|
|
332
|
-
copilot = execSync(`npm list ${packageName} -g -p
|
|
333
|
-
|
|
334
|
-
stdio: "pipe"
|
|
335
|
-
}).trim();
|
|
319
|
+
for (const packageName of packageNames) try {
|
|
320
|
+
copilot = execSync(`npm list ${packageName} -g -p`).toString().trim();
|
|
321
|
+
if (copilot) break;
|
|
336
322
|
} catch {}
|
|
337
323
|
if (!copilot) {
|
|
338
324
|
const first = platform === "win32" ? win : linux;
|
|
339
325
|
const second = platform === "win32" ? linux : win;
|
|
340
|
-
copilot = first(
|
|
341
|
-
if (!copilot) copilot = second(
|
|
342
|
-
if (!copilot) throw new Error(
|
|
326
|
+
copilot = first();
|
|
327
|
+
if (!copilot) copilot = second();
|
|
328
|
+
if (!copilot) throw new Error("没找到安装的包");
|
|
343
329
|
}
|
|
344
330
|
const pkg = join(copilot, "package.json");
|
|
345
331
|
if (!existsSync(pkg)) throw new Error("安装的包找不到正确版本 " + pkg);
|
|
346
332
|
const copilotPackage = JSON.parse(readFileSync(pkg, "utf8"));
|
|
347
|
-
const binPath = typeof copilotPackage.bin === "string" ? copilotPackage.bin : copilotPackage.bin?.copilot || copilotPackage.bin?.["@github/copilot"]
|
|
333
|
+
const binPath = typeof copilotPackage.bin === "string" ? copilotPackage.bin : copilotPackage.bin?.copilot || copilotPackage.bin?.["@github/copilot"];
|
|
348
334
|
if (!binPath) throw new Error("non copilot executable found");
|
|
349
335
|
const copilotVersion = copilotPackage.version || "unknown";
|
|
350
336
|
const copilotPath = join(copilot, binPath);
|
|
@@ -352,19 +338,23 @@ function findCopilopt() {
|
|
|
352
338
|
version: ${VERSION}
|
|
353
339
|
path: ${serveFile}
|
|
354
340
|
copilot:
|
|
355
|
-
package: ${packageName}
|
|
356
341
|
version: ${copilotVersion}
|
|
357
342
|
path: ${copilotPath}`);
|
|
358
343
|
return copilotPath;
|
|
359
344
|
}
|
|
360
|
-
function win(
|
|
345
|
+
function win() {
|
|
361
346
|
const pathEnv = env.PATH || env.Path || "";
|
|
362
347
|
const pathSeparator = platform === "win32" ? ";" : ":";
|
|
363
348
|
const npm = pathEnv.split(pathSeparator).find((p) => p.includes("npm"));
|
|
364
|
-
if (npm) return
|
|
349
|
+
if (!npm) return "";
|
|
350
|
+
const packageNames = getCopilotPackageNames();
|
|
351
|
+
for (const packageName of packageNames) {
|
|
352
|
+
const packagePath = join(npm, "node_modules", ...packageName.split("/"));
|
|
353
|
+
if (existsSync(join(packagePath, "package.json"))) return packagePath;
|
|
354
|
+
}
|
|
365
355
|
return "";
|
|
366
356
|
}
|
|
367
|
-
function linux(
|
|
357
|
+
function linux() {
|
|
368
358
|
let cached = env.NVM_BIN;
|
|
369
359
|
if (!cached) {
|
|
370
360
|
const pathEnv = env.PATH || env.Path || "";
|
|
@@ -372,9 +362,11 @@ function linux(packageName = "@github/copilot") {
|
|
|
372
362
|
const npm = pathEnv.split(pathSeparator).find((p) => p.includes(".nvm"));
|
|
373
363
|
if (npm) cached = npm;
|
|
374
364
|
}
|
|
375
|
-
if (cached)
|
|
376
|
-
|
|
377
|
-
|
|
365
|
+
if (!cached) return "";
|
|
366
|
+
const packageNames = getCopilotPackageNames();
|
|
367
|
+
for (const packageName of packageNames) {
|
|
368
|
+
const packagePath = join(cached, "..", "lib", "node_modules", ...packageName.split("/"));
|
|
369
|
+
if (existsSync(join(packagePath, "package.json"))) return packagePath;
|
|
378
370
|
}
|
|
379
371
|
return "";
|
|
380
372
|
}
|