#!/bin/bash # issue-view.sh - View issue details, including comments, on GitHub or Gitea # Usage: issue-view.sh -i set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/detect-platform.sh" # Parse arguments ISSUE_NUMBER="" # get_remote_host and get_gitea_token are provided by detect-platform.sh gitea_issue_view_api() { local host repo token url host=$(get_remote_host) || { echo "Error: could not determine remote host for API fallback" >&2 return 1 } repo=$(get_repo_info) || { echo "Error: could not determine repo owner/name for API fallback" >&2 return 1 } token=$(get_gitea_token "$host") || { echo "Error: Gitea token not found for API fallback (set GITEA_TOKEN or configure ~/.git-credentials)" >&2 return 1 } url="https://${host}/api/v1/repos/${repo}/issues/${ISSUE_NUMBER}" local -a curl_args=(-fsS -H "User-Agent: curl/8" -H "Authorization: token ${token}") if ! command -v python3 >/dev/null 2>&1; then # No renderer: raw JSON is all this path can give. Comments are a # second resource, so fetch them too rather than only the count. curl "${curl_args[@]}" "$url" curl "${curl_args[@]}" "${url}/comments" return fi # Render issue + comments as text (#1357 F2). The old fallback dumped the # issue JSON, which carries only a comment COUNT, so every comment body was # invisible on this path and the wrapper could never show what # `tea issues --comments` shows. { curl "${curl_args[@]}" "$url" echo echo "__MOSAIC_COMMENTS__" curl "${curl_args[@]}" "${url}/comments" } | python3 -c ' import json, sys raw = sys.stdin.read() issue_raw, _, comments_raw = raw.partition("__MOSAIC_COMMENTS__") issue = json.loads(issue_raw) comments = json.loads(comments_raw) if comments_raw.strip() else [] print("#%s %s" % (issue["number"], issue["title"])) print("State: %s Author: %s Created: %s" % (issue["state"], issue["user"]["login"], issue["created_at"])) labels = ", ".join(l["name"] for l in issue.get("labels") or []) if labels: print("Labels: " + labels) if issue.get("milestone"): print("Milestone: " + issue["milestone"]["title"]) print("URL: " + issue["html_url"]) print() print(issue.get("body") or "(no body)") if comments: print() print("--- Comments (%d) ---" % len(comments)) for c in comments: print() print("[%s at %s]" % (c["user"]["login"], c["created_at"])) print(c.get("body") or "") ' } while [[ $# -gt 0 ]]; do case $1 in -i|--issue) ISSUE_NUMBER="$2" shift 2 ;; -h|--help) echo "Usage: issue-view.sh -i " echo "" echo "Options:" echo " -i, --issue Issue number (required)" echo "" echo "Comments are always included (tea --comments / Gitea API /comments)." echo " -h, --help Show this help" exit 0 ;; *) echo "Unknown option: $1" exit 1 ;; esac done if [[ -z "$ISSUE_NUMBER" ]]; then echo "Error: Issue number is required (-i)" exit 1 fi detect_platform >/dev/null if [[ "$PLATFORM" == "github" ]]; then gh issue view "$ISSUE_NUMBER" elif [[ "$PLATFORM" == "gitea" ]]; then if command -v tea >/dev/null 2>&1; then # --comments is what makes tea print the comment bodies (#1357 F3). # Without it tea prompts for them interactively, which in a # non-interactive wrapper means they are silently never shown. tea_err=$(mktemp) if tea issue "$ISSUE_NUMBER" $(get_gitea_repo_args) --comments 2>"$tea_err"; then rm -f "$tea_err" exit 0 fi # Name the cause tea actually reported, not a guessed one (#1357 F1/F4). # tea reads the cwd's git config before honouring --repo; a repo with # extensions.worktreeconfig=true makes it exit 1 with a # repositoryformatversion error. That is a git-config condition, not a # credential one. The old path printed the REVOKED OR STALE TOKEN note # here unconditionally, which sent readers to rotate a token that was fine. if grep -q 'repositoryformatversion' "$tea_err"; then echo "Warning: tea cannot read this repo's git config (extensions.worktreeconfig); not a credential problem. Using Gitea API fallback." >&2 elif grep -q 'user does not exist' "$tea_err"; then echo "Warning: tea issue view failed, trying Gitea API fallback..." >&2 { declare -F explain_tea_user_does_not_exist >/dev/null && explain_tea_user_does_not_exist; } || true else echo "Warning: tea issue view failed, trying Gitea API fallback..." >&2 fi sed 's/^/ tea: /' "$tea_err" >&2 rm -f "$tea_err" fi gitea_issue_view_api else echo "Error: Unknown platform" exit 1 fi