Skip to content

Instantly share code, notes, and snippets.

@ericboehs
Created February 27, 2026 20:44
Show Gist options
  • Select an option

  • Save ericboehs/a512ee3f1997f7f3aaa9a789b250637a to your computer and use it in GitHub Desktop.

Select an option

Save ericboehs/a512ee3f1997f7f3aaa9a789b250637a to your computer and use it in GitHub Desktop.
watch-ci: Monitor GitHub Actions CI status for the current branch, with colored output and auto-exit on pass/fail
#!/bin/bash
# Script to watch CI status for the current branch
# Usage: bin/watch-ci [interval_seconds]
set -e
# Default interval (in seconds)
INTERVAL=${1:-10}
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Clear screen function
clear_screen() {
printf "\033[2J\033[H"
}
# Check if we're in a git repository
if ! git rev-parse --git-dir > /dev/null 2>&1; then
echo "❌ Not in a git repository"
exit 1
fi
# Check if gh CLI is available
if ! command -v gh >/dev/null 2>&1; then
echo "❌ GitHub CLI (gh) not found. Install with: brew install gh"
exit 1
fi
# Check if jq is available
if ! command -v jq >/dev/null 2>&1; then
echo "❌ jq not found. Install with: brew install jq"
exit 1
fi
# Get current branch
BRANCH=$(git branch --show-current)
if [ -z "$BRANCH" ]; then
echo "❌ Not on a branch (detached HEAD)"
exit 1
fi
echo -e "πŸ” Watching CI for branch: ${BLUE}$BRANCH${NC}"
echo "⏱️ Refresh interval: ${INTERVAL}s (press Ctrl+C to stop)"
echo ""
# Function to display CI status
show_ci_status() {
local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
clear_screen
echo -e "πŸ” CI Status for branch: ${BLUE}$BRANCH${NC}"
echo "⏱️ Last updated: $timestamp (refreshing every ${INTERVAL}s)"
echo "πŸ“ Press Ctrl+C to stop watching"
echo ""
# Try to get PR checks first
PR_CHECKS=$(gh pr checks 2>/dev/null) || true
if [ -n "$PR_CHECKS" ]; then
echo "πŸ“Š CI Check Results:"
echo "===================="
# Parse and colorize the output
while IFS=$'\t' read -r name status duration url; do
case "$status" in
"pass")
echo -e "βœ… ${GREEN}$name${NC} - ${duration}"
;;
"fail")
echo -e "❌ ${RED}$name${NC} - ${duration}"
echo -e " πŸ“‹ ${BLUE}$url${NC}"
;;
"pending")
echo -e "⏳ ${YELLOW}$name${NC} - running..."
;;
*)
echo -e "❓ ${YELLOW}$name${NC} - $status"
;;
esac
done <<< "$PR_CHECKS"
# Check if all passed
if echo "$PR_CHECKS" | grep -q "fail"; then
echo ""
echo -e "${RED}❌ Some checks failed${NC}"
echo ""
echo "πŸ“‹ Failure logs:"
echo "==============="
gh run view --log-failed
return 1
elif echo "$PR_CHECKS" | grep -q "pending"; then
echo ""
echo -e "${YELLOW}⏳ Checks still running...${NC}"
return 0
else
echo ""
echo -e "${GREEN}βœ… All checks passed!${NC}"
echo "πŸŽ‰ Exiting since all checks have passed"
return 2
fi
else
# No PR found, check workflow runs for the branch directly
echo "πŸ“Š CI Workflow Status (latest run on $BRANCH):"
echo "=============================================="
# Get the latest workflow run for this branch
RUN_ID=$(gh run list --branch "$BRANCH" --limit 1 --json databaseId --jq '.[0].databaseId' 2>/dev/null)
if [ -z "$RUN_ID" ]; then
echo "❓ No CI runs found for branch $BRANCH"
echo "πŸ’‘ Make sure you've pushed your branch"
return 0
fi
# Get run status and jobs
RUN_INFO=$(gh run view "$RUN_ID" --json status,conclusion,jobs 2>/dev/null)
RUN_STATUS=$(echo "$RUN_INFO" | jq -r '.status')
RUN_CONCLUSION=$(echo "$RUN_INFO" | jq -r '.conclusion')
# Display each job
echo "$RUN_INFO" | jq -r '.jobs[] | "\(.name)\t\(.status)\t\(.conclusion)"' | while IFS=$'\t' read -r name status conclusion; do
if [ "$status" = "completed" ]; then
case "$conclusion" in
"success")
echo -e "βœ… ${GREEN}$name${NC}"
;;
"failure")
echo -e "❌ ${RED}$name${NC}"
;;
"cancelled")
echo -e "β›” ${YELLOW}$name${NC} - cancelled"
;;
*)
echo -e "❓ ${YELLOW}$name${NC} - $conclusion"
;;
esac
else
echo -e "⏳ ${YELLOW}$name${NC} - $status..."
fi
done
# Overall status
echo ""
if [ "$RUN_STATUS" = "completed" ]; then
if [ "$RUN_CONCLUSION" = "success" ]; then
echo -e "${GREEN}βœ… All jobs passed!${NC}"
echo "πŸŽ‰ Exiting since all jobs have passed"
return 2
else
echo -e "${RED}❌ Workflow $RUN_CONCLUSION${NC}"
echo ""
echo "πŸ“‹ Failure logs:"
echo "==============="
gh run view "$RUN_ID" --log-failed
return 1
fi
else
echo -e "${YELLOW}⏳ Workflow still running...${NC}"
return 0
fi
fi
echo ""
echo "πŸ› οΈ Quick commands:"
echo " gh pr view - View PR details"
echo " gh pr checks - Show detailed check status"
echo " gh run list - List recent runs"
}
# Initial display
show_ci_status && rc=$? || rc=$?
if [ $rc -eq 2 ]; then
# All checks already passed on initial check
exit 0
fi
# Watch loop
while true; do
sleep $INTERVAL
show_ci_status && rc=$? || rc=$?
case $rc in
2)
# All checks passed, exit successfully
exit 0
;;
1)
# Some checks failed, continue watching
;;
0)
# Checks still running, continue watching
;;
esac
done
@ericboehs
Copy link
Author

watch-ci

Monitor GitHub Actions CI status for the current branch with colored terminal output. Auto-exits on pass or fail.

Features

  • Auto-detection: Picks up the current git branch automatically
  • PR-aware: Uses gh pr checks when a PR exists, falls back to gh run list for branches without PRs
  • Colored output: Green for pass, red for fail, yellow for pending
  • Auto-exit: Exits with code 0 when all checks pass, continues watching on failure or pending
  • Failure logs: Automatically displays gh run view --log-failed when checks fail
  • Configurable interval: Default 10s refresh, customizable via first argument

Dependencies

  • GitHub CLI (gh) β€” authenticated
  • jq β€” JSON processor
  • git β€” must be run inside a git repository

Installation

curl -fsSL https://gist.githubusercontent.com/ericboehs/a512ee3f1997f7f3aaa9a789b250637a/raw/watch-ci -o ~/bin/watch-ci
chmod +x ~/bin/watch-ci

Usage

# Watch CI with default 10s refresh
watch-ci

# Watch with 30s refresh interval
watch-ci 30

# Typical workflow: push and watch
git push && watch-ci

Exit Codes

Code Meaning
0 All checks passed
1 Not in a git repo, missing dependencies, or detached HEAD

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment