@dev-angsu/cli 1.0.0 → 1.0.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/bin/index.js +1 -1
- package/package.json +9 -3
- package/src/utils/engine.js +142 -0
package/bin/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dev-angsu/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
8
|
},
|
|
9
9
|
"bin": {
|
|
10
|
-
"
|
|
10
|
+
"dev-angsu": "./bin/index.js",
|
|
11
|
+
"review-code": "./src/utils/engine.js"
|
|
11
12
|
},
|
|
12
13
|
"keywords": [],
|
|
13
14
|
"author": "",
|
|
14
15
|
"license": "ISC",
|
|
15
16
|
"type": "module",
|
|
16
17
|
"dependencies": {
|
|
18
|
+
"@actions/core": "^2.0.1",
|
|
19
|
+
"@actions/github": "^6.0.1",
|
|
17
20
|
"chalk": "^5.6.2",
|
|
18
21
|
"commander": "^14.0.2",
|
|
22
|
+
"dotenv": "^17.2.3",
|
|
19
23
|
"inquirer": "^13.1.0",
|
|
20
|
-
"
|
|
24
|
+
"openai": "^6.15.0",
|
|
25
|
+
"ora": "^9.0.0",
|
|
26
|
+
"simple-git": "^3.30.0"
|
|
21
27
|
},
|
|
22
28
|
"files": [
|
|
23
29
|
"bin",
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { simpleGit } from "simple-git";
|
|
4
|
+
import OpenAI from "openai";
|
|
5
|
+
import "dotenv/config"; // Loads .env file automatically
|
|
6
|
+
|
|
7
|
+
import * as core from "@actions/core";
|
|
8
|
+
import * as github from "@actions/github";
|
|
9
|
+
|
|
10
|
+
const git = simpleGit();
|
|
11
|
+
|
|
12
|
+
if (!process.env.OPENAI_API_KEY) {
|
|
13
|
+
console.error("❌ Error: OPENAI_API_KEY is missing in .env file.");
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const openai = new OpenAI({
|
|
18
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
19
|
+
baseURL: process.env.AI_BASE_URL || "https://api.z.ai/api/paas/v4/",
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// async function getStagedDiff() {
|
|
23
|
+
// const diff = await git.diff(["--staged"]);
|
|
24
|
+
// return diff;
|
|
25
|
+
// }
|
|
26
|
+
// STRATEGY 1: Local Development
|
|
27
|
+
async function getLocalDiff() {
|
|
28
|
+
console.log("💻 Running in Local Mode...");
|
|
29
|
+
const git = simpleGit();
|
|
30
|
+
const diff = await git.diff(["--staged"]);
|
|
31
|
+
return diff;
|
|
32
|
+
}
|
|
33
|
+
// STRATEGY 2: GitHub Actions (CI/CD)
|
|
34
|
+
async function getPRDiff() {
|
|
35
|
+
console.log("☁️ Running in GitHub Actions Mode...");
|
|
36
|
+
|
|
37
|
+
// The 'GITHUB_TOKEN' is automatically provided by the workflow
|
|
38
|
+
const token = process.env.GITHUB_TOKEN;
|
|
39
|
+
const octokit = github.getOctokit(token);
|
|
40
|
+
|
|
41
|
+
const context = github.context;
|
|
42
|
+
const prNumber = context.payload.pull_request?.number;
|
|
43
|
+
|
|
44
|
+
if (!prNumber) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
"❌ No Pull Request found in context. Are you running this on push?"
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Fetch the diff specifically
|
|
51
|
+
const { data: diff } = await octokit.rest.pulls.get({
|
|
52
|
+
owner: context.repo.owner,
|
|
53
|
+
repo: context.repo.repo,
|
|
54
|
+
pull_number: prNumber,
|
|
55
|
+
mediaType: {
|
|
56
|
+
format: "diff", // Ask GitHub to return the raw diff text
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return diff;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function generateReview(diff) {
|
|
64
|
+
// 1. Token Safety: Truncate if too huge (basic safety mechanism)
|
|
65
|
+
const MAX_CHARS = 15000;
|
|
66
|
+
const processedDiff =
|
|
67
|
+
diff.length > MAX_CHARS
|
|
68
|
+
? diff.substring(0, MAX_CHARS) + "\n...[Diff Truncated due to size]..."
|
|
69
|
+
: diff;
|
|
70
|
+
|
|
71
|
+
console.log("🤔 Analyzing changes...");
|
|
72
|
+
|
|
73
|
+
const response = await openai.chat.completions.create({
|
|
74
|
+
model: process.env.AI_MODEL || "glm-4.6v-flash",
|
|
75
|
+
messages: [
|
|
76
|
+
{
|
|
77
|
+
role: "system",
|
|
78
|
+
content: `You are a Senior Software Engineer doing a Code Review.
|
|
79
|
+
|
|
80
|
+
Rules:
|
|
81
|
+
1. Summarize the changes in 1 sentence.
|
|
82
|
+
2. Identify any critical bugs or security risks (SQL injection, hardcoded secrets).
|
|
83
|
+
3. Suggest code style improvements (focus on readability).
|
|
84
|
+
4. Generate a concise, conventional commit message for these changes.
|
|
85
|
+
5. If the code looks good, output "LGTM" (Looks Good To Me) with a thumbs up.
|
|
86
|
+
|
|
87
|
+
Format your response in nice Markdown.`,
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
role: "user",
|
|
91
|
+
content: `Here is the git diff of the changes:\n\n${processedDiff}`,
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
return response.choices[0].message.content;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Main Execution
|
|
100
|
+
async function run() {
|
|
101
|
+
try {
|
|
102
|
+
// const diff = await getStagedDiff();
|
|
103
|
+
// 1. SELECT STRATEGY
|
|
104
|
+
let diff;
|
|
105
|
+
if (process.env.CI) {
|
|
106
|
+
diff = await getPRDiff();
|
|
107
|
+
} else {
|
|
108
|
+
diff = await getLocalDiff();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (!diff) {
|
|
112
|
+
console.log("⚠️ No staged changes found. Did you run 'git add'?");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const review = await generateReview(diff);
|
|
117
|
+
if (process.env.CI) {
|
|
118
|
+
// In CI, we post a comment back to the PR
|
|
119
|
+
const token = process.env.GITHUB_TOKEN;
|
|
120
|
+
const octokit = github.getOctokit(token);
|
|
121
|
+
const context = github.context;
|
|
122
|
+
|
|
123
|
+
await octokit.rest.issues.createComment({
|
|
124
|
+
owner: context.repo.owner,
|
|
125
|
+
repo: context.repo.repo,
|
|
126
|
+
issue_number: context.payload.pull_request.number,
|
|
127
|
+
body: review,
|
|
128
|
+
});
|
|
129
|
+
console.log("✅ Review posted to GitHub PR!");
|
|
130
|
+
} else {
|
|
131
|
+
// Locally, we just print it
|
|
132
|
+
console.log("\n================ 🤖 AI CODE REVIEW ================ \n");
|
|
133
|
+
console.log(review);
|
|
134
|
+
console.log("\n=================================================== \n");
|
|
135
|
+
}
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.error("Error:", error.message);
|
|
138
|
+
if (process.env.CI) core.setFailed(error.message); // Fail the pipeline
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
run();
|