#!/bin/bash # common.sh - Shared utilities for Codex review scripts # Source this file from review scripts: source "$(dirname "${BASH_SOURCE[0]}")/common.sh" set -e CODEX_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" GIT_SCRIPT_DIR="$CODEX_SCRIPT_DIR/../git" # Source platform detection source "$GIT_SCRIPT_DIR/detect-platform.sh" # Check codex is installed check_codex() { if ! command -v codex &>/dev/null; then echo "Error: codex CLI not found. Install with: npm i -g @openai/codex" >&2 exit 1 fi } # Check jq is installed (needed for JSON processing) check_jq() { if ! command -v jq &>/dev/null; then echo "Error: jq not found. Install with your package manager." >&2 exit 1 fi } # Build the codex exec command args for the review mode # Arguments: $1=mode (--uncommitted|--base|--commit), $2=value (branch/sha) build_diff_context() { local mode="$1" local value="$2" local diff_text="" case "$mode" in uncommitted) diff_text=$(git diff HEAD 2>/dev/null; git diff --cached 2>/dev/null; git ls-files --others --exclude-standard 2>/dev/null | while read -r f; do echo "=== NEW FILE: $f ==="; cat "$f" 2>/dev/null; done) ;; base) diff_text=$(git diff "${value}...HEAD" 2>/dev/null) ;; commit) diff_text=$(git show "$value" 2>/dev/null) ;; pr) # Provider detection writes its result to stdout; suppress it so it cannot # be mistaken for diff content when this function is used in a substitution. detect_platform >/dev/null if [[ "$PLATFORM" == "github" ]]; then diff_text=$(gh pr diff "$value" 2>/dev/null) || { echo "Error: Failed to fetch the diff for PR #${value}." >&2 return 1 } elif [[ "$PLATFORM" == "gitea" ]]; then local pr_base base_ref pr_head_ref pr_base=$(tea pr list --fields index,base --output simple 2>/dev/null | awk -v pr="$value" '$1 == pr { print $2; exit }') if [[ -z "$pr_base" ]]; then echo "Error: Could not resolve the base branch for Gitea PR #${value}." >&2 return 1 fi base_ref="refs/remotes/origin/${pr_base}" pr_head_ref="refs/remotes/origin/pr/${value}/head" if ! git fetch --quiet origin \ "+refs/heads/${pr_base}:${base_ref}" \ "+refs/pull/${value}/head:${pr_head_ref}"; then echo "Error: Failed to fetch the base and head refs for Gitea PR #${value}." >&2 return 1 fi diff_text=$(git diff "${base_ref}...${pr_head_ref}") || { echo "Error: Failed to diff the fetched refs for Gitea PR #${value}." >&2 return 1 } else echo "Error: Unsupported git platform while resolving PR #${value}." >&2 return 1 fi ;; esac if [[ "$mode" == "pr" && -z "${diff_text//[[:space:]]/}" ]]; then echo "Error: Unable to construct a non-empty diff for PR #${value}; verify the PR refs and provider access." >&2 return 1 fi printf '%s\n' "$diff_text" } # Format JSON findings as markdown for PR comments # Arguments: $1=json_file, $2=review_type (code|security) format_findings_as_markdown() { local json_file="$1" local review_type="$2" if [[ ! -f "$json_file" ]]; then echo "Error: JSON file not found: $json_file" >&2 return 1 fi local summary verdict confidence summary=$(jq -r '.summary' "$json_file") confidence=$(jq -r '.confidence' "$json_file") if [[ "$review_type" == "code" ]]; then verdict=$(jq -r '.verdict' "$json_file") local blockers should_fix suggestions files_reviewed blockers=$(jq -r '.stats.blockers' "$json_file") should_fix=$(jq -r '.stats.should_fix' "$json_file") suggestions=$(jq -r '.stats.suggestions' "$json_file") files_reviewed=$(jq -r '.stats.files_reviewed' "$json_file") cat </dev/null || echo "unknown"))*" } # Post review findings to a PR # Arguments: $1=pr_number, $2=json_file, $3=review_type (code|security) post_to_pr() { local pr_number="$1" local json_file="$2" local review_type="$3" local markdown markdown=$(format_findings_as_markdown "$json_file" "$review_type") detect_platform # Determine review action based on findings local action="comment" if [[ "$review_type" == "code" ]]; then local verdict verdict=$(jq -r '.verdict' "$json_file") action="$verdict" else local risk_level risk_level=$(jq -r '.risk_level' "$json_file") case "$risk_level" in critical|high) action="request-changes" ;; medium) action="comment" ;; low|none) action="comment" ;; esac fi # Post the review "$GIT_SCRIPT_DIR/pr-review.sh" -n "$pr_number" -a "$action" -c "$markdown" } # Print review results to stdout # Arguments: $1=json_file, $2=review_type (code|security) print_results() { local json_file="$1" local review_type="$2" format_findings_as_markdown "$json_file" "$review_type" }