This commit is contained in:
Alexandre
2025-08-28 09:09:53 +02:00
committed by GitHub
parent e11a7dcefb
commit 4986512576

View File

@@ -1,205 +0,0 @@
name: AI triage (comment + optional PR)
on:
# issues:
# types: [opened]
issue_comment:
types: [created]
permissions:
contents: write
pull-requests: write
issues: write
jobs:
ai_first_reply:
runs-on: ubuntu-latest
# Run when: issue opened OR a '/codex' comment on an issue (not PR)
if: >
(github.event_name == 'issues' ||
(github.event_name == 'issue_comment' &&
github.event.action == 'created' &&
github.event.comment.body == '/codex' &&
github.event.issue.pull_request == null))
&& contains(github.event.issue.labels.*.name, 'bug')
steps:
- name: Compose and post AI reply
uses: actions/github-script@v7
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
with:
script: |
const issue = context.payload.issue;
const { owner, repo } = context.repo;
// Optional repo context
let readmeText = '';
try {
const readme = await github.rest.repos.getReadme({ owner, repo });
readmeText = Buffer.from(readme.data.content, 'base64').toString('utf8');
if (readmeText.length > 18000) readmeText = readmeText.slice(0, 18000) + "\n...[truncated]...";
} catch {}
const system = `
You are an open-source triage assistant.
Write a concise, actionable first reply for a new bug report.
Focus on diagnosing the problem and suggesting potential fixes.
Minimize follow-up questions and avoid inventing repo facts.
Propose next steps and link to repo files only when certain.
`.trim();
const user = `
Repository: ${owner}/${repo}
Issue #${issue.number}: ${issue.title}
Issue body:
${issue.body || '(no body provided)'}
README excerpt:
${readmeText || '(none)'}
`.trim();
const res = await fetch('https://api.openai.com/v1/responses', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
},
body: JSON.stringify({
model: 'gpt-4o-mini',
input: [
{ role: 'system', content: system },
{ role: 'user', content: user }
],
}),
});
if (!res.ok) {
const txt = await res.text();
await github.rest.issues.createComment({
owner, repo, issue_number: issue.number,
body: `⚠️ AI reply failed (${res.status}).\n\n\`\`\`\n${txt}\n\`\`\``
});
return;
}
const data = await res.json();
const text = data.output_text
|| data.output?.map(p => p.content?.map(c => c.text ?? '').join('')).join('\n')
|| data?.choices?.[0]?.message?.content
|| 'Thanks for opening this issue — we will take a look!';
await github.rest.issues.createComment({
owner, repo, issue_number: issue.number, body: text
});
ai_autofix_pr:
runs-on: ubuntu-latest
needs: ai_first_reply
# Same trigger conditions as above AND issue has label 'auto-pr'
if: >
(github.event_name == 'issues' ||
(github.event_name == 'issue_comment' &&
github.event.action == 'created' &&
github.event.comment.body == '/codex' &&
github.event.issue.pull_request == null))
&& contains(github.event.issue.labels.*.name, 'auto-pr')
&& contains(github.event.issue.labels.*.name, 'bug')
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Generate patch with OpenAI (unified diff)
id: genpatch
uses: actions/github-script@v7
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
with:
result-encoding: string
script: |
const { owner, repo } = context.repo;
const issue = context.payload.issue;
let readmeText = '';
try {
const readme = await github.rest.repos.getReadme({ owner, repo });
readmeText = Buffer.from(readme.data.content, 'base64').toString('utf8');
if (readmeText.length > 12000) readmeText = readmeText.slice(0, 12000) + "\n...[truncated]...";
} catch {}
const system = `
You are a code-change generator.
Output ONLY a git unified diff (git apply compatible). No prose, no backticks.
Keep changes minimal and safe; if unsure, output an empty diff.
`.trim();
const user = `
Repo: ${owner}/${repo}
Issue #${issue.number}: ${issue.title}
Issue body:
${issue.body || '(no body)'}
README excerpt:
${readmeText || '(none)'}
`.trim();
const res = await fetch('https://api.openai.com/v1/responses', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
},
body: JSON.stringify({
model: 'gpt-4o-mini',
input: [
{ role: 'system', content: system },
{ role: 'user', content: user }
],
}),
});
if (!res.ok) {
const txt = await res.text();
core.setFailed(`OpenAI error ${res.status}: ${txt}`);
} else {
const data = await res.json();
const patch = (
data.output_text
|| data.output?.map(p => p.content?.map(c => c.text ?? '').join('')).join('\n')
|| data?.choices?.[0]?.message?.content
|| ''
).trim();
return patch;
}
- name: Apply patch (if any)
id: apply
shell: bash
run: |
set -euo pipefail
patch="${{ steps.genpatch.outputs.result }}"
if [ -z "$patch" ]; then
echo "No patch produced; skipping PR."
echo "skip_pr=true" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "$patch" > ai.patch
git apply --whitespace=fix ai.patch
echo "skip_pr=false" >> "$GITHUB_OUTPUT"
- name: Create Pull Request
if: steps.apply.outputs.skip_pr == 'false'
uses: peter-evans/create-pull-request@v7
with:
branch: ai/autofix-${{ github.event.issue.number }}
title: AI autofix for #${{ github.event.issue.number }}
commit-message: AI autofix for #${{ github.event.issue.number }}
body: |
This PR was generated automatically from issue #${{ github.event.issue.number }}.
Label `auto-pr` triggered patch creation. Please review carefully.
labels: auto-pr, ai-generated
delete-branch: true