Skip to content

Commit 6c08e73

Browse files
committed
Enable AI code review for test scripts
1 parent bdd3553 commit 6c08e73

File tree

9 files changed

+1334
-0
lines changed

9 files changed

+1334
-0
lines changed

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ make update
4343
make verify # Runs verify-yaml and verify-update
4444
make verify-yaml # Validates YAML manifests
4545
make verify-update # Ensures generated files are up-to-date
46+
make review-changes # Code review for the test files
4647
```
4748

4849
## Architecture

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ verify-update: update
4545
git diff --exit-code HEAD
4646
.PHONY: verify-update
4747

48+
review-changes:
49+
hack/review.sh
50+
.PHONY: review-changes
51+
4852
clean:
4953
rm -rf _output/
5054
.PHONY: clean

hack/review.sh

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Helper script to run code review using Claude Code's Task tool
4+
#
5+
# Usage:
6+
# ./test/review.sh # Review current branch vs origin/main
7+
# ./test/review.sh --pr 1234 # Review specific PR
8+
# ./test/review.sh --range HEAD~3 # Review last 3 commits
9+
# ./test/review.sh --files file1.go file2.go # Review specific files
10+
11+
set -euo pipefail
12+
13+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
14+
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
15+
16+
# Default values
17+
DIFF_RANGE="origin/main...HEAD"
18+
PR_NUMBER=""
19+
PR_REMOTE="${PR_REMOTE:-origin}" # Can be overridden via env var (e.g., PR_REMOTE=upstream)
20+
FILES=()
21+
OUTPUT_FILE="${SCRIPT_DIR}/review-output.json"
22+
23+
function usage() {
24+
cat <<EOF
25+
Usage: $0 [OPTIONS]
26+
27+
Run automated code review using Claude Code agent.
28+
29+
Options:
30+
--pr NUMBER Review a specific pull request number
31+
--range RANGE Git diff range (default: origin/main...HEAD)
32+
--files FILE... Review only specific files
33+
--output FILE Output file for review results (default: test/review-output.json)
34+
-h, --help Show this help message
35+
36+
Environment Variables:
37+
PR_REMOTE Git remote to use for fetching PRs (default: origin)
38+
Set to 'upstream' if working from a fork
39+
40+
Examples:
41+
$0 # Review current changes vs main
42+
$0 --pr 1234 # Review PR #1234 (uses gh CLI if available)
43+
PR_REMOTE=upstream $0 --pr 1234 # Review PR from upstream remote
44+
$0 --range HEAD~5..HEAD # Review last 5 commits
45+
$0 --files pkg/cvo/cvo.go # Review specific file
46+
47+
Notes:
48+
- PR reviews work best with 'gh' CLI installed: https://cli.github.com/
49+
- Without 'gh', falls back to git fetch (requires proper remote configuration)
50+
- When working from a fork, use PR_REMOTE=upstream to fetch from main repository
51+
EOF
52+
}
53+
54+
# Parse arguments
55+
while [[ $# -gt 0 ]]; do
56+
case $1 in
57+
--pr)
58+
PR_NUMBER="$2"
59+
shift 2
60+
;;
61+
--range)
62+
DIFF_RANGE="$2"
63+
shift 2
64+
;;
65+
--files)
66+
shift
67+
while [[ $# -gt 0 ]] && [[ ! $1 =~ ^-- ]]; do
68+
FILES+=("$1")
69+
shift
70+
done
71+
;;
72+
--output)
73+
OUTPUT_FILE="$2"
74+
shift 2
75+
;;
76+
-h|--help)
77+
usage
78+
exit 0
79+
;;
80+
*)
81+
echo "Unknown option: $1"
82+
usage
83+
exit 1
84+
;;
85+
esac
86+
done
87+
88+
cd "$REPO_ROOT"
89+
90+
# Get diff based on input
91+
if [[ -n "$PR_NUMBER" ]]; then
92+
echo "Fetching PR #${PR_NUMBER}..."
93+
94+
if command -v gh &> /dev/null; then
95+
# Use gh CLI (preferred - shows PR metadata and handles authentication)
96+
echo "Using 'gh' CLI to fetch PR..."
97+
DIFF=$(gh pr diff "$PR_NUMBER" 2>&1) || {
98+
echo "Error: Failed to fetch PR #${PR_NUMBER} using 'gh' CLI"
99+
echo "Output: $DIFF"
100+
exit 1
101+
}
102+
FILES_CHANGED=$(gh pr view "$PR_NUMBER" --json files -q '.files[].path' 2>&1) || {
103+
echo "Error: Failed to get PR file list"
104+
exit 1
105+
}
106+
else
107+
# Fallback to git fetch (no gh CLI required)
108+
# Note: This requires 'origin' to be the upstream GitHub repo, not a fork
109+
echo "Note: 'gh' CLI not found. Using git fetch as fallback."
110+
echo "Install 'gh' for better PR integration: https://cli.github.com/"
111+
echo ""
112+
113+
PR_REF="pull/${PR_NUMBER}/head"
114+
echo "Fetching ${PR_REF} from remote '${PR_REMOTE}'..."
115+
116+
if ! git fetch "$PR_REMOTE" "$PR_REF" 2>/dev/null; then
117+
echo ""
118+
echo "Error: Could not fetch PR #${PR_NUMBER} from remote '${PR_REMOTE}'"
119+
echo ""
120+
echo "This can happen if:"
121+
echo " - Your 'origin' remote is a fork (not the upstream repo)"
122+
echo " - The PR doesn't exist or is closed"
123+
echo " - You don't have network access to the repository"
124+
echo ""
125+
echo "Possible solutions:"
126+
echo " 1. Install 'gh' CLI (recommended): https://cli.github.com/manual/installation"
127+
echo " 2. Add upstream remote: git remote add upstream https://github.com/openshift/cluster-version-operator.git"
128+
echo " Then use: PR_REMOTE=upstream ./test/review.sh --pr ${PR_NUMBER}"
129+
echo " 3. Manually fetch: git fetch origin pull/${PR_NUMBER}/head:pr-${PR_NUMBER}"
130+
echo " 4. Use git range instead: ./test/review.sh --range origin/main...HEAD"
131+
exit 1
132+
fi
133+
134+
# Get the base branch (usually main)
135+
BASE_BRANCH=$(git remote show "$PR_REMOTE" 2>/dev/null | grep 'HEAD branch' | cut -d' ' -f5)
136+
BASE_BRANCH=${BASE_BRANCH:-main}
137+
138+
DIFF=$(git diff "${PR_REMOTE}/${BASE_BRANCH}...FETCH_HEAD")
139+
FILES_CHANGED=$(git diff --name-only "${PR_REMOTE}/${BASE_BRANCH}...FETCH_HEAD")
140+
141+
echo "Successfully fetched PR #${PR_NUMBER}"
142+
fi
143+
elif [[ ${#FILES[@]} -gt 0 ]]; then
144+
echo "Reviewing specified files: ${FILES[*]}"
145+
DIFF=$(git diff "$DIFF_RANGE" -- "${FILES[@]}")
146+
FILES_CHANGED=$(printf '%s\n' "${FILES[@]}")
147+
else
148+
echo "Reviewing changes in range: $DIFF_RANGE"
149+
DIFF=$(git diff "$DIFF_RANGE")
150+
FILES_CHANGED=$(git diff --name-only "$DIFF_RANGE")
151+
fi
152+
153+
if [[ -z "$DIFF" ]]; then
154+
echo "No changes found to review."
155+
exit 0
156+
fi
157+
158+
echo "Files changed:"
159+
echo "$FILES_CHANGED"
160+
echo ""
161+
echo "Generating code review..."
162+
echo ""
163+
164+
# Create prompt for the agent
165+
REPO_NAME=$(git remote get-url origin | sed -e 's/.*[:/]\([^/]*\/[^/]*\)\.git$/\1/' -e 's/.*[:/]\([^/]*\/[^/]*\)$/\1/')
166+
167+
REVIEW_PROMPT=$(cat <<EOF
168+
Please perform a code review for the following changes in the ${REPO_NAME} repository.
169+
170+
Files changed:
171+
${FILES_CHANGED}
172+
173+
Git diff:
174+
\`\`\`diff
175+
${DIFF}
176+
\`\`\`
177+
178+
Analyze these changes according to the code review checklist and provide your findings in JSON format as specified in your instructions.
179+
EOF
180+
)
181+
182+
# Save prompt to temp file for claude CLI
183+
PROMPT_FILE=$(mktemp)
184+
echo "$REVIEW_PROMPT" > "$PROMPT_FILE"
185+
186+
echo "=== CODE REVIEW RESULTS ==="
187+
echo ""
188+
189+
# Check if claude CLI is available
190+
if command -v claude &> /dev/null; then
191+
# Use Claude Code CLI if available
192+
claude task --type general-purpose --prompt "@${PROMPT_FILE}" --output "$OUTPUT_FILE"
193+
echo ""
194+
echo "Review saved to: $OUTPUT_FILE"
195+
196+
# Pretty print if jq is available
197+
if command -v jq &> /dev/null && [[ -f "$OUTPUT_FILE" ]]; then
198+
echo ""
199+
echo "=== SUMMARY ==="
200+
jq -r '.summary // "No summary available"' "$OUTPUT_FILE"
201+
echo ""
202+
echo "Verdict: $(jq -r '.verdict // "Unknown"' "$OUTPUT_FILE")"
203+
echo ""
204+
echo "Top Risks:"
205+
jq -r '.top_risks[]? // "None identified"' "$OUTPUT_FILE" | sed 's/^/ - /'
206+
fi
207+
else
208+
# Fallback: Print instructions for manual review
209+
echo "Claude Code CLI not found."
210+
echo ""
211+
echo "To perform the review, copy the following prompt to Claude Code:"
212+
echo "---------------------------------------------------------------"
213+
cat "$PROMPT_FILE"
214+
echo "---------------------------------------------------------------"
215+
fi
216+
217+
rm -f "$PROMPT_FILE"

0 commit comments

Comments
 (0)