Skip to content

Update git fetch command to use --prune flag in PR review workflows #4

Update git fetch command to use --prune flag in PR review workflows

Update git fetch command to use --prune flag in PR review workflows #4

name: Ampcode PR Review
on:
pull_request:
types: [opened, ready_for_review, synchronize]
branches: [main, staging]
issue_comment:
types: [created]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
pull-requests: write
issues: write
jobs:
ampcode-review:
if: github.event_name == 'pull_request' && github.event.pull_request.draft == false
timeout-minutes: 15
runs-on: ${{ vars.RUNNER_IMAGE || 'ubuntu-latest' }}
strategy:
matrix:
review-chunk: [1]
max-parallel: 3
steps:
- name: Set PR context
id: pr-context
run: |
echo "pr_number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
echo "pr_sha=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT
echo "pr_base_ref=${{ github.event.pull_request.base.ref }}" >> $GITHUB_OUTPUT
echo "trigger_type=automatic" >> $GITHUB_OUTPUT
- name: Checkout PR branch
uses: actions/checkout@v4
with:
ref: ${{ steps.pr-context.outputs.pr_sha }}
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install Ampcode CLI
run: |
npm install -g @sourcegraph/amp
amp --version
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Install project dependencies
run: pnpm install --frozen-lockfile
- name: Get changed files
id: changed-files
run: |
git fetch origin --prune
CHANGED_FILES=$(git diff --name-only origin/${{ steps.pr-context.outputs.pr_base_ref }}..HEAD | grep -E '\.(ts|tsx|js|jsx|py|go|java|cpp|c|h|hpp|rs|rb|php|cs|swift|kt|scala|clj|hs|ml|fs|elm|dart|lua|r|sql|sh|bash|zsh|fish|ps1|bat|cmd|yaml|yml|json|toml|ini|cfg|conf|xml|html|css|scss|sass|less|styl|vue|svelte|astro|md|mdx|tex|latex|bib|org|rst|adoc|asciidoc|wiki|txt)$' | head -50 || echo "")
echo "changed_files<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGED_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
echo "Changed files count: $(echo "$CHANGED_FILES" | wc -l)"
- name: Add Review Started Reaction
if: steps.changed-files.outputs.changed_files != ''
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" \
-d '{"content":"eyes"}' \
"https://api.github.com/repos/${{ github.repository }}/issues/${{ steps.pr-context.outputs.pr_number }}/reactions"
echo "Added 👀 reaction to indicate review has started"
- name: Run Ampcode Review
if: steps.changed-files.outputs.changed_files != ''
env:
AMP_API_KEY: ${{ secrets.AMPCODE_API_KEY }}
run: |
echo "Running ampcode review on changed files..."
echo "${{ steps.changed-files.outputs.changed_files }}" > changed_files.txt
REVIEW_OUTPUT=$(amp -x "Review the following files for code quality, potential bugs, security issues, performance concerns, and best practices. For each issue found, provide the specific file path and line number where the issue occurs. Format your response as: FILE:line_number:issue_description. Focus on providing specific, actionable feedback with exact line numbers. Files to review: $(cat changed_files.txt | tr '\n' ' ')" 2>&1 || echo "Ampcode review failed")
echo "$REVIEW_OUTPUT" > ampcode_review.txt
echo "=== Ampcode Review Output ==="
cat ampcode_review.txt
echo "=== End Review Output ==="
- name: Parse and Post Comments with Python
if: steps.changed-files.outputs.changed_files != ''
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMMIT_SHA: ${{ steps.pr-context.outputs.pr_sha }}
run: |
if [ ! -f ampcode_review.txt ] || [ ! -s ampcode_review.txt ]; then
echo "No review output found or file is empty"
exit 0
fi
REVIEW_CONTENT=$(cat ampcode_review.txt)
# Extract line-specific comments in format FILE:line_number:issue_description
echo "$REVIEW_CONTENT" | grep -E '^[[:space:]-]*[^[:space:]]+\.[a-zA-Z0-9]+[[:space:]]*[: ]+[Ll]?[iI]?[nN]?[eE]?[[:space:]]*[0-9]+' > line_comments.txt || true
if [ ! -s line_comments.txt ]; then
echo "No line-specific comments found, creating multiple smaller comments"
# Split the review content into smaller chunks and create multiple comments
echo "$REVIEW_CONTENT" | awk '
BEGIN {
chunk_size = 1000
chunk_count = 0
current_chunk = ""
line_count = 0
}
{
if (length(current_chunk) + length($0) > chunk_size && current_chunk != "") {
chunk_count++
print "=== CHUNK " chunk_count " ===" > "chunk_" chunk_count ".txt"
print current_chunk > "chunk_" chunk_count ".txt"
current_chunk = $0
line_count = 1
} else {
if (current_chunk != "") current_chunk = current_chunk "\n"
current_chunk = current_chunk $0
line_count++
}
}
END {
if (current_chunk != "") {
chunk_count++
print "=== CHUNK " chunk_count " ===" > "chunk_" chunk_count ".txt"
print current_chunk > "chunk_" chunk_count ".txt"
}
print chunk_count > "total_chunks.txt"
}'
TOTAL_CHUNKS=$(cat total_chunks.txt 2>/dev/null || echo "0")
if [ "$TOTAL_CHUNKS" -gt 0 ]; then
echo "Creating $TOTAL_CHUNKS smaller review comments..."
for i in $(seq 1 $TOTAL_CHUNKS); do
if [ -f "chunk_$i.txt" ]; then
CHUNK_CONTENT=$(cat "chunk_$i.txt")
jq -n \
--arg content "$CHUNK_CONTENT" \
--arg run_id "${{ github.run_id }}" \
--arg repo "${{ github.repository }}" \
--arg chunk_num "$i" \
--arg total_chunks "$TOTAL_CHUNKS" \
'{
"body": ("## 🤖 Automated Code Review by Ampcode (Part " + $chunk_num + "/" + $total_chunks + ")\n\n**Review Summary:**\n\n```\n" + $content + "\n```\n\n### 🔍 Key Areas Reviewed\n- Code quality and best practices\n- Potential bugs and security issues\n- Performance considerations\n- Maintainability and readability\n\n### 📝 Notes\n- This is an automated review generated by Ampcode AI\n- Please review the suggestions and apply them as appropriate\n- For questions about specific recommendations, feel free to ask!\n\n---\n*Generated by [Ampcode](https://ampcode.com) • [View Workflow](https://github.com/" + $repo + "/actions/runs/" + $run_id + ")*"),
"event": "COMMENT"
}' > "review_comment_$i.json"
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" \
-d @"review_comment_$i.json" \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ steps.pr-context.outputs.pr_number }}/reviews"
echo "Posted review comment part $i/$TOTAL_CHUNKS"
sleep 1
fi
done
else
# Fallback to single comment if chunking failed
jq -n \
--arg content "$REVIEW_CONTENT" \
--arg run_id "${{ github.run_id }}" \
--arg repo "${{ github.repository }}" \
'{
"body": ("## 🤖 Automated Code Review by Ampcode\n\n**Review Summary:**\n\n```\n" + $content + "\n```\n\n### 🔍 Key Areas Reviewed\n- Code quality and best practices\n- Potential bugs and security issues\n- Performance considerations\n- Maintainability and readability\n\n### 📝 Notes\n- This is an automated review generated by Ampcode AI\n- Please review the suggestions and apply them as appropriate\n- For questions about specific recommendations, feel free to ask!\n\n---\n*Generated by [Ampcode](https://ampcode.com) • [View Workflow](https://github.com/" + $repo + "/actions/runs/" + $run_id + ")*"),
"event": "COMMENT"
}' > review_comment.json
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" \
-d @review_comment.json \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ steps.pr-context.outputs.pr_number }}/reviews"
fi
echo "Multiple smaller review comments posted successfully"
exit 0
fi
echo "Processing line-specific comments..."
# Get the actual diff to compute GitHub diff positions
git diff origin/${{ steps.pr-context.outputs.pr_base_ref }}..HEAD > actual_diff.patch
# Fetch PR files with GitHub-calculated patch chunks for exact diff positions
curl -s \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ steps.pr-context.outputs.pr_number }}/files?per_page=100" \
> pr_files.json
# Install TypeScript dependencies and run the parser script
cd .github/scripts
npm install
npm run build
node dist/parse-review-comments.js
cd ../..
if [ -f review_payload.json ]; then
response=$(curl -s -w "\n%{http_code}" -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" \
-d @review_payload.json \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ steps.pr-context.outputs.pr_number }}/reviews")
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | head -n -1)
if [ "$http_code" = "200" ] || [ "$http_code" = "201" ]; then
echo "Posted review with inline comments successfully"
else
echo "Posting review failed (HTTP $http_code). Falling back to multiple smaller comments."
echo "$body"
# Fall back to multiple smaller comments
echo "$REVIEW_CONTENT" | awk '
BEGIN {
chunk_size = 1000
chunk_count = 0
current_chunk = ""
}
{
if (length(current_chunk) + length($0) > chunk_size && current_chunk != "") {
chunk_count++
print "=== CHUNK " chunk_count " ===" > "chunk_" chunk_count ".txt"
print current_chunk > "chunk_" chunk_count ".txt"
current_chunk = $0
} else {
if (current_chunk != "") current_chunk = current_chunk "\n"
current_chunk = current_chunk $0
}
}
END {
if (current_chunk != "") {
chunk_count++
print "=== CHUNK " chunk_count " ===" > "chunk_" chunk_count ".txt"
print current_chunk > "chunk_" chunk_count ".txt"
}
print chunk_count > "total_chunks.txt"
}'
TOTAL_CHUNKS=$(cat total_chunks.txt 2>/dev/null || echo "0")
if [ "$TOTAL_CHUNKS" -gt 0 ]; then
for i in $(seq 1 $TOTAL_CHUNKS); do
if [ -f "chunk_$i.txt" ]; then
CHUNK_CONTENT=$(cat "chunk_$i.txt")
jq -n \
--arg content "$CHUNK_CONTENT" \
--arg run_id "${{ github.run_id }}" \
--arg repo "${{ github.repository }}" \
--arg chunk_num "$i" \
--arg total_chunks "$TOTAL_CHUNKS" \
'{
"body": ("## 🤖 Automated Code Review by Ampcode (Part " + $chunk_num + "/" + $total_chunks + ")\n\n**Review Summary:**\n\n```\n" + $content + "\n```\n\n---\n*Generated by [Ampcode](https://ampcode.com) • [View Workflow](https://github.com/" + $repo + "/actions/runs/" + $run_id + ")*"),
"event": "COMMENT"
}' > "review_comment_fallback_$i.json"
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" \
-d @"review_comment_fallback_$i.json" \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ steps.pr-context.outputs.pr_number }}/reviews"
echo "Posted fallback review comment part $i/$TOTAL_CHUNKS"
sleep 1
fi
done
fi
fi
else
echo "No valid inline comments; posting multiple smaller review comments"
echo "$REVIEW_CONTENT" | awk '
BEGIN {
chunk_size = 1000
chunk_count = 0
current_chunk = ""
}
{
if (length(current_chunk) + length($0) > chunk_size && current_chunk != "") {
chunk_count++
print "=== CHUNK " chunk_count " ===" > "chunk_" chunk_count ".txt"
print current_chunk > "chunk_" chunk_count ".txt"
current_chunk = $0
} else {
if (current_chunk != "") current_chunk = current_chunk "\n"
current_chunk = current_chunk $0
}
}
END {
if (current_chunk != "") {
chunk_count++
print "=== CHUNK " chunk_count " ===" > "chunk_" chunk_count ".txt"
print current_chunk > "chunk_" chunk_count ".txt"
}
print chunk_count > "total_chunks.txt"
}'
TOTAL_CHUNKS=$(cat total_chunks.txt 2>/dev/null || echo "0")
if [ "$TOTAL_CHUNKS" -gt 0 ]; then
for i in $(seq 1 $TOTAL_CHUNKS); do
if [ -f "chunk_$i.txt" ]; then
CHUNK_CONTENT=$(cat "chunk_$i.txt")
jq -n \
--arg content "$CHUNK_CONTENT" \
--arg run_id "${{ github.run_id }}" \
--arg repo "${{ github.repository }}" \
--arg chunk_num "$i" \
--arg total_chunks "$TOTAL_CHUNKS" \
'{
"body": ("## 🤖 Automated Code Review by Ampcode (Part " + $chunk_num + "/" + $total_chunks + ")\n\n**Review Summary:**\n\n```\n" + $content + "\n```\n\n---\n*Generated by [Ampcode](https://ampcode.com) • [View Workflow](https://github.com/" + $repo + "/actions/runs/" + $run_id + ")*"),
"event": "COMMENT"
}' > "review_comment_$i.json"
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" \
-d @"review_comment_$i.json" \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ steps.pr-context.outputs.pr_number }}/reviews"
echo "Posted review comment part $i/$TOTAL_CHUNKS"
sleep 1
fi
done
else
# Final fallback to single comment
jq -n \
--arg content "$REVIEW_CONTENT" \
--arg run_id "${{ github.run_id }}" \
--arg repo "${{ github.repository }}" \
'{
"body": ("## 🤖 Automated Code Review by Ampcode\n\n**Review Summary:**\n\n```\n" + $content + "\n```\n\n---\n*Generated by [Ampcode](https://ampcode.com) • [View Workflow](https://github.com/" + $repo + "/actions/runs/" + $run_id + ")*"),
"event": "COMMENT"
}' > review_comment.json
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" \
-d @review_comment.json \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ steps.pr-context.outputs.pr_number }}/reviews"
fi
fi
- name: Add Review Completed Reaction
if: always() && steps.changed-files.outputs.changed_files != ''
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" \
-d '{"content":"hooray"}' \
"https://api.github.com/repos/${{ github.repository }}/issues/${{ steps.pr-context.outputs.pr_number }}/reactions"
echo "Added ✅ reaction to indicate review has completed"
- name: Cleanup
if: always()
run: |
rm -f changed_files.txt ampcode_review.txt review_comment.json review_payload.json review_comment_fallback.json line_comments.txt actual_diff.patch
rm -f chunk_*.txt total_chunks.txt review_comment_*.json review_comment_fallback_*.json
echo "Cleanup completed"
- name: Summary
if: always()
run: |
echo "=== Ampcode PR Review Summary ==="
echo "PR Number: ${{ steps.pr-context.outputs.pr_number }}"
echo "Trigger Type: ${{ steps.pr-context.outputs.trigger_type }}"
echo "Changed Files: $(echo '${{ steps.changed-files.outputs.changed_files }}' | wc -l)"
echo "Review Status: $([ -f ampcode_review.txt ] && echo 'Completed' || echo 'Skipped')"
echo "=== End Summary ==="
manual-review:
if: github.event_name == 'issue_comment' && contains(github.event.comment.body, '/review')
timeout-minutes: 15
runs-on: ${{ vars.RUNNER_IMAGE || 'ubuntu-latest' }}
strategy:
matrix:
review-chunk: [1]
max-parallel: 3
steps:
- name: Check if comment is on a PR
id: check-pr
run: |
if [[ "${{ github.event.issue.pull_request }}" == "" ]]; then
echo "This is not a PR, skipping review"
echo "is_pr=false" >> $GITHUB_OUTPUT
exit 0
else
echo "is_pr=true" >> $GITHUB_OUTPUT
echo "PR URL: ${{ github.event.issue.pull_request.url }}"
fi
- name: Set PR context
if: steps.check-pr.outputs.is_pr == 'true'
id: pr-context
run: |
echo "pr_number=${{ github.event.issue.number }}" >> $GITHUB_OUTPUT
echo "pr_sha=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT
echo "pr_base_ref=${{ github.event.pull_request.base.ref }}" >> $GITHUB_OUTPUT
echo "trigger_type=manual" >> $GITHUB_OUTPUT
echo "comment_author=${{ github.event.comment.user.login }}" >> $GITHUB_OUTPUT
- name: Checkout PR branch
if: steps.check-pr.outputs.is_pr == 'true'
uses: actions/checkout@v4
with:
ref: ${{ steps.pr-context.outputs.pr_sha }}
fetch-depth: 0
- name: Setup Node.js
if: steps.check-pr.outputs.is_pr == 'true'
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install Ampcode CLI
if: steps.check-pr.outputs.is_pr == 'true'
run: |
npm install -g @sourcegraph/amp
amp --version
- name: Setup pnpm
if: steps.check-pr.outputs.is_pr == 'true'
uses: pnpm/action-setup@v4
- name: Install project dependencies
if: steps.check-pr.outputs.is_pr == 'true'
run: pnpm install --frozen-lockfile
- name: Get changed files
if: steps.check-pr.outputs.is_pr == 'true'
id: changed-files
run: |
git fetch origin --prune
CHANGED_FILES=$(git diff --name-only origin/${{ steps.pr-context.outputs.pr_base_ref }}..HEAD | grep -E '\.(ts|tsx|js|jsx|py|go|java|cpp|c|h|hpp|rs|rb|php|cs|swift|kt|scala|clj|hs|ml|fs|elm|dart|lua|r|sql|sh|bash|zsh|fish|ps1|bat|cmd|yaml|yml|json|toml|ini|cfg|conf|xml|html|css|scss|sass|less|styl|vue|svelte|astro|md|mdx|tex|latex|bib|org|rst|adoc|asciidoc|wiki|txt)$' | head -50 || echo "")
echo "changed_files<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGED_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
echo "Changed files count: $(echo "$CHANGED_FILES" | wc -l)"
- name: Add Review Started Reaction
if: steps.check-pr.outputs.is_pr == 'true' && steps.changed-files.outputs.changed_files != ''
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" \
-d '{"content":"eyes"}' \
"https://api.github.com/repos/${{ github.repository }}/issues/${{ steps.pr-context.outputs.pr_number }}/reactions"
echo "Added 👀 reaction to indicate review has started"
- name: Run Ampcode Review
if: steps.check-pr.outputs.is_pr == 'true' && steps.changed-files.outputs.changed_files != ''
env:
AMP_API_KEY: ${{ secrets.AMPCODE_API_KEY }}
run: |
echo "Running ampcode review on changed files..."
echo "${{ steps.changed-files.outputs.changed_files }}" > changed_files.txt
REVIEW_OUTPUT=$(amp -x "Review the following files for code quality, potential bugs, security issues, performance concerns, and best practices. For each issue found, provide the specific file path and line number where the issue occurs. Format your response as: FILE:line_number:issue_description. Focus on providing specific, actionable feedback with exact line numbers. Files to review: $(cat changed_files.txt | tr '\n' ' ')" 2>&1 || echo "Ampcode review failed")
echo "$REVIEW_OUTPUT" > ampcode_review.txt
echo "=== Ampcode Review Output ==="
cat ampcode_review.txt
echo "=== End Review Output ==="
- name: Parse and Post Comments with Python
if: steps.check-pr.outputs.is_pr == 'true' && steps.changed-files.outputs.changed_files != ''
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMMIT_SHA: ${{ steps.pr-context.outputs.pr_sha }}
run: |
if [ ! -f ampcode_review.txt ] || [ ! -s ampcode_review.txt ]; then
echo "No review output found or file is empty"
exit 0
fi
REVIEW_CONTENT=$(cat ampcode_review.txt)
# Extract line-specific comments in format FILE:line_number:issue_description
echo "$REVIEW_CONTENT" | grep -E '^[[:space:]-]*[^[:space:]]+\.[a-zA-Z0-9]+[[:space:]]*[: ]+[Ll]?[iI]?[nN]?[eE]?[[:space:]]*[0-9]+' > line_comments.txt || true
if [ ! -s line_comments.txt ]; then
echo "No line-specific comments found, creating multiple smaller comments"
# Split the review content into smaller chunks and create multiple comments
echo "$REVIEW_CONTENT" | awk '
BEGIN {
chunk_size = 1000
chunk_count = 0
current_chunk = ""
line_count = 0
}
{
if (length(current_chunk) + length($0) > chunk_size && current_chunk != "") {
chunk_count++
print "=== CHUNK " chunk_count " ===" > "chunk_" chunk_count ".txt"
print current_chunk > "chunk_" chunk_count ".txt"
current_chunk = $0
line_count = 1
} else {
if (current_chunk != "") current_chunk = current_chunk "\n"
current_chunk = current_chunk $0
line_count++
}
}
END {
if (current_chunk != "") {
chunk_count++
print "=== CHUNK " chunk_count " ===" > "chunk_" chunk_count ".txt"
print current_chunk > "chunk_" chunk_count ".txt"
}
print chunk_count > "total_chunks.txt"
}'
TOTAL_CHUNKS=$(cat total_chunks.txt 2>/dev/null || echo "0")
if [ "$TOTAL_CHUNKS" -gt 0 ]; then
echo "Creating $TOTAL_CHUNKS smaller review comments..."
for i in $(seq 1 $TOTAL_CHUNKS); do
if [ -f "chunk_$i.txt" ]; then
CHUNK_CONTENT=$(cat "chunk_$i.txt")
jq -n \
--arg content "$CHUNK_CONTENT" \
--arg run_id "${{ github.run_id }}" \
--arg repo "${{ github.repository }}" \
--arg chunk_num "$i" \
--arg total_chunks "$TOTAL_CHUNKS" \
'{
"body": ("## 🤖 Automated Code Review by Ampcode (Part " + $chunk_num + "/" + $total_chunks + ")\n\n**Review Summary:**\n\n```\n" + $content + "\n```\n\n### 🔍 Key Areas Reviewed\n- Code quality and best practices\n- Potential bugs and security issues\n- Performance considerations\n- Maintainability and readability\n\n### 📝 Notes\n- This is an automated review generated by Ampcode AI\n- Please review the suggestions and apply them as appropriate\n- For questions about specific recommendations, feel free to ask!\n\n---\n*Generated by [Ampcode](https://ampcode.com) • [View Workflow](https://github.com/" + $repo + "/actions/runs/" + $run_id + ")*"),
"event": "COMMENT"
}' > "review_comment_$i.json"
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" \
-d @"review_comment_$i.json" \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ steps.pr-context.outputs.pr_number }}/reviews"
echo "Posted review comment part $i/$TOTAL_CHUNKS"
sleep 1
fi
done
else
# Fallback to single comment if chunking failed
jq -n \
--arg content "$REVIEW_CONTENT" \
--arg run_id "${{ github.run_id }}" \
--arg repo "${{ github.repository }}" \
'{
"body": ("## 🤖 Automated Code Review by Ampcode\n\n**Review Summary:**\n\n```\n" + $content + "\n```\n\n### 🔍 Key Areas Reviewed\n- Code quality and best practices\n- Potential bugs and security issues\n- Performance considerations\n- Maintainability and readability\n\n### 📝 Notes\n- This is an automated review generated by Ampcode AI\n- Please review the suggestions and apply them as appropriate\n- For questions about specific recommendations, feel free to ask!\n\n---\n*Generated by [Ampcode](https://ampcode.com) • [View Workflow](https://github.com/" + $repo + "/actions/runs/" + $run_id + ")*"),
"event": "COMMENT"
}' > review_comment.json
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" \
-d @review_comment.json \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ steps.pr-context.outputs.pr_number }}/reviews"
fi
echo "Multiple smaller review comments posted successfully"
exit 0
fi
echo "Processing line-specific comments..."
git diff origin/${{ steps.pr-context.outputs.pr_base_ref }}..HEAD > actual_diff.patch
# Fetch PR files with GitHub-calculated patch chunks for exact diff positions
curl -s \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ steps.pr-context.outputs.pr_number }}/files?per_page=100" \
> pr_files.json
# Install TypeScript dependencies and run the parser script
cd .github/scripts
npm install
npm run build
node dist/parse-review-comments.js
cd ../..
if [ -f review_payload.json ]; then
response=$(curl -s -w "\n%{http_code}" -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" \
-d @review_payload.json \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ steps.pr-context.outputs.pr_number }}/reviews")
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | head -n -1)
if [ "$http_code" = "200" ] || [ "$http_code" = "201" ]; then
echo "Posted review with inline comments successfully"
else
echo "Posting review failed (HTTP $http_code). Falling back to multiple smaller comments."
echo "$body"
# Fall back to multiple smaller comments
echo "$REVIEW_CONTENT" | awk '
BEGIN {
chunk_size = 1000
chunk_count = 0
current_chunk = ""
}
{
if (length(current_chunk) + length($0) > chunk_size && current_chunk != "") {
chunk_count++
print "=== CHUNK " chunk_count " ===" > "chunk_" chunk_count ".txt"
print current_chunk > "chunk_" chunk_count ".txt"
current_chunk = $0
} else {
if (current_chunk != "") current_chunk = current_chunk "\n"
current_chunk = current_chunk $0
}
}
END {
if (current_chunk != "") {
chunk_count++
print "=== CHUNK " chunk_count " ===" > "chunk_" chunk_count ".txt"
print current_chunk > "chunk_" chunk_count ".txt"
}
print chunk_count > "total_chunks.txt"
}'
TOTAL_CHUNKS=$(cat total_chunks.txt 2>/dev/null || echo "0")
if [ "$TOTAL_CHUNKS" -gt 0 ]; then
for i in $(seq 1 $TOTAL_CHUNKS); do
if [ -f "chunk_$i.txt" ]; then
CHUNK_CONTENT=$(cat "chunk_$i.txt")
jq -n \
--arg content "$CHUNK_CONTENT" \
--arg run_id "${{ github.run_id }}" \
--arg repo "${{ github.repository }}" \
--arg chunk_num "$i" \
--arg total_chunks "$TOTAL_CHUNKS" \
'{
"body": ("## 🤖 Automated Code Review by Ampcode (Part " + $chunk_num + "/" + $total_chunks + ")\n\n**Review Summary:**\n\n```\n" + $content + "\n```\n\n---\n*Generated by [Ampcode](https://ampcode.com) • [View Workflow](https://github.com/" + $repo + "/actions/runs/" + $run_id + ")*"),
"event": "COMMENT"
}' > "review_comment_fallback_$i.json"
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" \
-d @"review_comment_fallback_$i.json" \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ steps.pr-context.outputs.pr_number }}/reviews"
echo "Posted fallback review comment part $i/$TOTAL_CHUNKS"
sleep 1
fi
done
fi
fi
else
echo "No valid inline comments; posting multiple smaller review comments"
echo "$REVIEW_CONTENT" | awk '
BEGIN {
chunk_size = 1000
chunk_count = 0
current_chunk = ""
}
{
if (length(current_chunk) + length($0) > chunk_size && current_chunk != "") {
chunk_count++
print "=== CHUNK " chunk_count " ===" > "chunk_" chunk_count ".txt"
print current_chunk > "chunk_" chunk_count ".txt"
current_chunk = $0
} else {
if (current_chunk != "") current_chunk = current_chunk "\n"
current_chunk = current_chunk $0
}
}
END {
if (current_chunk != "") {
chunk_count++
print "=== CHUNK " chunk_count " ===" > "chunk_" chunk_count ".txt"
print current_chunk > "chunk_" chunk_count ".txt"
}
print chunk_count > "total_chunks.txt"
}'
TOTAL_CHUNKS=$(cat total_chunks.txt 2>/dev/null || echo "0")
if [ "$TOTAL_CHUNKS" -gt 0 ]; then
for i in $(seq 1 $TOTAL_CHUNKS); do
if [ -f "chunk_$i.txt" ]; then
CHUNK_CONTENT=$(cat "chunk_$i.txt")
jq -n \
--arg content "$CHUNK_CONTENT" \
--arg run_id "${{ github.run_id }}" \
--arg repo "${{ github.repository }}" \
--arg chunk_num "$i" \
--arg total_chunks "$TOTAL_CHUNKS" \
'{
"body": ("## 🤖 Automated Code Review by Ampcode (Part " + $chunk_num + "/" + $total_chunks + ")\n\n**Review Summary:**\n\n```\n" + $content + "\n```\n\n---\n*Generated by [Ampcode](https://ampcode.com) • [View Workflow](https://github.com/" + $repo + "/actions/runs/" + $run_id + ")*"),
"event": "COMMENT"
}' > "review_comment_$i.json"
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" \
-d @"review_comment_$i.json" \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ steps.pr-context.outputs.pr_number }}/reviews"
echo "Posted review comment part $i/$TOTAL_CHUNKS"
sleep 1
fi
done
else
# Final fallback to single comment
jq -n \
--arg content "$REVIEW_CONTENT" \
--arg run_id "${{ github.run_id }}" \
--arg repo "${{ github.repository }}" \
'{
"body": ("## 🤖 Automated Code Review by Ampcode\n\n**Review Summary:**\n\n```\n" + $content + "\n```\n\n---\n*Generated by [Ampcode](https://ampcode.com) • [View Workflow](https://github.com/" + $repo + "/actions/runs/" + $run_id + ")*"),
"event": "COMMENT"
}' > review_comment.json
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" \
-d @review_comment.json \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ steps.pr-context.outputs.pr_number }}/reviews"
fi
fi
- name: Add Review Completed Reaction
if: always() && steps.check-pr.outputs.is_pr == 'true' && steps.changed-files.outputs.changed_files != ''
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" \
-d '{"content":"hooray"}' \
"https://api.github.com/repos/${{ github.repository }}/issues/${{ steps.pr-context.outputs.pr_number }}/reactions"
echo "Added ✅ reaction to indicate review has completed"
- name: Cleanup
if: always() && steps.check-pr.outputs.is_pr == 'true'
run: |
rm -f changed_files.txt ampcode_review.txt review_comment.json review_payload.json review_comment_fallback.json line_comments.txt actual_diff.patch
rm -f chunk_*.txt total_chunks.txt review_comment_*.json review_comment_fallback_*.json
echo "Cleanup completed"
- name: Summary
if: always() && steps.check-pr.outputs.is_pr == 'true'
run: |
echo "=== Ampcode Manual PR Review Summary ==="
echo "PR Number: ${{ steps.pr-context.outputs.pr_number }}"
echo "Trigger Type: ${{ steps.pr-context.outputs.trigger_type }}"
echo "Comment Author: ${{ steps.pr-context.outputs.comment_author }}"
echo "Changed Files: $(echo '${{ steps.changed-files.outputs.changed_files }}' | wc -l)"
echo "Review Status: $([ -f ampcode_review.txt ] && echo 'Completed' || echo 'Skipped')"
echo "=== End Summary ==="