Add --no-wait flag and CI workflow polling after push via Gitea Actions API
This commit is contained in:
154
gp
154
gp
@@ -34,6 +34,7 @@ OPTIONS:
|
|||||||
-b, --branch Specify branch to push to (default: current branch)
|
-b, --branch Specify branch to push to (default: current branch)
|
||||||
-a, --add-all Add all files including untracked (default)
|
-a, --add-all Add all files including untracked (default)
|
||||||
--staged-only Only commit staged changes (don't add untracked files)
|
--staged-only Only commit staged changes (don't add untracked files)
|
||||||
|
--no-wait Don't wait for CI workflow to complete after push
|
||||||
|
|
||||||
ARGUMENTS:
|
ARGUMENTS:
|
||||||
message Optional custom commit message (overrides auto-generation)
|
message Optional custom commit message (overrides auto-generation)
|
||||||
@@ -476,6 +477,139 @@ show_status_and_confirm() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Function to extract Gitea API URL and token from git remote
|
||||||
|
# Returns: sets GITEA_API_BASE and GITEA_API_TOKEN, or returns 1
|
||||||
|
parse_gitea_remote() {
|
||||||
|
local remote_url
|
||||||
|
remote_url=$(git remote get-url origin 2>/dev/null) || return 1
|
||||||
|
|
||||||
|
# Match https://TOKEN@HOST/OWNER/REPO.git or https://HOST/OWNER/REPO.git
|
||||||
|
local token="" host="" owner="" repo=""
|
||||||
|
if [[ "$remote_url" =~ ^https://([^@]+)@([^/]+)/([^/]+)/([^/]+?)(\.git)?$ ]]; then
|
||||||
|
token="${BASH_REMATCH[1]}"
|
||||||
|
host="${BASH_REMATCH[2]}"
|
||||||
|
owner="${BASH_REMATCH[3]}"
|
||||||
|
repo="${BASH_REMATCH[4]}"
|
||||||
|
elif [[ "$remote_url" =~ ^https://([^/]+)/([^/]+)/([^/]+?)(\.git)?$ ]]; then
|
||||||
|
host="${BASH_REMATCH[1]}"
|
||||||
|
owner="${BASH_REMATCH[2]}"
|
||||||
|
repo="${BASH_REMATCH[3]}"
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Only support Gitea instances (not github.com etc)
|
||||||
|
case "$host" in
|
||||||
|
github.com|gitlab.com|bitbucket.org) return 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Use GITEA_TOKEN env var if no token in URL
|
||||||
|
[ -z "$token" ] && token="${GITEA_TOKEN:-}"
|
||||||
|
[ -z "$token" ] && return 1
|
||||||
|
|
||||||
|
GITEA_API_BASE="https://${host}/api/v1/repos/${owner}/${repo}"
|
||||||
|
GITEA_API_TOKEN="$token"
|
||||||
|
GITEA_HTML_BASE="https://${host}/${owner}/${repo}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to wait for CI workflow to complete after push
|
||||||
|
# Polls Gitea Actions API, shows spinner, ESC cancels
|
||||||
|
wait_for_workflow() {
|
||||||
|
local head_sha="$1"
|
||||||
|
local branch="$2"
|
||||||
|
|
||||||
|
if ! parse_gitea_remote; then
|
||||||
|
return 0 # silently skip if not a Gitea remote or no token
|
||||||
|
fi
|
||||||
|
|
||||||
|
local spinner_chars='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
|
||||||
|
local spin_idx=0
|
||||||
|
local poll_interval=3
|
||||||
|
local max_wait=600 # 10 minutes max
|
||||||
|
local elapsed=0
|
||||||
|
|
||||||
|
echo
|
||||||
|
print_info "Waiting for CI workflow... (press ESC to stop waiting)"
|
||||||
|
|
||||||
|
# Save terminal settings and enable non-blocking input
|
||||||
|
local old_tty
|
||||||
|
old_tty=$(stty -g 2>/dev/null) || true
|
||||||
|
stty -echo -icanon min 0 time 0 2>/dev/null || true
|
||||||
|
|
||||||
|
# Restore terminal on exit
|
||||||
|
trap 'stty "$old_tty" 2>/dev/null; trap - RETURN' RETURN
|
||||||
|
|
||||||
|
local run_url="" status="" conclusion="" found=false
|
||||||
|
|
||||||
|
while [ "$elapsed" -lt "$max_wait" ]; do
|
||||||
|
# Check for ESC key
|
||||||
|
local key=""
|
||||||
|
key=$(dd bs=1 count=1 2>/dev/null) || true
|
||||||
|
if [ "$key" = $'\x1b' ]; then
|
||||||
|
# Drain any remaining escape sequence bytes
|
||||||
|
dd bs=1 count=5 2>/dev/null >/dev/null || true
|
||||||
|
echo -e "\r\033[K"
|
||||||
|
print_info "Stopped waiting (CI still running in background)"
|
||||||
|
[ -n "$run_url" ] && print_info "View: $run_url"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Poll API
|
||||||
|
local response
|
||||||
|
response=$(curl -sf "${GITEA_API_BASE}/actions/runs?limit=5&token=${GITEA_API_TOKEN}" 2>/dev/null) || true
|
||||||
|
|
||||||
|
if [ -n "$response" ]; then
|
||||||
|
# Find the run matching our commit SHA
|
||||||
|
local run_info
|
||||||
|
run_info=$(echo "$response" | python3 -c "
|
||||||
|
import json, sys
|
||||||
|
d = json.load(sys.stdin)
|
||||||
|
for r in d.get('workflow_runs', []):
|
||||||
|
if r.get('head_sha','').startswith('${head_sha}'):
|
||||||
|
print(r['status'], r.get('conclusion',''), r.get('html_url',''))
|
||||||
|
break
|
||||||
|
" 2>/dev/null) || true
|
||||||
|
|
||||||
|
if [ -n "$run_info" ]; then
|
||||||
|
found=true
|
||||||
|
status=$(echo "$run_info" | awk '{print $1}')
|
||||||
|
conclusion=$(echo "$run_info" | awk '{print $2}')
|
||||||
|
run_url=$(echo "$run_info" | awk '{print $3}')
|
||||||
|
|
||||||
|
if [ "$status" = "completed" ]; then
|
||||||
|
echo -e "\r\033[K"
|
||||||
|
if [ "$conclusion" = "success" ]; then
|
||||||
|
print_success "CI workflow passed"
|
||||||
|
else
|
||||||
|
print_error "CI workflow failed (conclusion: $conclusion)"
|
||||||
|
[ -n "$run_url" ] && print_info "View: $run_url"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Show spinner
|
||||||
|
local spin_char="${spinner_chars:$spin_idx:1}"
|
||||||
|
spin_idx=$(( (spin_idx + 1) % ${#spinner_chars} ))
|
||||||
|
local status_msg="waiting"
|
||||||
|
$found && status_msg="$status"
|
||||||
|
local mins=$((elapsed / 60))
|
||||||
|
local secs=$((elapsed % 60))
|
||||||
|
printf "\r %s CI %s (%d:%02d)" "$spin_char" "$status_msg" "$mins" "$secs"
|
||||||
|
|
||||||
|
sleep "$poll_interval"
|
||||||
|
elapsed=$((elapsed + poll_interval))
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "\r\033[K"
|
||||||
|
print_warning "Timed out waiting for CI (${max_wait}s)"
|
||||||
|
[ -n "$run_url" ] && print_info "View: $run_url"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# Function to perform the actual commit and push
|
# Function to perform the actual commit and push
|
||||||
do_commit_and_push() {
|
do_commit_and_push() {
|
||||||
local commit_msg="$1"
|
local commit_msg="$1"
|
||||||
@@ -493,6 +627,8 @@ do_commit_and_push() {
|
|||||||
|
|
||||||
# Push
|
# Push
|
||||||
print_info "Pushing to $target_branch..."
|
print_info "Pushing to $target_branch..."
|
||||||
|
local push_sha
|
||||||
|
push_sha=$(git rev-parse HEAD)
|
||||||
# Check if branch exists on remote to determine if we need -u flag
|
# Check if branch exists on remote to determine if we need -u flag
|
||||||
if git ls-remote --exit-code --heads origin "$target_branch" >/dev/null 2>&1; then
|
if git ls-remote --exit-code --heads origin "$target_branch" >/dev/null 2>&1; then
|
||||||
# Branch exists on remote, normal push
|
# Branch exists on remote, normal push
|
||||||
@@ -513,13 +649,18 @@ do_commit_and_push() {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Wait for CI workflow if enabled
|
||||||
|
if [ "$WAIT_FOR_CI" = true ]; then
|
||||||
|
wait_for_workflow "$push_sha" "$target_branch" || true
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Autocomplete function for bash
|
# Autocomplete function for bash
|
||||||
autocomplete() {
|
autocomplete() {
|
||||||
local args=("$@")
|
local args=("$@")
|
||||||
if [ ${#args[@]} -eq 0 ]; then
|
if [ ${#args[@]} -eq 0 ]; then
|
||||||
printf "%s\n" "--help" "--dry-run" "--force" "--yes" "--add-all" "--staged-only" "--branch" "-h" "-n" "-f" "-y" "-a" "-b"
|
printf "%s\n" "--help" "--dry-run" "--force" "--yes" "--add-all" "--staged-only" "--no-wait" "--branch" "-h" "-n" "-f" "-y" "-a" "-b"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,6 +672,7 @@ ADD_ALL=true # Default to adding all files
|
|||||||
CUSTOM_MESSAGE=""
|
CUSTOM_MESSAGE=""
|
||||||
TARGET_BRANCH=""
|
TARGET_BRANCH=""
|
||||||
PUSH_ONLY=false
|
PUSH_ONLY=false
|
||||||
|
WAIT_FOR_CI=true
|
||||||
|
|
||||||
# Handle special commands first
|
# Handle special commands first
|
||||||
case "${1:-}" in
|
case "${1:-}" in
|
||||||
@@ -572,6 +714,10 @@ while [[ $# -gt 0 ]]; do
|
|||||||
ADD_ALL=false
|
ADD_ALL=false
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
--no-wait)
|
||||||
|
WAIT_FOR_CI=false
|
||||||
|
shift
|
||||||
|
;;
|
||||||
-b|--branch)
|
-b|--branch)
|
||||||
if [ -z "${2:-}" ]; then
|
if [ -z "${2:-}" ]; then
|
||||||
print_error "Option -b/--branch requires a branch name"
|
print_error "Option -b/--branch requires a branch name"
|
||||||
@@ -628,6 +774,8 @@ main() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Execute push only
|
# Execute push only
|
||||||
|
local push_sha
|
||||||
|
push_sha=$(git rev-parse HEAD)
|
||||||
print_info "Pushing existing commits to $TARGET_BRANCH..."
|
print_info "Pushing existing commits to $TARGET_BRANCH..."
|
||||||
# Check if branch exists on remote to determine if we need -u flag
|
# Check if branch exists on remote to determine if we need -u flag
|
||||||
if git ls-remote --exit-code --heads origin "$TARGET_BRANCH" >/dev/null 2>&1; then
|
if git ls-remote --exit-code --heads origin "$TARGET_BRANCH" >/dev/null 2>&1; then
|
||||||
@@ -649,6 +797,10 @@ main() {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
# Wait for CI workflow if enabled
|
||||||
|
if [ "$WAIT_FOR_CI" = true ]; then
|
||||||
|
wait_for_workflow "$push_sha" "$TARGET_BRANCH" || true
|
||||||
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user