#!/bin/bash # issue-assign.sh - Assign issues on Gitea or GitHub # Usage: issue-assign.sh -i ISSUE_NUMBER [-a assignee] [-l labels] [-m milestone] set -e set -o pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/detect-platform.sh" # Default values ISSUE="" ASSIGNEE="" LABELS="" MILESTONE="" REMOVE_ASSIGNEE=false usage() { cat <&2 usage >&2 } # Parse arguments while [[ $# -gt 0 ]]; do case $1 in -i|--issue) [[ $# -ge 2 && "$2" != - && "$2" != --* && ! "$2" =~ ^-[[:alnum:]] ]] || usage_error "option $1 requires a value (option-like values are rejected; bare - is reserved)" ISSUE="$2" shift 2 ;; -a|--assignee) [[ $# -ge 2 && "$2" != - && "$2" != --* && ! "$2" =~ ^-[[:alnum:]] ]] || usage_error "option $1 requires a value (option-like values are rejected; bare - is reserved)" ASSIGNEE="$2" shift 2 ;; -l|--labels) [[ $# -ge 2 && "$2" != - && "$2" != --* && ! "$2" =~ ^-[[:alnum:]] ]] || usage_error "option $1 requires a value (option-like values are rejected; bare - is reserved)" LABELS="$2" shift 2 ;; -m|--milestone) [[ $# -ge 2 && "$2" != - && "$2" != --* && ! "$2" =~ ^-[[:alnum:]] ]] || usage_error "option $1 requires a value (option-like values are rejected; bare - is reserved)" MILESTONE="$2" shift 2 ;; -r|--remove-assignee) REMOVE_ASSIGNEE=true shift ;; -h|--help) usage 0 ;; *) echo "Unknown option: $1" >&2 usage ;; esac done if [[ -z "$ISSUE" ]]; then echo "Error: Issue number is required (-i)" >&2 usage fi PLATFORM=$(detect_platform) case "$PLATFORM" in github) if [[ -n "$ASSIGNEE" ]]; then prov_rc=0 gh issue edit "$ISSUE" --add-assignee "$ASSIGNEE" || prov_rc=$? [[ "$prov_rc" -eq 0 ]] || { echo "Error: provider command failed (exit ${prov_rc}; provider failure, not a usage error)" >&2; exit 1; } fi if [[ "$REMOVE_ASSIGNEE" == true ]]; then # Get current assignees and remove them # pipefail preserves the provider status through the pipeline; # a FAILED lookup exits here instead of reading as a silent # no-assignees skip (codex PR #1464). A successful lookup with # zero assignees still skips the edit below. CURRENT=$(gh issue view "$ISSUE" --json assignees -q '.assignees[].login' 2>/dev/null | tr '\n' ',') || { echo "Error: could not read current assignees (provider lookup failed)" >&2 exit 1 } if [[ -n "$CURRENT" ]]; then prov_rc=0 gh issue edit "$ISSUE" --remove-assignee "${CURRENT%,}" || prov_rc=$? [[ "$prov_rc" -eq 0 ]] || { echo "Error: provider command failed (exit ${prov_rc}; provider failure, not a usage error)" >&2; exit 1; } fi fi if [[ -n "$LABELS" ]]; then prov_rc=0 gh issue edit "$ISSUE" --add-label "$LABELS" || prov_rc=$? [[ "$prov_rc" -eq 0 ]] || { echo "Error: provider command failed (exit ${prov_rc}; provider failure, not a usage error)" >&2; exit 1; } fi if [[ -n "$MILESTONE" ]]; then prov_rc=0 gh issue edit "$ISSUE" --milestone "$MILESTONE" || prov_rc=$? [[ "$prov_rc" -eq 0 ]] || { echo "Error: provider command failed (exit ${prov_rc}; provider failure, not a usage error)" >&2; exit 1; } fi echo "Issue #$ISSUE updated successfully" ;; gitea) # tea issue edit syntax REPO_SLUG=$(get_repo_slug) || { echo "Error: Could not resolve Gitea repo slug from remote" >&2 exit 1 } REPO_LOGIN=$(get_gitea_login) || { echo "Error: Could not resolve Gitea login for remote host" >&2 exit 1 } REPO_ARGS=(--repo "$REPO_SLUG" --login "$REPO_LOGIN") CMD=(tea issue edit "$ISSUE" "${REPO_ARGS[@]}") NEEDS_EDIT=false if [[ -n "$ASSIGNEE" ]]; then # tea uses --assignees flag CMD+=(--assignees "$ASSIGNEE") NEEDS_EDIT=true fi if [[ -n "$LABELS" ]]; then # tea uses --labels flag (replaces existing) CMD+=(--labels "$LABELS") NEEDS_EDIT=true fi if [[ -n "$MILESTONE" ]]; then MILESTONE_ID=$(tea milestones list "${REPO_ARGS[@]}" 2>/dev/null | grep -E "^\s*[0-9]+" | grep "$MILESTONE" | awk '{print $1}' | head -1) if [[ -n "$MILESTONE_ID" ]]; then CMD+=(--milestone "$MILESTONE_ID") NEEDS_EDIT=true else echo "Warning: Could not find milestone '$MILESTONE'" >&2 fi fi if [[ "$NEEDS_EDIT" == true ]]; then prov_rc=0 "${CMD[@]}" || prov_rc=$? [[ "$prov_rc" -eq 0 ]] || { echo "Error: provider command failed (exit ${prov_rc}; provider failure, not a usage error)" >&2; exit 1; } echo "Issue #$ISSUE updated successfully" else echo "No changes specified" fi ;; *) echo "Error: Could not detect git platform" >&2 exit 1 ;; esac