Skip to content

Update

Update #104

Workflow file for this run

name: AI Commit Comment
on:
push:
branches:
- "dev/*"
jobs:
ai-comment:
name: Review & Comment on HEAD Commit
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/heads/dev/')
continue-on-error: true
steps:
- name: Checkout full history
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js with AI tools
uses: ./.github/actions/setup-node-ai
with:
checkout: 'false' # Skip checkout since we already did it
fetch-depth: 0
- name: Comment on HEAD commit via ChatGPT
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}
HEAD_SHA: ${{ github.event.head_commit.id }}
OPENAI_MODEL: ${{ secrets.OPENAI_MODEL || 'gpt-4o-mini' }}
run: |
cat > review-commit.mjs << 'EOF'
import { OpenAI } from "openai";
import { Octokit } from "@octokit/rest";
import { execSync } from "child_process";
const ai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/");
const sha = process.env.HEAD_SHA;
// Try different diff strategies for different commit types
let diff = "";
try {
// First, try to get the diff for a single commit
diff = execSync(`git diff ${sha}^!`, { encoding: "utf-8" });
// If diff is empty, try merge commit diff (for PR merges)
if (!diff.trim()) {
console.log("Single commit diff empty, trying merge commit diff...");
diff = execSync(`git diff ${sha}^1 ${sha}`, { encoding: "utf-8" });
}
// If still empty, try comparing with HEAD~1
if (!diff.trim()) {
console.log("Merge diff empty, trying HEAD~1 comparison...");
diff = execSync(`git diff HEAD~1 HEAD`, { encoding: "utf-8" });
}
// If still empty, get the commit message and changed files
if (!diff.trim()) {
console.log("All diffs empty, getting commit info...");
const commitMsg = execSync(`git log -1 --pretty=format:"%s"`, { encoding: "utf-8" });
const changedFiles = execSync(`git diff-tree --no-commit-id --name-only -r ${sha}`, { encoding: "utf-8" });
diff = `Commit: ${commitMsg}\n\nChanged files:\n${changedFiles}`;
}
} catch (error) {
console.error("Error getting diff:", error);
diff = `Error getting diff for commit ${sha}`;
}
console.log("Diff for", sha, ":\n", diff);
try {
const res = await ai.chat.completions.create({
model: process.env.OPENAI_MODEL,
messages: [
{ role: "system", content: "You are a concise code diff explainer." },
{ role: "user", content: `Review this git diff and give me a short but technically accurate summary:\n\n${diff}` }
]
});
const comment = res.choices.map(c => c.message.content).join("\n\n---\n\n");
console.log("AI summary:\n", comment);
// Only post comment if we have actual content and it's not a generic "provide diff" response
if (comment && !comment.toLowerCase().includes("please provide") && !comment.toLowerCase().includes("i need")) {
await octokit.repos.createCommitComment({
owner,
repo,
commit_sha: sha,
body: comment,
});
console.log("Posted comment to", sha);
} else {
console.log("Skipping comment - no meaningful diff found");
}
} catch (err) {
console.error("Failed to review or comment:", err);
}
EOF
node review-commit.mjs