Skip to content

Instantly share code, notes, and snippets.

@seabass011
Created September 9, 2025 16:38
Show Gist options
  • Select an option

  • Save seabass011/93afecf79b4003e4a9ac1f0d45ce355e to your computer and use it in GitHub Desktop.

Select an option

Save seabass011/93afecf79b4003e4a9ac1f0d45ce355e to your computer and use it in GitHub Desktop.
Nova Demo C - Advanced CI with iteration limits
#!/usr/bin/env bash
# Nova CI-Rescue — CI Mode & Iteration Demo (Beautiful, presenter-ready)
# Focus: CI flow, branch safety, iteration limits, and clear status reporting
set -Eeuo pipefail
# Unset any existing GitHub tokens to ensure we use our hardcoded PAT
unset GH_TOKEN
unset GITHUB_TOKEN
# GitHub PAT for joinnova-ci organization demos
export GITHUB_TOKEN="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"
export GH_TOKEN="$GITHUB_TOKEN"
########################################
# Args & Defaults
########################################
VERBOSE=false
FORCE_YES=false
CI_CMD="pytest -q"
MAX_ITERS="3"
TIMEOUT_SEC="600"
for arg in "$@"; do
case $arg in
-y|--yes)
FORCE_YES=true
shift
;;
-v|--verbose)
VERBOSE=true
shift
;;
--ci=*)
CI_CMD="${arg#*=}"
shift
;;
--max-iters=*)
MAX_ITERS="${arg#*=}"
shift
;;
--timeout=*)
TIMEOUT_SEC="${arg#*=}"
shift
;;
-h|--help)
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " -y, --yes Non-interactive mode"
echo " -v, --verbose Show detailed Nova output"
echo " --ci=\"<cmd>\" Test command (default: pytest -q)"
echo " --max-iters=<N> Iteration cap (default: 3)"
echo " --timeout=<seconds> Max runtime in seconds (default: 600)"
echo " -h, --help Show this help"
exit 0
;;
*)
echo "Unknown option: $arg" >&2
exit 1
;;
esac
done
########################################
# Terminal Intelligence & Visuals
########################################
detect_terminal() {
TERM_WIDTH=$(tput cols 2>/dev/null || echo 80)
TERM_HEIGHT=$(tput lines 2>/dev/null || echo 24)
CAN_UTF8=false
if echo -e '\u2713' | grep -q '' 2>/dev/null; then CAN_UTF8=true; fi
}
setup_visuals() {
BOLD=$'\033[1m'; DIM=$'\033[2m'; UNDERLINE=$'\033[4m'; ITALIC=$'\033[3m'; NC=$'\033[0m'
RED=$'\033[0;31m'; GREEN=$'\033[0;32m'; YELLOW=$'\033[1;33m'; BLUE=$'\033[0;34m'; CYAN=$'\033[0;36m'; PURPLE=$'\033[0;35m'; WHITE=$'\033[0;37m'
if [ "$CAN_UTF8" = true ]; then CHECK=""; CROSS=""; BULLET=""; SPARKLE=""; ROCKET="🚀"; PACKAGE="📦"; BRAIN="🧠"; SHIELD="🛡️"; LOOP="🔁"; else CHECK="[OK]"; CROSS="[X]"; BULLET="*"; SPARKLE="*"; ROCKET=">"; PACKAGE="[]"; BRAIN="AI"; SHIELD="[]"; LOOP="(loop)"; fi
}
hr() { printf '%*s\n' "${TERM_WIDTH}" '' | tr ' ' ''; }
thr() { printf '%*s\n' "${TERM_WIDTH}" '' | tr ' ' ''; }
banner() {
clear || true
echo
echo
thr
echo "Nova CI-Rescue — CI Mode & Iteration"
echo "Software that fixes software"
thr
echo
}
step() {
local n="$1"; local t="$2"; local msg="$3"; local icon="${4:-$PACKAGE}"
echo
echo "Step ${n}/${t}${icon} ${msg}"
hr
}
ok() { echo -e "${GREEN}${NC} $1"; }
warn() { echo -e "${YELLOW}${NC} $1"; }
err() { echo -e "${RED}${NC} $1"; }
info() { echo -e "${CYAN}${NC} $1"; }
ask_yes() {
local prompt="$1"; local default="${2:-Y}"; local yn="[Y/n]"; [ "$default" = "N" ] && yn="[y/N]"
if [ "$FORCE_YES" = true ]; then return 0; fi
printf "%s %s " "$prompt" "$yn"; read -r REPLY; REPLY="${REPLY:-$default}"; [[ "$REPLY" =~ ^[Yy]$ ]]
}
preview_file() {
local file="$1"; local label="$2"
echo
echo -e "${BOLD}${file}${NC} ${DIM}${label}${NC}"
echo -e "${DIM}$(hr)${NC}"
[ -f "$file" ] && nl -ba "$file" | head -15 | sed 's/^/ /'
echo
}
########################################
# Core Demo Flow
########################################
run_demo() {
detect_terminal; setup_visuals; banner
echo -e "${BOLD}What you'll see in under 2 minutes:${NC}"
echo -e " ${BULLET} ${BOLD}CI Mode${NC}: tests fail → Nova auto-fix runs"
echo -e " ${BULLET} ${BOLD}Branch Safety${NC}: fixes on ${ITALIC}nova/fix/*${NC}"
echo -e " ${BULLET} ${BOLD}Iteration Limits${NC}: --max-iters ${MAX_ITERS}, timeouts ${TIMEOUT_SEC}s"
echo -e " ${BULLET} ${BOLD}Safety Limits${NC}: ≤5 files, ≤40 LOC"
echo
if ! ask_yes "Ready to begin?" "Y"; then
echo -e "${DIM}Come back when you're ready.${NC}"
exit 0
fi
# Step 1: Workspace
step 1 6 "Create isolated workspace" "$PACKAGE"
DEMO_DIR="/tmp/nova-ci-iter-$(date +%s)"
rm -rf "$DEMO_DIR" 2>/dev/null || true
mkdir -p "$DEMO_DIR"
cd "$DEMO_DIR"
ok "Workspace: $DEMO_DIR"
# Step 2: Python env
step 2 6 "Set up Python environment" "$PACKAGE"
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install --upgrade pip >/dev/null 2>&1
ok "Virtualenv ready"
# Step 3: Install Nova
step 3 6 "Install Nova CI-Rescue" "$ROCKET"
info "Installing from Cloudsmith mirror + PyPI"
python3 -m pip install --quiet \
nova-ci-rescue pytest pytest-json-report openai requests \
--index-url "https://dl.cloudsmith.io/9rqxsQdhFkYzaXqm/nova/nova-ci-rescue/python/simple/" \
--extra-index-url "https://pypi.org/simple/" \
2>&1 | grep -v "Requirement already satisfied" || true
version=$(nova --version 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "latest")
ok "Nova ${version} installed"
# Step 4: Create demo project
step 4 6 "Set up demo project" "$BRAIN"
# Check for GitHub integration
SKIP_GITHUB=false
if ! command -v gh &> /dev/null; then
warn "GitHub CLI not found. Running local demo only."
info "To enable GitHub integration, install from: https://cli.github.com"
SKIP_GITHUB=true
else
# Unset any existing GitHub tokens to avoid conflicts
unset GITHUB_TOKEN
unset GH_TOKEN
# Check for PAT
if [ -z "${CHAPTER_ONE_PAT:-}" ]; then
err "GitHub Personal Access Token required"
echo
echo "The demo PATs have expired. Please create your own:"
echo
echo " 1. Go to: ${BOLD}https://github.com/settings/tokens/new${NC}"
echo " 2. Give it a name (e.g., 'Nova Demo')"
echo " 3. Select scopes:"
echo " ${CHECK} repo (all)"
echo " ${CHECK} workflow"
echo " 4. Click 'Generate token' and copy it"
echo " 5. Run: ${BOLD}export CHAPTER_ONE_PAT='your-token-here'${NC}"
echo " 6. Then run this demo again"
echo
echo "Note: GitHub PATs expire and need to be regenerated periodically."
exit 1
else
# Test the provided PAT
if ! GH_TOKEN="$CHAPTER_ONE_PAT" gh api user &>/dev/null; then
err "Provided PAT is invalid or expired"
echo
# Get more details about why it failed
ERROR_MSG=$(GH_TOKEN="$CHAPTER_ONE_PAT" gh api user 2>&1 | grep -o '"message":"[^"]*"' | cut -d'"' -f4)
echo "GitHub API error: $ERROR_MSG"
echo
echo "Please check your CHAPTER_ONE_PAT environment variable"
echo "You may need to create a new token at: https://github.com/settings/tokens/new"
exit 1
fi
ok "Using provided CHAPTER_ONE_PAT"
fi
fi
# Create project directory
if [ "$SKIP_GITHUB" = false ]; then
# Create GitHub repo
REPO_NAME="nova-demo-ci-$(date +%s)"
info "Creating GitHub repository: $REPO_NAME"
GH_TOKEN="$CHAPTER_ONE_PAT" gh repo create "$REPO_NAME" --public --clone --description "Nova CI Demo - Automated test fixing" 2>&1 | grep -v "Cloning into" || true
cd "$REPO_NAME"
else
# Create local directory
REPO_NAME="nova-demo-local"
mkdir -p "$REPO_NAME"
cd "$REPO_NAME"
git init
git config user.email "demo@joinnova.com"
git config user.name "Nova Demo"
ok "Local demo repository created"
fi
# Copy demo files
info "Setting up broken calculator demo..."
cat > calculator.py << 'EOF'
"""
Broken Calculator - Nova CI-Rescue Demo
========================================
This calculator has bugs in EVERY function!
Perfect for demonstrating Nova CI-Rescue's ability to fix multiple issues.
Each function has a deliberate bug that causes incorrect results.
The tests will expose these bugs, and Nova will fix them automatically.
"""
def add(a, b):
"""Add two numbers together."""
return a + b + 1
def subtract(a, b):
"""Subtract b from a."""
return a + b
def multiply(a, b):
"""Multiply two numbers."""
return a + b
EOF
cat > test_calculator.py << 'EOF'
"""
Test suite for calculator.py
============================
These tests will reveal the bugs in each calculator function.
Nova CI-Rescue will automatically fix the failing tests.
"""
import pytest
from calculator import (
add, subtract, multiply, divide, power,
modulo, absolute, square_root, factorial, max_of_two
)
class TestCalculator:
"""Test cases for the calculator functions."""
def test_addition(self):
"""Test the add function."""
assert add(2, 3) == 5
assert add(-1, 1) == 0
assert add(0, 0) == 0
assert add(100, 200) == 300
def test_subtraction(self):
"""Test the subtract function."""
assert subtract(10, 3) == 7
assert subtract(0, 5) == -5
assert subtract(-5, -3) == -2
assert subtract(100, 100) == 0
def test_multiplication(self):
"""Test the multiply function."""
assert multiply(3, 4) == 12
assert multiply(-2, 3) == -6
assert multiply(0, 100) == 0
assert multiply(7, 8) == 56
EOF
# Create GitHub workflow
mkdir -p .github/workflows
cat > .github/workflows/nova-ci.yml << 'EOF'
name: Nova CI-Rescue
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest pytest-json-report openai requests
pip install nova-ci-rescue --index-url https://dl.cloudsmith.io/9rqxsQdhFkYzaXqm/nova/nova-ci-rescue/python/simple/ --extra-index-url https://pypi.org/simple/
- name: Run tests
id: test
run: |
pytest test_calculator.py -v || echo "Tests failed as expected"
- name: Nova Auto-Fix
if: failure()
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Set git config
git config --global user.email "nova-ci@joinnova.com"
git config --global user.name "Nova CI Bot"
# Run Nova with safety limits
nova fix --max-iters 3 --timeout 600 --ci "pytest test_calculator.py"
# Create PR if changes made
if [ -n "$(git status --porcelain)" ]; then
BRANCH="nova-fix/$(date +%Y%m%d_%H%M%S)"
git checkout -b "$BRANCH"
git add -A
git commit -m "Nova CI: Auto-fix failing tests"
git push origin "$BRANCH"
gh pr create \
--title "Nova CI: Auto-fix failing tests" \
--body "This PR was automatically generated by Nova CI-Rescue to fix failing tests." \
--base main
fi
EOF
# Initial commit
git add -A
git commit -m "Initial commit with broken calculator"
if [ "$SKIP_GITHUB" = false ]; then
# Set GitHub secret
info "Setting up GitHub secrets..."
GH_TOKEN="$CHAPTER_ONE_PAT" gh secret set OPENAI_API_KEY --body "$OPENAI_API_KEY" || true
# Push to trigger CI
git push -u origin main
ok "Repository created: https://github.com/$(gh repo view --json nameWithOwner -q .nameWithOwner)"
else
ok "Local repository ready"
fi
# Preview
preview_file "calculator.py" "(broken implementation)"
# Step 5: Run Nova fix
if [ "$SKIP_GITHUB" = false ]; then
step 5 6 "Monitor CI pipeline" "$SHIELD"
# Get the workflow run URL
REPO_URL="https://github.com/$(gh repo view --json nameWithOwner -q .nameWithOwner)"
echo -e "${DIM}Repository:${NC} $REPO_URL"
echo -e "${DIM}Actions:${NC} $REPO_URL/actions"
echo
info "Waiting for CI workflow to start..."
# Wait for workflow to start
sleep 5
# Get the latest run
RUN_ID=$(GH_TOKEN="$CHAPTER_ONE_PAT" gh run list --limit 1 --json databaseId --jq '.[0].databaseId' 2>/dev/null || echo "")
if [ -n "$RUN_ID" ]; then
RUN_URL="$REPO_URL/actions/runs/$RUN_ID"
ok "CI workflow started: $RUN_URL"
echo
# Monitor the run
info "Monitoring CI run (this may take 1-2 minutes)..."
echo -e "${DIM}Nova will automatically fix the failing tests...${NC}"
echo
# Poll for status
MAX_WAIT=180 # 3 minutes
ELAPSED=0
while [ $ELAPSED -lt $MAX_WAIT ]; do
STATUS=$(GH_TOKEN="$CHAPTER_ONE_PAT" gh run view $RUN_ID --json status --jq '.status' 2>/dev/null || echo "")
CONCLUSION=$(GH_TOKEN="$CHAPTER_ONE_PAT" gh run view $RUN_ID --json conclusion --jq '.conclusion' 2>/dev/null || echo "")
if [ "$STATUS" = "completed" ]; then
if [ "$CONCLUSION" = "success" ]; then
ok "CI run completed successfully!"
else
warn "CI run completed with status: $CONCLUSION"
fi
break
fi
# Show progress
printf "."
sleep 5
ELAPSED=$((ELAPSED + 5))
done
echo
echo
# Check for PR created by Nova
info "Checking for Nova-generated PR..."
sleep 3
PR_NUMBER=$(GH_TOKEN="$CHAPTER_ONE_PAT" gh pr list --state open --json number,title --jq '.[] | select(.title | contains("Nova")) | .number' | head -1)
if [ -n "$PR_NUMBER" ]; then
PR_URL="$REPO_URL/pull/$PR_NUMBER"
ok "Nova created PR #$PR_NUMBER: $PR_URL"
echo
# Show PR details
echo -e "${BOLD}Pull Request Summary:${NC}"
GH_TOKEN="$CHAPTER_ONE_PAT" gh pr view $PR_NUMBER --json title,body,additions,deletions,changedFiles --jq '
"Title: \(.title)\n" +
"Files changed: \(.changedFiles)\n" +
"Lines added: +\(.additions)\n" +
"Lines deleted: -\(.deletions)"
' | sed 's/^/ /'
echo
# Show the diff
echo -e "${BOLD}Changes made by Nova:${NC}"
GH_TOKEN="$CHAPTER_ONE_PAT" gh pr diff $PR_NUMBER --color always | head -50
else
warn "No PR found yet. Check $REPO_URL/pulls"
fi
else
warn "Could not detect CI run. Check manually at: $REPO_URL/actions"
fi
else
step 5 6 "Run Nova CI Mode locally" "$SHIELD"
# Run tests to show failures
info "Running tests to identify failures..."
export PYTHONPATH="."
set +e
python3 -m pytest test_calculator.py -v --tb=short --no-header | \
sed -e 's/FAILED/\x1b[31mFAILED\x1b[0m/g' -e 's/PASSED/\x1b[32mPASSED\x1b[0m/g'
initial_rc=$?
set -e
echo
echo -e "${BOLD}${RED}${CROSS} Tests failing${NC} - Nova will now fix them"
echo
# API key setup
if [ -z "${OPENAI_API_KEY:-}" ]; then
[ -f "$HOME/.nova.env" ] && source "$HOME/.nova.env" || true
if [ -z "${OPENAI_API_KEY:-}" ]; then
if [ "$FORCE_YES" = true ]; then
err "OPENAI_API_KEY required in environment"
exit 1
fi
printf "${BOLD}Enter OPENAI_API_KEY:${NC} "
read -rs OPENAI_API_KEY
echo
export OPENAI_API_KEY
fi
fi
# Run Nova fix
echo -e "${DIM}Options:${NC} --ci=\"$CI_CMD\" --max-iters=${MAX_ITERS} --timeout=${TIMEOUT_SEC}s (Safety: ≤5 files, ≤40 LOC)"
echo
export NOVA_CI_CMD="$CI_CMD"
if [ "$VERBOSE" = true ]; then
nova fix --max-iters "$MAX_ITERS" --timeout "$TIMEOUT_SEC"
else
echo -e "${DIM}Running Nova...${NC}"
echo -e "${DIM}This may take 30-60 seconds...${NC}"
echo
# Capture Nova output to show progress
local nova_output=$(nova fix --max-iters "$MAX_ITERS" --timeout "$TIMEOUT_SEC" 2>&1)
local nova_result=$?
# Show filtered output
echo "$nova_output" | grep -E "(Running tests|Test results|Fixing|Fixed|Iteration|All tests|PASSED|FAILED|Error:|Failed to|Successfully|Analyzing|Creating|Applying)" | sed 's/^/ /'
# If Nova failed or produced no output, show full output
if [ $nova_result -ne 0 ] || [ -z "$(echo "$nova_output" | grep -E "(Running tests|Fixing|Fixed)")" ]; then
echo
print_warning "Showing full Nova output:"
echo "$nova_output" | sed 's/^/ /'
fi
fi
# Show results
echo
info "Verifying fixes..."
set +e
python3 -m pytest test_calculator.py -v --tb=no --no-header | sed -e 's/PASSED/\x1b[32mPASSED\x1b[0m/g' -e 's/FAILED/\x1b[31mFAILED\x1b[0m/g'
final_rc=$?
set -e
if [ $final_rc -eq 0 ]; then
ok "ALL TESTS PASS — Nova fixed the suite!"
echo
echo -e "${BOLD}Changes made:${NC}"
git --no-pager diff --stat || true
echo
echo -e "${BOLD}Branch:${NC}"
git branch --show-current | sed 's/^/ ➜ /'
else
warn "Some tests still failing — check iteration limits"
fi
fi
# Step 6: Summary
step 6 6 "Summary" "$SPARKLE"
echo -e "${BOLD}What we demonstrated:${NC}"
echo " ${CHECK} Real GitHub repository with failing tests"
echo " ${CHECK} GitHub Actions CI pipeline"
echo " ${CHECK} Nova automatically fixing tests in CI"
echo " ${CHECK} Pull Request created by Nova"
echo " ${CHECK} Safety limits enforced (≤5 files, ≤40 LOC)"
echo
thr
echo -e "${BOLD}${PURPLE} Key Safety Points${NC}"
hr
echo " ${CHECK} Branch isolation: nova/fix/* (never commits to main)"
echo " ${CHECK} Human review: PR flow for all changes"
echo " ${CHECK} Safety limits: ≤5 files, ≤40 LOC per change"
echo " ${CHECK} Iteration cap: --max-iters ${MAX_ITERS} prevents infinite loops"
echo " ${CHECK} Timeout protection: ${TIMEOUT_SEC}s max runtime"
echo
if [ "$SKIP_GITHUB" = false ]; then
echo -e "${DIM}Repository:${NC} ${BOLD}$REPO_URL${NC}"
echo -e "${DIM}GitHub Actions:${NC} ${BOLD}$REPO_URL/actions${NC}"
echo -e "${DIM}Pull Requests:${NC} ${BOLD}$REPO_URL/pulls${NC}"
else
echo -e "${DIM}Demo workspace:${NC} ${BOLD}$DEMO_DIR/$REPO_NAME${NC}"
fi
echo
echo -e "${DIM}To use Nova in your CI:${NC}"
echo " 1. Add the workflow file to .github/workflows/"
echo " 2. Set OPENAI_API_KEY as a repository secret"
echo " 3. Push failing tests and watch Nova fix them!"
}
########################################
# Entry Point
########################################
for c in python3 git; do
command -v "$c" >/dev/null 2>&1 || { echo "Error: $c is required." >&2; exit 1; }
done
# Cleanup function
cleanup() {
local exit_code=$?
if [ $exit_code -ne 0 ]; then
echo
echo -e "${YELLOW}Demo interrupted or failed${NC}"
fi
# Deactivate virtual environment if active
if [ -n "${VIRTUAL_ENV:-}" ]; then
deactivate 2>/dev/null || true
fi
echo -e "${DIM}Thank you for trying Nova CI-Rescue${NC}"
exit $exit_code
}
# Set trap for cleanup
trap cleanup EXIT INT TERM
# Run the demo
run_demo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment