Refactor.

This commit is contained in:
2025-11-24 18:56:11 -05:00
parent 91002081f7
commit 431a035ca7
3 changed files with 211 additions and 199 deletions
+159
View File
@@ -0,0 +1,159 @@
#!/usr/bin/env bash
set -euo pipefail
# -----------------------------
# Inputs
# -----------------------------
TOKEN="${TOKEN:?Missing TOKEN}"
API_URL="${API_URL:?Missing API_URL}"
REPO_OWNER="${REPO_OWNER:?Missing REPO_OWNER}"
REPO_NAME="${REPO_NAME:?Missing REPO_NAME}"
APPROVERS="${APPROVERS:?Missing APPROVERS}"
APPROVAL_KEYWORDS="${APPROVAL_KEYWORDS:?Missing APPROVAL_KEYWORDS}"
DENIAL_KEYWORDS="${DENIAL_KEYWORDS:?Missing DENIAL_KEYWORDS}"
POLL_INTERVAL="${POLL_INTERVAL:-10}"
REMINDER_INTERVAL="${REMINDER_INTERVAL:-0}"
IFS=',' read -r -a approver_list <<< "$APPROVERS"
IFS=',' read -r -a approved_kws <<< "$APPROVAL_KEYWORDS"
IFS=',' read -r -a denied_kws <<< "$DENIAL_KEYWORDS"
last_reminder=$(date +%s)
# -----------------------------
# Helper: Escape regex special chars
# -----------------------------
escape_regex() {
sed -e 's/[]\/$*.^|[]/\\&/g' <<< "$1"
}
# -----------------------------
# Helper: Notifications
# -----------------------------
notify_func() {
local msg="$1"
echo "::notice::$msg"
# Local notify script
if [[ -x "$GITHUB_ACTION_PATH/notify" ]]; then
bash "$GITHUB_ACTION_PATH/notify" "$msg" || true
fi
# Apprise CLI
if command -v apprise >/dev/null 2>&1; then
apprise -b "$msg" >/dev/null 2>&1 || true
fi
# Apprise API
if [[ -n "${APPRISE_API_URL:-}" ]]; then
curl -s -X POST \
-H "Content-Type: application/json" \
-d "{\"body\":\"$msg\"}" \
"$APPRISE_API_URL/notify" >/dev/null 2>&1 || true
fi
}
# -----------------------------
# Step 1: Create the issue
# -----------------------------
title="Manual approval required"
body="Workflow requires manual approval.
Approvers: ${APPROVERS}
Reply with:
${APPROVAL_KEYWORDS}
${DENIAL_KEYWORDS}"
# Build assignees JSON
assignees_json=$(jq -nc --arg csv "$APPROVERS" '$csv|split(",")')
json=$(jq -n \
--arg title "$title" \
--arg body "$body" \
--argjson assignees "$assignees_json" \
'{title:$title, body:$body, assignees:$assignees}')
resp=$(curl -s -X POST \
-H "Authorization: token $TOKEN" \
-H "Content-Type: application/json" \
-d "$json" \
"$API_URL/repos/$REPO_OWNER/$REPO_NAME/issues")
ISSUE=$(echo "$resp" | jq -r '.number // .index // .id')
if [[ -z "$ISSUE" || "$ISSUE" == "null" ]]; then
echo "❌ Failed to create issue: $resp"
exit 1
fi
notify_func "Approval required on issue #$ISSUE"
# -----------------------------
# Step 2: Poll for comments
# -----------------------------
while true; do
comments=$(curl -s \
-H "Authorization: token $TOKEN" \
"$API_URL/repos/$REPO_OWNER/$REPO_NAME/issues/$ISSUE/comments")
declare -A state
for u in "${approver_list[@]}"; do
state["$u"]="pending"
done
count=$(echo "$comments" | jq 'length')
for ((i=0; i<count; i++)); do
user=$(echo "$comments" | jq -r ".[$i].user.login")
body=$(echo "$comments" | jq -r ".[$i].body" | tr '[:upper:]' '[:lower:]')
body_esc=$(escape_regex "$body")
for k in "${approved_kws[@]}"; do
k_esc=$(escape_regex "$k")
[[ "$body_esc" =~ ^${k_esc}[.!]?$ ]] && state["$user"]="approved"
done
for k in "${denied_kws[@]}"; do
k_esc=$(escape_regex "$k")
[[ "$body_esc" =~ ^${k_esc}[.!]?$ ]] && state["$user"]="denied"
done
done
# Denial check
for u in "${!state[@]}"; do
if [[ "${state[$u]}" == "denied" ]]; then
notify_func "Approval denied by $u on issue #$ISSUE"
echo "approved=false" >> "$GITHUB_OUTPUT"
exit 1
fi
done
# Full approval check
all_ok=true
for u in "${!state[@]}"; do
[[ "${state[$u]}" != "approved" ]] && all_ok=false
done
if $all_ok; then
notify_func "All approvers approved issue #$ISSUE"
echo "approved=true" >> "$GITHUB_OUTPUT"
exit 0
fi
# Send reminders
if (( REMINDER_INTERVAL > 0 )); then
now=$(date +%s)
if (( now - last_reminder >= REMINDER_INTERVAL )); then
pending=""
for u in "${!state[@]}"; do
[[ "${state[$u]}" == "pending" ]] && pending+="$u "
done
notify_func "Reminder: approval pending for [${pending}] on issue #$ISSUE"
last_reminder=$now
fi
fi
sleep "$POLL_INTERVAL"
done