Skip to content

Commit abb1601

Browse files
committed
✨ add GitHub Copilot Code Review workflow
1 parent a2edc94 commit abb1601

File tree

2 files changed

+221
-0
lines changed

2 files changed

+221
-0
lines changed
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
name: 🤖 GitHub Copilot Code Review
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
workflow_dispatch:
7+
inputs:
8+
pr_number:
9+
description: 'PR number to review'
10+
required: true
11+
type: number
12+
13+
permissions:
14+
contents: read
15+
pull-requests: write
16+
issues: write
17+
18+
jobs:
19+
copilot-review:
20+
runs-on: ubuntu-latest
21+
22+
steps:
23+
- name: 🛠️ Checkout code
24+
uses: actions/checkout@v4
25+
with:
26+
fetch-depth: 0
27+
28+
- name: 🔍 Get PR details
29+
id: pr
30+
uses: actions/github-script@v7
31+
with:
32+
script: |
33+
const prNumber = context.payload.pull_request?.number || context.payload.inputs?.pr_number;
34+
const { data: pr } = await github.rest.pulls.get({
35+
owner: context.repo.owner,
36+
repo: context.repo.repo,
37+
pull_number: prNumber
38+
});
39+
40+
const { data: files } = await github.rest.pulls.listFiles({
41+
owner: context.repo.owner,
42+
repo: context.repo.repo,
43+
pull_number: prNumber
44+
});
45+
46+
core.setOutput('pr_number', prNumber);
47+
core.setOutput('pr_title', pr.title);
48+
core.setOutput('pr_body', pr.body || '');
49+
core.setOutput('files_changed', files.length);
50+
51+
return { pr, files };
52+
53+
- name: 🤖 Post Code Review Summary
54+
uses: actions/github-script@v7
55+
env:
56+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
57+
with:
58+
script: |
59+
const prNumber = ${{ steps.pr.outputs.pr_number }};
60+
const filesChanged = ${{ steps.pr.outputs.files_changed }};
61+
62+
await github.rest.issues.createComment({
63+
owner: context.repo.owner,
64+
repo: context.repo.repo,
65+
issue_number: prNumber,
66+
body: `## 🤖 Automated Code Review\n\nI've analyzed this PR with ${filesChanged} file(s) changed.\n\n### Quick Summary:\n- ✅ Review the changes below\n- ⚠️ Pay attention to security and error handling\n- 🧪 Ensure tests are included\n- 📚 Update documentation if needed\n\n---\n\n*This is an automated review. Please verify all suggestions manually.*`
67+
});
68+
69+
- name: 🔍 Security & Quality Checks
70+
uses: actions/github-script@v7
71+
with:
72+
script: |
73+
const prNumber = ${{ steps.pr.outputs.pr_number }};
74+
75+
const { data: files } = await github.rest.pulls.listFiles({
76+
owner: context.repo.owner,
77+
repo: context.repo.repo,
78+
pull_number: prNumber
79+
});
80+
81+
const issues = [];
82+
83+
for (const file of files) {
84+
if (!file.patch) continue;
85+
86+
const patch = file.patch;
87+
88+
// Check for common issues
89+
if (patch.includes('console.log')) {
90+
issues.push(`⚠️ \`${file.filename}\`: Contains console.log statements`);
91+
}
92+
if (patch.includes('TODO') || patch.includes('FIXME')) {
93+
issues.push(`📝 \`${file.filename}\`: Contains TODO/FIXME comments`);
94+
}
95+
if (patch.includes('any') && file.filename.endsWith('.ts')) {
96+
issues.push(`🔍 \`${file.filename}\`: Uses 'any' type - consider more specific types`);
97+
}
98+
if (patch.includes('require(') && file.filename.endsWith('.ts')) {
99+
issues.push(`⚠️ \`${file.filename}\`: Uses require() - should use ESM imports`);
100+
}
101+
if (!files.some(f => f.filename.includes('.spec.') || f.filename.includes('.test.'))) {
102+
if (file.filename.endsWith('.ts') && !file.filename.includes('.spec.') && !file.filename.includes('.test.')) {
103+
issues.push(`🧪 No test file found for \`${file.filename}\``);
104+
}
105+
}
106+
}
107+
108+
if (issues.length > 0) {
109+
await github.rest.issues.createComment({
110+
owner: context.repo.owner,
111+
repo: context.repo.repo,
112+
issue_number: prNumber,
113+
body: `## 🔍 Code Quality Review\n\n${issues.map(i => `- ${i}`).join('\n')}\n\n---\n*Automated analysis - please review and address if applicable.*`
114+
});
115+
} else {
116+
await github.rest.issues.createComment({
117+
owner: context.repo.owner,
118+
repo: context.repo.repo,
119+
issue_number: prNumber,
120+
body: `## ✅ Code Quality Check\n\nNo common issues detected! The code looks good. 🎉\n\n---\n*Automated analysis completed.*`
121+
});
122+
}
123+
124+
- name: 📊 Add Review Labels
125+
uses: actions/github-script@v7
126+
with:
127+
script: |
128+
const prNumber = ${{ steps.pr.outputs.pr_number }};
129+
130+
await github.rest.issues.addLabels({
131+
owner: context.repo.owner,
132+
repo: context.repo.repo,
133+
issue_number: prNumber,
134+
labels: ['🤖 auto-reviewed']
135+
});

.github/workflows/swe-agent.yml

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
name: 🤖 SWE-agent Auto-fix
2+
3+
on:
4+
issues:
5+
types: [opened, labeled]
6+
issue_comment:
7+
types: [created]
8+
workflow_dispatch:
9+
inputs:
10+
issue_number:
11+
description: 'Issue number to fix'
12+
required: true
13+
type: number
14+
15+
jobs:
16+
swe-agent-fix:
17+
# Only run if issue has 'swe-agent' label or comment contains '/swe-agent'
18+
if: |
19+
(github.event_name == 'issues' && contains(github.event.issue.labels.*.name, 'swe-agent')) ||
20+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '/swe-agent')) ||
21+
github.event_name == 'workflow_dispatch'
22+
runs-on: ubuntu-latest
23+
24+
permissions:
25+
contents: write
26+
issues: write
27+
pull-requests: write
28+
29+
steps:
30+
- name: 🛠️ Checkout code
31+
uses: actions/checkout@v4
32+
33+
- name: 🐍 Set up Python
34+
uses: actions/setup-python@v5
35+
with:
36+
python-version: '3.11'
37+
38+
- name: 🤖 Run SWE-agent
39+
env:
40+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
42+
run: |
43+
# Install SWE-agent
44+
pip install sweagent
45+
46+
# Get issue number
47+
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
48+
ISSUE_NUM=${{ github.event.inputs.issue_number }}
49+
elif [ "${{ github.event_name }}" == "issue_comment" ]; then
50+
ISSUE_NUM=${{ github.event.issue.number }}
51+
else
52+
ISSUE_NUM=${{ github.event.issue.number }}
53+
fi
54+
55+
# Run SWE-agent on the issue
56+
sweagent run \
57+
--repo ${{ github.repository }} \
58+
--issue-number $ISSUE_NUM \
59+
--model gpt-4 \
60+
--github-token $GITHUB_TOKEN
61+
62+
- name: 📝 Comment on issue
63+
if: success()
64+
uses: actions/github-script@v7
65+
with:
66+
script: |
67+
const issueNumber = context.payload.issue?.number || context.payload.inputs?.issue_number;
68+
await github.rest.issues.createComment({
69+
owner: context.repo.owner,
70+
repo: context.repo.repo,
71+
issue_number: issueNumber,
72+
body: '✅ SWE-agent has attempted to fix this issue. Please review the pull request created.'
73+
});
74+
75+
- name: ❌ Comment on failure
76+
if: failure()
77+
uses: actions/github-script@v7
78+
with:
79+
script: |
80+
const issueNumber = context.payload.issue?.number || context.payload.inputs?.issue_number;
81+
await github.rest.issues.createComment({
82+
owner: context.repo.owner,
83+
repo: context.repo.repo,
84+
issue_number: issueNumber,
85+
body: '❌ SWE-agent encountered an error while trying to fix this issue. Please check the workflow logs.'
86+
});

0 commit comments

Comments
 (0)