Skip to content

feat(cloud): ✨ add checkout integration and payment callback flow #38

feat(cloud): ✨ add checkout integration and payment callback flow

feat(cloud): ✨ add checkout integration and payment callback flow #38

Workflow file for this run

name: LLM PR Review
on:
pull_request:
types: [opened, synchronize, reopened]
branches:
- master
workflow_dispatch:
inputs:
pr_number:
description: "Pull request number to review"
required: true
type: number
concurrency:
group: llm-review-${{ github.event.pull_request.number || github.event.inputs.pr_number }}
cancel-in-progress: true
permissions:
contents: read
pull-requests: write
jobs:
llm-review:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 1
# This step uses the Anthropic Messages API.
# Secrets required: APIKey; Variables required: APIBase, ModelId
- name: Generate LLM review
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
API_BASE: ${{ vars.ANTHROPIC_BASE_URL }}
API_KEY: ${{ secrets.ANTHROPIC_AUTH_TOKEN }}
MODEL_ID: ${{ vars.ANTHROPIC_MODEL }}
PR_NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number }}
REPO: ${{ github.repository }}
run: |
set -euo pipefail
IFS=$'\n\t'
pr_json=$(curl -sf \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$REPO/pulls/$PR_NUMBER") || {
echo "::error::Failed to fetch PR metadata"
exit 1
}
pr_title=$(printf "%s" "$pr_json" | jq -r '.title // ""')
pr_body=$(printf "%s" "$pr_json" | jq -r '.body // ""')
pr_diff=$(curl -sf \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3.diff" \
"https://api.github.com/repos/$REPO/pulls/$PR_NUMBER") || {
echo "::error::Failed to fetch PR diff"
exit 1
}
max_diff_chars=131072
pr_diff_trimmed="${pr_diff:0:$max_diff_chars}"
# Trim to last complete line to avoid cutting mid-line
pr_diff_trimmed="${pr_diff_trimmed%$'\n'*}"
system_prompt=$(cat <<'SYSPROMPT'
You are a senior software engineer reviewing a pull request for an Electron desktop application (React 18 + TypeScript + Vite + Prisma/SQLite + Ant Design). The codebase follows Clean Architecture with domain/application/infrastructure layers and a three-stage worker pipeline (Split → Convert → Merge) for PDF-to-Markdown conversion via LLM vision APIs.
## Review priorities (highest to lowest)
1. **Correctness** — Logic errors, race conditions, broken control flow, incorrect types, off-by-one errors, null/undefined mishandling
2. **Security** — Command injection, path traversal, credential leaks, unsafe IPC, unvalidated external input (OWASP Top 10)
3. **Resource & performance** — Memory leaks, unbounded loops, missing cleanup in Electron main process, unnecessary re-renders in React, N+1 queries
4. **Error handling** — Swallowed errors, overly broad catch blocks, missing user-facing error feedback, silent failures that hide bugs
5. **API & type contracts** — Breaking changes to IPC channel signatures, mismatched shared types between main/renderer, incorrect Prisma usage
6. **Maintainability** — Violations of existing project patterns, dead code, missing or misleading abstractions
## What NOT to comment on
- Pure style/formatting (handled by Prettier + ESLint)
- Adding comments or docstrings to unchanged code
- Minor naming preferences that don't affect clarity
- Suggesting tests for trivial changes
- Hypothetical future improvements unrelated to this PR
## How to read the diff
The diff uses unified format. Each hunk header looks like:
`@@ -old_start,old_count +new_start,new_count @@ optional_context`
To reference a line: start from `+new_start` and count only context lines (` `) and added lines (`+`), skipping removed lines (`-`). Use the format `file_path:line_number`.
## Output format
Use this exact structure. **Omit any section that has no items.** Each item must reference a specific location and be actionable.
### Summary
1-3 sentences: what this PR does, overall quality assessment, and whether it is ready to merge.
### Critical
Issues that **must** be fixed before merge — bugs, security vulnerabilities, data loss risks.
- `file:line` — **Title**: Explanation of the issue and a concrete suggestion to fix it.
### Important
Issues that **should** be fixed — error handling gaps, performance concerns, contract violations.
- `file:line` — **Title**: Explanation and suggestion.
### Suggestion
Non-blocking improvements — cleaner patterns, minor simplifications, readability tweaks.
- `file:line` — **Title**: Explanation and suggestion.
### Praise
Highlight 1-3 notably well-done aspects to reinforce good practices.
- `file:line` — **Title**: What was done well and why it matters.
SYSPROMPT
)
# Write large variables to temp files to avoid ARG_MAX limit
printf "%s" "$system_prompt" > /tmp/system_prompt.txt
printf "%s" "$pr_diff_trimmed" > /tmp/pr_diff.txt
request_body=$(jq -n \
--arg model "$MODEL_ID" \
--rawfile system /tmp/system_prompt.txt \
--arg title "$pr_title" \
--arg body "$pr_body" \
--rawfile diff /tmp/pr_diff.txt \
'{
model: $model,
max_tokens: 8192,
system: [{ type: "text", text: $system }],
messages: [
{ role: "user", content: ("Review the following pull request.\n\n## Title\n" + $title + "\n\n## Description\n" + $body + "\n\n## Diff\n```diff\n" + $diff + "\n```") }
]
}')
printf "%s" "$request_body" > /tmp/llm_request.json
http_code=$(curl -s -o /tmp/llm_response.json -w "%{http_code}" \
--max-time 120 \
-H "x-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-H "anthropic-version: 2023-06-01" \
"$API_BASE/v1/messages" \
-d @/tmp/llm_request.json) || {
echo "::error::LLM API request failed (curl error)"
exit 1
}
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
echo "::error::LLM API returned HTTP $http_code"
cat /tmp/llm_response.json
exit 1
fi
llm_response=$(cat /tmp/llm_response.json)
review_text=$(printf "%s" "$llm_response" | jq -r '[.content[] | select(.type == "text")] | first? | .text // ""')
if [ -z "$review_text" ]; then
echo "::error::LLM response missing content. Raw response:"
printf "%s" "$llm_response" | jq .
exit 1
fi
review_payload=$(jq -n --arg body "$review_text" '{body: $body, event: "COMMENT"}')
curl -sf --max-time 30 \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$REPO/pulls/$PR_NUMBER/reviews" \
-d "$review_payload" >/dev/null || {
echo "::error::Failed to post PR review"
exit 1
}