-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcode-review.yml
More file actions
190 lines (169 loc) · 6.06 KB
/
Copy pathcode-review.yml
File metadata and controls
190 lines (169 loc) · 6.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
name: code-review
description: >
Parallel DAG code review: lint, diff, and structure analysis run concurrently,
then an agent synthesizes findings with structured output.
inputs:
directory:
type: string
default: "."
description: "Directory to review"
base:
type: string
default: "main"
description: "Base branch to diff against"
agents:
reviewer:
system_prompt: |
You are a senior code reviewer. Given lint results, a git diff, and
project structure, produce a structured review. Focus on real issues —
bugs, security, performance, and maintainability. Skip stylistic nitpicks
unless they indicate deeper problems.
jobs:
lint:
steps:
- id: run
uses: shell
run: |
dir="${{ inputs.directory }}"
cd "$dir"
echo "=== Lint Results ==="
# Auto-detect language and run appropriate linter
if [ -f "go.mod" ]; then
echo "Language: Go"
go vet ./... 2>&1 || true
echo "---"
if command -v golangci-lint >/dev/null 2>&1; then
golangci-lint run --timeout 60s 2>&1 | tail -50 || true
fi
elif [ -f "package.json" ]; then
echo "Language: JavaScript/TypeScript"
if [ -f "node_modules/.bin/eslint" ]; then
npx eslint . --max-warnings 50 2>&1 | tail -50 || true
else
echo "(eslint not installed — skipping)"
fi
elif [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
echo "Language: Python"
if command -v ruff >/dev/null 2>&1; then
ruff check . 2>&1 | tail -50 || true
elif command -v flake8 >/dev/null 2>&1; then
flake8 . --max-line-length=120 2>&1 | tail -50 || true
else
echo "(no Python linter found — skipping)"
fi
else
echo "(no recognized project type — skipping lint)"
fi
outputs:
result: ${{ steps.run.outputs.stdout }}
diff:
steps:
- id: run
uses: shell
run: |
dir="${{ inputs.directory }}"
base="${{ inputs.base }}"
cd "$dir"
echo "=== Git Diff vs $base ==="
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "(not a git repo — skipping diff)"
exit 0
fi
# Show changed files summary
echo "--- Changed files ---"
git diff --stat "$base"...HEAD 2>/dev/null || git diff --stat HEAD 2>/dev/null || echo "(no diff available)"
echo ""
# Show actual diff (limited)
echo "--- Diff content (truncated to 300 lines) ---"
git diff "$base"...HEAD 2>/dev/null | head -300 || git diff HEAD 2>/dev/null | head -300 || echo "(no diff)"
outputs:
result: ${{ steps.run.outputs.stdout }}
structure:
steps:
- id: run
uses: shell
run: |
dir="${{ inputs.directory }}"
cd "$dir"
echo "=== Project Structure ==="
echo "--- File tree (depth 3) ---"
find . -maxdepth 3 -not -path './.git/*' -not -path './node_modules/*' -not -path './vendor/*' -not -path './.venv/*' | head -80
echo ""
echo "--- Largest source files ---"
find . -type f \( -name '*.go' -o -name '*.js' -o -name '*.ts' -o -name '*.py' -o -name '*.rs' -o -name '*.java' \) \
-not -path './.git/*' -not -path './node_modules/*' -not -path './vendor/*' \
-exec wc -l {} + 2>/dev/null | sort -rn | head -15
outputs:
result: ${{ steps.run.outputs.stdout }}
review:
needs: [lint, diff, structure]
steps:
- id: analyze
uses: agent
with:
agent: reviewer
prompt: |
Review this codebase:
${{ jobs.lint.outputs.result }}
${{ jobs.diff.outputs.result }}
${{ jobs.structure.outputs.result }}
schema:
type: object
additionalProperties: false
properties:
summary:
type: string
description: "Brief overall assessment (1-2 sentences)"
findings:
type: array
items:
type: object
additionalProperties: false
properties:
severity:
type: string
enum: [critical, warning, info]
category:
type: string
description: "e.g., bug, security, performance, maintainability"
file:
type: string
description: "File path (if applicable)"
message:
type: string
description: "Clear description of the finding"
required: [severity, category, file, message]
recommendation:
type: string
description: "Top-priority action to take"
required: [summary, findings, recommendation]
max_iterations: 1
outputs:
result: ${{ steps.analyze.outputs.output }}
report:
needs: [review]
steps:
- id: format
uses: shell
run: |
echo "======================================"
echo " Code Review Report"
echo " Generated: $(date '+%Y-%m-%d %H:%M:%S')"
echo "======================================"
echo ""
result=$(cat <<'REED_EOF'
${{ jobs.review.outputs.result }}
REED_EOF
)
echo "$result" | jq -r '
"Summary: \(.summary)",
"",
"Findings:",
(.findings[] | " [\(.severity | ascii_upcase)] [\(.category)] \(.file // "-"): \(.message)"),
"",
"Recommendation: \(.recommendation)"
' 2>/dev/null || echo "$result"
outputs:
report: ${{ steps.format.outputs.stdout }}
outputs:
report: ${{ jobs.report.outputs.report }}