diff --git a/packages/mosaic/framework/tools/codex/README.md b/packages/mosaic/framework/tools/codex/README.md index b01ee75..03eb834 100644 --- a/packages/mosaic/framework/tools/codex/README.md +++ b/packages/mosaic/framework/tools/codex/README.md @@ -70,6 +70,8 @@ Security vulnerability review focusing on: ~/.config/mosaic/tools/codex/codex-security-review.sh -n 42 ``` +PR mode resolves the provider's PR diff rather than relying on the caller's checked-out branch. On Gitea, it fetches the base and `refs/pull//head` refs and diffs those explicit refs. If the refs cannot be fetched or the resulting diff is empty, the command exits nonzero before Codex runs or a review is posted. + ### Review Against Base Branch ```bash @@ -253,7 +255,7 @@ Run the script from inside a git repository. ### "No changes found to review" -The specified mode (--uncommitted, --base, etc.) found no changes to review. +The specified non-PR mode (`--uncommitted`, `--base`, etc.) found no changes to review. PR mode instead fails closed with an actionable error when it cannot construct a non-empty provider diff; verify the PR number, remote, provider login, and ref access before retrying. ### "Codex produced no output" diff --git a/packages/mosaic/framework/tools/codex/common.sh b/packages/mosaic/framework/tools/codex/common.sh index 197f1ec..2241405 100755 --- a/packages/mosaic/framework/tools/codex/common.sh +++ b/packages/mosaic/framework/tools/codex/common.sh @@ -44,38 +44,47 @@ build_diff_context() { diff_text=$(git show "$value" 2>/dev/null) ;; pr) - # For PRs, we need to fetch the PR diff - detect_platform + # 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) + 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 - # tea doesn't have a direct pr diff command, use git - local pr_base - pr_base=$(tea pr list --fields index,base --output simple 2>/dev/null | grep "^${value}" | awk '{print $2}') - if [[ -n "$pr_base" ]]; then - diff_text=$(git diff "${pr_base}...HEAD" 2>/dev/null) - else - # Fallback: fetch PR info via API - local repo_info - repo_info=$(get_repo_info) - local remote_url - remote_url=$(git remote get-url origin 2>/dev/null) - local host - host=$(echo "$remote_url" | sed -E 's|.*://([^/]+).*|\1|; s|.*@([^:]+).*|\1|') - diff_text=$(curl -s "https://${host}/api/v1/repos/${repo_info}/pulls/${value}" \ - -H "Authorization: token $(tea login list --output simple 2>/dev/null | head -1 | awk '{print $2}')" \ - 2>/dev/null | jq -r '.diff_url // empty') - if [[ -n "$diff_text" && "$diff_text" != "null" ]]; then - diff_text=$(curl -s "$diff_text" 2>/dev/null) - else - diff_text=$(git diff "main...HEAD" 2>/dev/null) - fi + 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 - echo "$diff_text" + 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