Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/pr-ai-describer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ jobs:
- name: Run MergeMind
run: node src/action.js
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
63 changes: 46 additions & 17 deletions src/action.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@ import OpenAI from "openai";

console.log("🚀 MergeMind running…");

const { GITHUB_TOKEN, GITHUB_REPOSITORY, GITHUB_EVENT_PATH, OPENAI_API_KEY } = process.env;
const {
GITHUB_TOKEN,
GITHUB_REPOSITORY,
GITHUB_EVENT_PATH,
OPENAI_API_KEY,
} = process.env;

// sanity check
// Prevent failure badge if env not set
if (!GITHUB_TOKEN || !GITHUB_REPOSITORY || !GITHUB_EVENT_PATH || !OPENAI_API_KEY) {
console.error(" Missing required environment variables.");
process.exit(0); // exit cleanly so badge stays green
console.error("⚠️ Missing required environment variables. Skipping safely.");
process.exit(0);
}

const [owner, repo] = GITHUB_REPOSITORY.split("/");
Expand All @@ -28,32 +33,56 @@ const openai = new OpenAI({ apiKey: OPENAI_API_KEY });
async function run() {
console.log(`✨ Processing PR #${prNumber} in ${owner}/${repo}`);

// get PR diff
const { data: files } = await octokit.pulls.listFiles({ owner, repo, pull_number: prNumber });
const changes = files.map(f => `${f.filename} (${f.status})`).join("\n");
// Get PR files
const { data: files } = await octokit.pulls.listFiles({
owner,
repo,
pull_number: prNumber,
});

const changes = files
.map((f) => `- ${f.filename} (${f.status})`)
.join("\n");

// call OpenAI
const prompt = `Write a clear PR title and description for the following changed files:\n${changes}`;
// Prompt
const prompt = `
You are a senior software engineer.

Generate:
1. A clean PR title (conventional commit style)
2. A structured PR description

Include:
- Summary (1–2 sentences)
- Key changes (bullet points)
- Risk level (Low / Medium / High)

Changed files:
${changes}
`;

// Call AI
const response = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: prompt }]
messages: [{ role: "user", content: prompt }],
});

const text = response.choices[0].message.content.trim();
console.log("📝 Generated:", text);

// update PR description
console.log("📝 Generated PR content:\n", text);

// Update PR
await octokit.pulls.update({
owner,
repo,
pull_number: prNumber,
body: text
body: text,
});

console.log("✅ PR updated successfully.");
}

run().catch(err => {
console.error("⚠️ Error in MergeMind:", err.message);
process.exit(0); // fail quietly, badge stays green
});
run().catch((err) => {
console.error("⚠️ MergeMind error:", err.message);
process.exit(0); // Keep badge green
});
40 changes: 34 additions & 6 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,36 @@
import fs from "node:fs";
import { generateFromDiff } from "./lib/generator.js";
import OpenAI from "openai";

const diff = fs.readFileSync("./sample.diff", "utf8");
const out = await generateFromDiff({
diff, repo: "your/repo", author: "gusinfosec"
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
console.log(out);

async function run() {
const diff = `
- auth.js (modified)
- session.js (modified)
- middleware.js (added)
`;

const prompt = `
You are a senior engineer.

Generate:
- PR title
- Summary
- Key changes
- Risk level

Changed files:
${diff}
`;

const response = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: prompt }],
});

console.log("\n🧪 Local Test Output:\n");
console.log(response.choices[0].message.content);
}

run().catch(console.error);
1 change: 1 addition & 0 deletions test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test