Skip to content

fix: AI PR 리뷰 워크플로우 완전 수정 #4

fix: AI PR 리뷰 워크플로우 완전 수정

fix: AI PR 리뷰 워크플로우 완전 수정 #4

Workflow file for this run

name: AI PR Review
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
ai-review:
runs-on: ubuntu-latest
if: github.actor != 'dependabot[bot]'
permissions:
contents: read
pull-requests: write
issues: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: AI Code Review
uses: actions/github-script@v7
with:
script: |
const OPENROUTER_API_KEY = '${{ secrets.OPENROUTER_API_KEY }}';
const diff = await github.rest.repos.compareCommits({
owner: context.repo.owner,
repo: context.repo.repo,
base: context.payload.pull_request.base.sha,
head: context.payload.pull_request.head.sha
});
const filesToReview = diff.data.files.filter(file =>
file.patch &&
!file.filename.includes('test/') &&
!file.filename.includes('build/') &&
(file.filename.endsWith('.kt') ||
file.filename.endsWith('.kts') ||
file.filename.endsWith('.java') ||
file.filename.endsWith('.yml') ||
file.filename.endsWith('.yaml') ||
file.filename.endsWith('.md'))
);
if (filesToReview.length === 0) {
console.log('No files to review');
return;
}
console.log(`Found ${filesToReview.length} files to review`);
let overallReview = `## 🤖 AI 코드 리뷰\n\n`;
let allChanges = '';
const filesSummary = [];
for (const file of filesToReview) {
filesSummary.push(`- ${file.filename} (+${file.additions}/-${file.deletions})`);
allChanges += `\n### ${file.filename}\n`;
allChanges += `\`\`\`diff\n${file.patch}\n\`\`\`\n`;
}
try {
const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${OPENROUTER_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'x-ai/grok-4-fast:free',
messages: [{
role: 'system',
content: `코드 리뷰어입니다. 다음 규칙만 검토하세요:
## 검토 항목
1. **글로벌 익셉션 처리**: @ControllerAdvice 사용, 표준 에러 응답

Check failure on line 79 in .github/workflows/ai-pr-review.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/ai-pr-review.yml

Invalid workflow file

You have an error in your yaml syntax on line 79
2. **ApiResponse 사용**: 모든 API는 ApiResponse<T>로 감싸서 응답
3. **Kotlin 최적화**: data class, null safety, when 표현식, 확장함수 등
4. **ktlint 규칙**: 포맷팅, 네이밍 컨벤션
## 응답 형식
### ✅ 준수사항
- [잘 지켜진 부분]
### ❌ 위반사항
- [파일:라인] 문제점과 수정방법
**점수**: X/10`
}, {
role: 'user',
content: `다음 PR의 변경사항을 리뷰해주세요:
PR 제목: ${{ github.event.pull_request.title }}
PR 설명: ${{ github.event.pull_request.body }}
변경된 파일:
${filesSummary.join('\n')}
전체 변경사항:
${allChanges}`
}],
temperature: 0.3
})
});
if (response.ok) {
const result = await response.json();
overallReview += result.choices[0].message.content + '\n\n';
console.log('✅ API review completed successfully!');
} else {
const errorText = await response.text();
console.error('API request failed:', response.status, errorText);
overallReview += `> ⚠️ 리뷰 실패: ${response.status} - ${errorText}\n\n`;
}
} catch (error) {
console.error('Error during review:', error);
overallReview += `> ⚠️ 리뷰 실패: ${error.message}\n\n`;
}
overallReview += `---\n`;
overallReview += `<details>\n<summary>💡 리뷰 정보</summary>\n\n`;
overallReview += `- 모델: Grok-4-fast\n`;
overallReview += `- 리뷰 시간: ${new Date().toLocaleString('ko-KR', {timeZone: 'Asia/Seoul'})}\n`;
overallReview += `- PR: #${{ github.event.number }}\n\n`;
overallReview += `</details>`;
await github.rest.pulls.createReview({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
body: overallReview,
event: 'COMMENT'
});
console.log(`✅ Review completed for ${filesToReview.length} files!`);