Files
bootstrap/tools/codex/codex-code-review.sh
Jason Woltje 80c3680ccb feat: rename rails/ to tools/ and add service tool suites
Rename the `rails/` directory to `tools/` for agent discoverability —
agents frequently failed to locate helper scripts due to the non-intuitive
directory name. Add backward-compat symlink `rails/ → tools/`.

New tool suites:
- Authentik: auth-token, user-list, user-create, group-list, app-list,
  flow-list, admin-status (8 scripts)
- Coolify: team-list, project-list, service-list, service-status, deploy,
  env-set (7 scripts)
- Woodpecker: pipeline-list, pipeline-status, pipeline-trigger (3 stubs)
- GLPI: session-init, computer-list, ticket-list, ticket-create, user-list
  (6 scripts)
- Health: stack-health.sh — stack-wide connectivity check

Infrastructure:
- Shared credential loader at tools/_lib/credentials.sh
- install.sh creates symlink + chmod on tool scripts
- All ~253 rails/ path references updated across 68+ files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 11:51:39 -06:00

239 lines
6.1 KiB
Bash
Executable File

#!/bin/bash
# codex-code-review.sh - Run an AI-powered code quality review using Codex CLI
# Usage: codex-code-review.sh [OPTIONS]
#
# Runs codex exec in read-only sandbox mode with a structured code review prompt.
# Outputs findings as JSON and optionally posts them to a PR.
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/common.sh"
# Defaults
PR_NUMBER=""
BASE_BRANCH="main"
COMMIT_SHA=""
OUTPUT_FILE=""
POST_TO_PR=false
UNCOMMITTED=false
REVIEW_MODE=""
show_help() {
cat <<'EOF'
Usage: codex-code-review.sh [OPTIONS]
Run an AI-powered code quality review using OpenAI Codex CLI.
Options:
-n, --pr <number> PR number (auto-enables posting findings to PR)
-b, --base <branch> Base branch to diff against (default: main)
-c, --commit <sha> Review a specific commit
-o, --output <path> Write JSON results to file
--post-to-pr Post findings as PR comment (requires -n)
--uncommitted Review uncommitted changes (staged + unstaged + untracked)
-h, --help Show this help
Examples:
# Review uncommitted changes
codex-code-review.sh --uncommitted
# Review a PR and post findings as a comment
codex-code-review.sh -n 42
# Review changes against main, save JSON
codex-code-review.sh -b main -o review.json
# Review a specific commit
codex-code-review.sh -c abc123f
EOF
exit 0
}
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
-n|--pr)
PR_NUMBER="$2"
POST_TO_PR=true
REVIEW_MODE="pr"
shift 2
;;
-b|--base)
BASE_BRANCH="$2"
REVIEW_MODE="base"
shift 2
;;
-c|--commit)
COMMIT_SHA="$2"
REVIEW_MODE="commit"
shift 2
;;
-o|--output)
OUTPUT_FILE="$2"
shift 2
;;
--post-to-pr)
POST_TO_PR=true
shift
;;
--uncommitted)
UNCOMMITTED=true
REVIEW_MODE="uncommitted"
shift
;;
-h|--help)
show_help
;;
*)
echo "Unknown option: $1" >&2
echo "Run with --help for usage" >&2
exit 1
;;
esac
done
# Validate
if [[ -z "$REVIEW_MODE" ]]; then
echo "Error: Specify a review mode: --uncommitted, --base <branch>, --commit <sha>, or --pr <number>" >&2
exit 1
fi
if [[ "$POST_TO_PR" == true && -z "$PR_NUMBER" ]]; then
echo "Error: --post-to-pr requires -n <pr_number>" >&2
exit 1
fi
check_codex
check_jq
# Verify we're in a git repo
if ! git rev-parse --is-inside-work-tree &>/dev/null; then
echo "Error: Not inside a git repository" >&2
exit 1
fi
# Get the diff context
echo "Gathering diff context..." >&2
case "$REVIEW_MODE" in
uncommitted) DIFF_CONTEXT=$(build_diff_context "uncommitted" "") ;;
base) DIFF_CONTEXT=$(build_diff_context "base" "$BASE_BRANCH") ;;
commit) DIFF_CONTEXT=$(build_diff_context "commit" "$COMMIT_SHA") ;;
pr) DIFF_CONTEXT=$(build_diff_context "pr" "$PR_NUMBER") ;;
esac
if [[ -z "$DIFF_CONTEXT" ]]; then
echo "No changes found to review." >&2
exit 0
fi
# Build the review prompt
REVIEW_PROMPT=$(cat <<'PROMPT'
You are an expert code reviewer. Review the following code changes thoroughly.
Focus on issues that are ACTIONABLE and IMPORTANT. Do not flag trivial style issues.
## Review Checklist
### Correctness
- Code does what it claims to do
- Edge cases are handled
- Error conditions are managed properly
- No obvious bugs or logic errors
### Code Quality
- Functions are focused and reasonably sized
- No unnecessary complexity
- DRY - no significant duplication
- Clear naming for variables and functions
- No dead code or commented-out code
### Testing
- Tests exist for new functionality
- Tests cover happy path AND error cases
- No flaky tests introduced
### Performance
- No obvious N+1 queries
- No blocking operations in hot paths
- Resource cleanup (connections, file handles)
### Dependencies
- No deprecated packages
- No unnecessary new dependencies
### Documentation
- Complex logic has explanatory comments
- Public APIs are documented
## Severity Guide
- **blocker**: Must fix before merge (bugs, correctness issues, missing error handling)
- **should-fix**: Important but not blocking (code quality, minor issues)
- **suggestion**: Optional improvements (nice-to-haves)
Only report findings you are confident about (confidence > 0.7).
If the code looks good, say so — don't manufacture issues.
PROMPT
)
# Set up temp files for output and diff
TEMP_OUTPUT=$(mktemp /tmp/codex-review-XXXXXX.json)
TEMP_DIFF=$(mktemp /tmp/codex-diff-XXXXXX.txt)
trap 'rm -f "$TEMP_OUTPUT" "$TEMP_DIFF"' EXIT
SCHEMA_FILE="$SCRIPT_DIR/schemas/code-review-schema.json"
# Write diff to temp file
echo "$DIFF_CONTEXT" > "$TEMP_DIFF"
echo "Running Codex code review..." >&2
echo " Diff size: $(wc -l < "$TEMP_DIFF") lines" >&2
# Build full prompt with diff reference
FULL_PROMPT="${REVIEW_PROMPT}
Here are the code changes to review:
\`\`\`diff
$(cat "$TEMP_DIFF")
\`\`\`"
# Run codex exec with prompt from stdin to avoid arg length limits
echo "$FULL_PROMPT" | codex exec \
--sandbox read-only \
--output-schema "$SCHEMA_FILE" \
-o "$TEMP_OUTPUT" \
- 2>&1 | while IFS= read -r line; do
echo " [codex] $line" >&2
done
# Check output was produced
if [[ ! -s "$TEMP_OUTPUT" ]]; then
echo "Error: Codex produced no output" >&2
exit 1
fi
# Validate JSON
if ! jq empty "$TEMP_OUTPUT" 2>/dev/null; then
echo "Error: Codex output is not valid JSON" >&2
cat "$TEMP_OUTPUT" >&2
exit 1
fi
# Save output if requested
if [[ -n "$OUTPUT_FILE" ]]; then
cp "$TEMP_OUTPUT" "$OUTPUT_FILE"
echo "Results saved to: $OUTPUT_FILE" >&2
fi
# Post to PR if requested
if [[ "$POST_TO_PR" == true && -n "$PR_NUMBER" ]]; then
echo "Posting findings to PR #$PR_NUMBER..." >&2
post_to_pr "$PR_NUMBER" "$TEMP_OUTPUT" "code"
echo "Posted review to PR #$PR_NUMBER" >&2
fi
# Always print results to stdout
print_results "$TEMP_OUTPUT" "code"