⏱️ Estimated reading time: 25 min

Series Introduction

This post is Part 2 of the macOS GitHub CLI Complete Automation Series. Building on the environment established in Part 1, it covers how to fully automate GitHub issue management.

GitHub issues go far beyond simple bug tracking - they are the central axis for managing every task in a project. In this part, we will build a professional-grade system that automates the entire process: intelligent issue creation, automatic classification, dynamic labeling, and sprint planning automation.

Part 2: Full Issue Management Automation

Goals

  • Build an intelligent issue creation and classification system
  • Implement automatic labeling and assignee allocation mechanisms
  • Create a dynamic issue template generation system
  • Manage issue status through workflow-based automation
  • Automate sprint planning and backlog management

Intelligent Issue Creation System

1. AI-Based Issue Classifier

# Issue classification and automatic labeling system
cat > ~/scripts/github-cli/issue/create.sh << 'EOF'
#!/bin/bash

# Intelligent issue creation system
# Usage: smart-issue-creator.sh <title> [description] [priority]

TITLE="$1"
DESCRIPTION="$2"
PRIORITY="${3:-medium}"

if [[ -z "$TITLE" ]]; then
    echo "Usage: smart-issue-creator.sh <title> [description] [priority:low|medium|high|critical]"
    exit 1
fi

# Keyword-based automatic classification
function classify_issue() {
    local title_lower=$(echo "$TITLE" | tr '[:upper:]' '[:lower:]')
    local desc_lower=$(echo "$DESCRIPTION" | tr '[:upper:]' '[:lower:]')
    local combined="$title_lower $desc_lower"
    
    # Bug-related keywords
    if echo "$combined" | grep -E "(bug|error|crash|fail|broken|fix|issue)" >/dev/null; then
        echo "bug"
    # Feature enhancement keywords
    elif echo "$combined" | grep -E "(feature|enhance|improve|add|new|implement)" >/dev/null; then
        echo "enhancement"
    # Documentation-related keywords
    elif echo "$combined" | grep -E "(doc|readme|wiki|guide|manual)" >/dev/null; then
        echo "documentation"
    # Performance-related keywords
    elif echo "$combined" | grep -E "(performance|slow|speed|optimize|memory|cpu)" >/dev/null; then
        echo "performance"
    # Security-related keywords
    elif echo "$combined" | grep -E "(security|vulnerable|exploit|auth|permission)" >/dev/null; then
        echo "security"
    # Testing-related keywords
    elif echo "$combined" | grep -E "(test|testing|spec|coverage|unit|integration)" >/dev/null; then
        echo "testing"
    else
        echo "general"
    fi
}

# Set label color by priority
function get_priority_color() {
    case "$1" in
        "critical") echo "b60205" ;;
        "high") echo "d93f0b" ;;
        "medium") echo "fbca04" ;;
        "low") echo "0e8a16" ;;
        *) echo "fbca04" ;;
    esac
}

# Automatic assignee allocation
function auto_assign() {
    local issue_type="$1"
    local context=$(cat ~/.config/gh/current_context 2>/dev/null || echo 'personal')
    
    # Assign team members for work projects
    if [[ "$context" == "work" ]]; then
        case "$issue_type" in
            "bug"|"performance") echo "@backend-team" ;;
            "enhancement") echo "@frontend-team" ;;
            "documentation") echo "@tech-writer" ;;
            "security") echo "@security-team" ;;
            "testing") echo "@qa-team" ;;
            *) echo "@dev-team" ;;
        esac
    else
        echo "@me"
    fi
}

# Execute issue creation
ISSUE_TYPE=$(classify_issue)
ASSIGNEE=$(auto_assign "$ISSUE_TYPE")
PRIORITY_COLOR=$(get_priority_color "$PRIORITY")

# Create labels if they do not exist
gh label create "$ISSUE_TYPE" --color "1d76db" --description "Auto-classified as $ISSUE_TYPE" 2>/dev/null || true
gh label create "priority:$PRIORITY" --color "$PRIORITY_COLOR" --description "$PRIORITY priority issue" 2>/dev/null || true

# Generate detailed issue body
ISSUE_BODY="## Issue Information

**Classification**: $ISSUE_TYPE
**Priority**: $PRIORITY
**Auto-assigned**: $ASSIGNEE

## Description

${DESCRIPTION:-Please write a detailed description of the issue.}

## Details

### Steps to Reproduce (for bugs)
1. 
2. 
3. 

### Expected Result


### Actual Result


### Environment
- OS: $(uname -s)
- Browser: 
- Version: 

## Acceptance Criteria

- [ ] 

## Related Issues


---
*This issue was automatically classified. If the classification is incorrect, please update the labels.*"

# Create the issue
CREATED_ISSUE=$(gh issue create \
    --title "$TITLE" \
    --body "$ISSUE_BODY" \
    --label "$ISSUE_TYPE,priority:$PRIORITY" \
    --assignee "$ASSIGNEE" \
    --format json)

ISSUE_NUMBER=$(echo "$CREATED_ISSUE" | jq -r '.number')
ISSUE_URL=$(echo "$CREATED_ISSUE" | jq -r '.url')

echo "Intelligent issue created!"
echo "#$ISSUE_NUMBER: $TITLE"
echo "Classification: $ISSUE_TYPE (Priority: $PRIORITY)"
echo "Assignee: $ASSIGNEE"
echo "$ISSUE_URL"

# Check whether to start work immediately
if [[ "$ASSIGNEE" == "@me" ]]; then
    read -p "Would you like to start working on this now? (y/N): " start_work
    if [[ "$start_work" =~ ^[Yy]$ ]]; then
        # Call the issue_start function created in Part 1
        issue_start "$ISSUE_NUMBER"
    fi
fi
EOF

chmod +x ~/scripts/github-cli/issue/create.sh

2. Dynamic Issue Template Generator

# Dynamic issue template generation system
cat > ~/scripts/github-cli/issue/template-generator.sh << 'EOF'
#!/bin/bash

# Automatically generate issue templates by project type
# Usage: template-generator.sh [project-type]

PROJECT_TYPE="${1:-general}"

# Detect project type
function detect_project_type() {
    if [[ -f "package.json" ]]; then
        echo "javascript"
    elif [[ -f "requirements.txt" ]] || [[ -f "pyproject.toml" ]]; then
        echo "python"
    elif [[ -f "Gemfile" ]]; then
        echo "ruby"
    elif [[ -f "go.mod" ]]; then
        echo "go"
    elif [[ -f "Cargo.toml" ]]; then
        echo "rust"
    elif [[ -f "pom.xml" ]] || [[ -f "build.gradle" ]]; then
        echo "java"
    else
        echo "general"
    fi
}

[[ "$PROJECT_TYPE" == "general" ]] && PROJECT_TYPE=$(detect_project_type)

mkdir -p .github/ISSUE_TEMPLATE

# Bug report template by project type
case "$PROJECT_TYPE" in
    "javascript"|"typescript")
        cat > .github/ISSUE_TEMPLATE/bug_report.yml << 'JSEOF'
name: 🐛 Bug Report
description: Report a bug in the application
title: "[Bug]: "
labels: ["bug", "needs-triage"]
body:
  - type: markdown
    attributes:
      value: |
        Thanks for reporting this bug! Please provide as much detail as possible.
  
  - type: textarea
    id: description
    attributes:
      label: Bug Description
      description: A clear description of what the bug is
      placeholder: Describe the bug...
    validations:
      required: true
      
  - type: textarea
    id: steps
    attributes:
      label: Steps to Reproduce
      description: Steps to reproduce the behavior
      placeholder: |
        1. Go to '...'
        2. Click on '....'
        3. Scroll down to '....'
        4. See error
    validations:
      required: true
      
  - type: textarea
    id: expected
    attributes:
      label: Expected Behavior
      description: What you expected to happen
    validations:
      required: true
      
  - type: dropdown
    id: browsers
    attributes:
      label: Browser
      description: Which browser(s) are you seeing the problem on?
      multiple: true
      options:
        - Chrome
        - Firefox
        - Safari
        - Edge
        - Other
    validations:
      required: true
      
  - type: input
    id: node-version
    attributes:
      label: Node.js Version
      description: What version of Node.js are you running?
      placeholder: "v18.17.0"
    validations:
      required: true
      
  - type: textarea
    id: additional
    attributes:
      label: Additional Context
      description: Add any other context about the problem here
JSEOF
        ;;
        
    "python")
        cat > .github/ISSUE_TEMPLATE/bug_report.yml << 'PYEOF'
name: 🐛 Bug Report  
description: Report a bug in the Python application
title: "[Bug]: "
labels: ["bug", "needs-triage"]
body:
  - type: textarea
    id: description
    attributes:
      label: Bug Description
      description: A clear description of what the bug is
    validations:
      required: true
      
  - type: textarea
    id: traceback
    attributes:
      label: Error Traceback
      description: If applicable, paste the full error traceback
      render: python
      
  - type: input
    id: python-version
    attributes:
      label: Python Version
      description: What version of Python are you using?
      placeholder: "3.11.0"
    validations:
      required: true
      
  - type: textarea
    id: environment
    attributes:
      label: Environment
      description: List relevant package versions
      placeholder: |
        - Django: 4.2.0
        - requests: 2.28.2
        - etc.
PYEOF
        ;;
esac

# Common feature request template
cat > .github/ISSUE_TEMPLATE/feature_request.yml << 'FEATEOF'
name: 🚀 Feature Request
description: Suggest a new feature or improvement
title: "[Feature]: "
labels: ["enhancement", "needs-discussion"]
body:
  - type: textarea
    id: problem
    attributes:
      label: Problem Statement
      description: What problem does this feature solve?
      placeholder: "I'm frustrated when..."
    validations:
      required: true
      
  - type: textarea
    id: solution
    attributes:
      label: Proposed Solution
      description: What would you like to happen?
    validations:
      required: true
      
  - type: textarea
    id: alternatives
    attributes:
      label: Alternatives Considered
      description: Any alternative solutions you've considered?
      
  - type: dropdown
    id: priority
    attributes:
      label: Priority
      description: How important is this feature?
      options:
        - Low
        - Medium  
        - High
        - Critical
    validations:
      required: true
      
  - type: checkboxes
    id: implementation
    attributes:
      label: Implementation Willingness
      description: Are you willing to help implement this feature?
      options:
        - label: I can help with implementation
        - label: I can help with testing
        - label: I can help with documentation
FEATEOF

echo "Issue templates for $PROJECT_TYPE project created!"
echo "Check the .github/ISSUE_TEMPLATE/ directory."
EOF

chmod +x ~/scripts/github-cli/issue/template-generator.sh

Issue Workflow Automation

1. Status-Based Automatic Management

# Create issue workflow automation script
cat > ~/scripts/github-cli/issue/workflow.sh << 'EOF'
#!/bin/bash

# Issue workflow automation functions

# Change issue status and trigger automatic actions
function issue_status() {
    local issue_num="$1"
    local status="$2"
    
    if [[ -z "$issue_num" || -z "$status" ]]; then
        echo "Usage: issue_status <issue-number> <status>"
        echo "Status: todo, in-progress, review, testing, done"
        return 1
    fi
    
    case "$status" in
        "todo")
            gh issue edit "$issue_num" \
                --remove-label "in-progress,review,testing" \
                --add-label "todo" \
                --milestone ""
            gh issue comment "$issue_num" --body "Issue moved to TODO status."
            ;;
            
        "in-progress") 
            gh issue edit "$issue_num" \
                --remove-label "todo,review,testing" \
                --add-label "in-progress" \
                --assignee "@me"
            gh issue comment "$issue_num" --body "Work started. Assignee: $(gh api user -q .login)"
            
            # Automatically create a branch
            issue_start "$issue_num"
            ;;
            
        "review")
            gh issue edit "$issue_num" \
                --remove-label "todo,in-progress,testing" \
                --add-label "review"
            
            # If a PR exists, automatically request review
            local pr_number=$(gh pr list --search "closes:#$issue_num" --json number -q '.[0].number')
            if [[ -n "$pr_number" && "$pr_number" != "null" ]]; then
                gh pr ready "$pr_number"
                gh pr edit "$pr_number" --add-reviewer "@team-leads"
                gh issue comment "$issue_num" --body "Code review requested. PR #$pr_number"
            fi
            ;;
            
        "testing")
            gh issue edit "$issue_num" \
                --remove-label "todo,in-progress,review" \
                --add-label "testing"
            gh issue comment "$issue_num" --body "In testing phase. Please check with the QA team."
            ;;
            
        "done")
            gh issue close "$issue_num"
            gh issue comment "$issue_num" --body "Issue completed. Thank you everyone who worked on this!"
            
            # Clean up related branch
            local current_branch=$(git branch --show-current)
            if [[ "$current_branch" == *"issue-$issue_num"* ]]; then
                git checkout main
                git branch -d "$current_branch" 2>/dev/null || true
                echo "Branch '$current_branch' cleaned up."
            fi
            ;;
            
        *)
            echo "Unsupported status."
            echo "Available statuses: todo, in-progress, review, testing, done"
            return 1
            ;;
    esac
    
    echo "Issue #$issue_num status changed to '$status'."
}

# Bulk issue status change
function bulk_issue_status() {
    local status="$1"
    shift
    local issues=("$@")
    
    if [[ -z "$status" || ${#issues[@]} -eq 0 ]]; then
        echo "Usage: bulk_issue_status <status> <issue1> <issue2> ..."
        return 1
    fi
    
    echo "Changing status of ${#issues[@]} issues to '$status'..."
    
    for issue in "${issues[@]}"; do
        echo "Processing: #$issue"
        issue_status "$issue" "$status"
        sleep 1  # Avoid API rate limits
    done
    
    echo "All issue status changes complete."
}

# Automatic priority adjustment
function auto_prioritize() {
    local issue_num="$1"
    
    if [[ -z "$issue_num" ]]; then
        echo "Usage: auto_prioritize <issue-number>"
        return 1
    fi
    
    # Fetch issue information
    local issue_info=$(gh issue view "$issue_num" --json labels,comments,reactions,createdAt)
    local labels=$(echo "$issue_info" | jq -r '.labels[].name' | tr '\n' ' ')
    local comment_count=$(echo "$issue_info" | jq '.comments | length')
    local reaction_count=$(echo "$issue_info" | jq '.reactions.totalCount')
    local created_days_ago=$(( ($(date +%s) - $(date -d "$(echo "$issue_info" | jq -r '.createdAt')" +%s)) / 86400 ))
    
    local priority="medium"
    
    # Priority calculation logic
    if echo "$labels" | grep -q "bug"; then
        if echo "$labels" | grep -q "critical\|security"; then
            priority="critical"
        elif [[ $reaction_count -gt 5 || $comment_count -gt 10 ]]; then
            priority="high"
        elif [[ $created_days_ago -gt 7 ]]; then
            priority="high"
        else
            priority="medium"
        fi
    elif echo "$labels" | grep -q "enhancement"; then
        if [[ $reaction_count -gt 10 || $comment_count -gt 15 ]]; then
            priority="high"
        elif [[ $created_days_ago -gt 30 ]]; then
            priority="low"
        fi
    fi
    
    # Remove existing priority labels and set new priority
    gh issue edit "$issue_num" \
        --remove-label "priority:low,priority:medium,priority:high,priority:critical" \
        --add-label "priority:$priority"
    
    echo "Issue #$issue_num priority adjusted to '$priority'."
    echo "Analysis: $comment_count comments, $reaction_count reactions, created ${created_days_ago} days ago"
}
EOF

chmod +x ~/scripts/github-cli/issue/workflow.sh

# Add script loading to .zshrc
cat >> ~/.zshrc << 'EOF'

# Load issue management script
source ~/scripts/github-cli/issue/workflow.sh
EOF

source ~/.zshrc

2. Sprint Planning Automation

# Sprint management system
cat > ~/scripts/github-cli/issue/sprint-manager.sh << 'EOF'
#!/bin/bash

# Sprint management automation system
# Usage: sprint-manager.sh <command> [options]

COMMAND="$1"
SPRINT_NAME="$2"
DURATION="${3:-14}"  # Default 2 weeks

case "$COMMAND" in
    "create")
        if [[ -z "$SPRINT_NAME" ]]; then
            echo "Usage: sprint-manager.sh create <sprint-name> [duration-days]"
            exit 1
        fi
        
        # Create sprint milestone
        START_DATE=$(date +%Y-%m-%d)
        END_DATE=$(date -d "+${DURATION} days" +%Y-%m-%d)
        
        gh milestone create "$SPRINT_NAME" \
            --description "Sprint period: $START_DATE to $END_DATE" \
            --due-date "$END_DATE"
        
        echo "Sprint '$SPRINT_NAME' created."
        echo "Period: $START_DATE to $END_DATE"
        
        # Automatically assign issues from backlog
        echo "Automatically assigning issues from backlog..."
        
        # Add high-priority issues to the sprint
        gh issue list --label "priority:high" --state open --limit 5 --json number | \
            jq -r '.[] | .number' | while read issue_num; do
            gh issue edit "$issue_num" --milestone "$SPRINT_NAME"
            echo "  Issue #$issue_num added to sprint."
        done
        ;;
        
    "status")
        if [[ -z "$SPRINT_NAME" ]]; then
            echo "Usage: sprint-manager.sh status <sprint-name>"
            exit 1
        fi
        
        echo "Sprint '$SPRINT_NAME' Status"
        echo "================================"
        
        # Total issue count
        TOTAL_ISSUES=$(gh issue list --milestone "$SPRINT_NAME" --json number | jq length)
        CLOSED_ISSUES=$(gh issue list --milestone "$SPRINT_NAME" --state closed --json number | jq length)
        OPEN_ISSUES=$((TOTAL_ISSUES - CLOSED_ISSUES))
        
        echo "Progress: $CLOSED_ISSUES/$TOTAL_ISSUES ($(( CLOSED_ISSUES * 100 / TOTAL_ISSUES ))%)"
        echo
        
        echo "Issues by status:"
        echo "  Open issues: $OPEN_ISSUES"
        echo "  Completed issues: $CLOSED_ISSUES"
        echo
        
        echo "In-progress issues:"
        gh issue list --milestone "$SPRINT_NAME" --state open --json number,title,assignees | \
            jq -r '.[] | "  #\(.number): \(.title) (\(.assignees[0].login // "unassigned"))"'
        ;;
        
    "burndown")
        if [[ -z "$SPRINT_NAME" ]]; then
            echo "Usage: sprint-manager.sh burndown <sprint-name>"
            exit 1
        fi
        
        # Generate burndown chart data
        BURNDOWN_FILE="$HOME/Documents/github-automation/burndown-$SPRINT_NAME.csv"
        
        echo "date,remaining_issues" > "$BURNDOWN_FILE"
        
        # Generate data for the last 14 days
        for i in $(seq 0 13); do
            DATE=$(date -d "-$i days" +%Y-%m-%d)
            REMAINING=$(gh issue list --milestone "$SPRINT_NAME" --search "created:>=$DATE" --json number | jq length)
            echo "$DATE,$REMAINING" >> "$BURNDOWN_FILE"
        done
        
        echo "Burndown chart data generated: $BURNDOWN_FILE"
        ;;
        
    "close")
        if [[ -z "$SPRINT_NAME" ]]; then
            echo "Usage: sprint-manager.sh close <sprint-name>"
            exit 1
        fi
        
        echo "Closing sprint '$SPRINT_NAME'..."
        
        # Move incomplete issues to the next sprint
        OPEN_ISSUES=$(gh issue list --milestone "$SPRINT_NAME" --state open --json number,title)
        OPEN_COUNT=$(echo "$OPEN_ISSUES" | jq length)
        
        if [[ $OPEN_COUNT -gt 0 ]]; then
            echo "$OPEN_COUNT incomplete issues remain."
            read -p "Enter next sprint name (or press Enter to move to backlog): " NEXT_SPRINT
            
            echo "$OPEN_ISSUES" | jq -r '.[] | .number' | while read issue_num; do
                if [[ -n "$NEXT_SPRINT" ]]; then
                    gh issue edit "$issue_num" --milestone "$NEXT_SPRINT"
                    echo "  Issue #$issue_num moved to '$NEXT_SPRINT'."
                else
                    gh issue edit "$issue_num" --milestone ""
                    echo "  Issue #$issue_num moved to backlog."
                fi
            done
        fi
        
        # Generate sprint report
        REPORT_FILE="$HOME/Documents/github-automation/sprint-report-$SPRINT_NAME.md"
        
        cat > "$REPORT_FILE" << REPORTEOF
# Sprint '$SPRINT_NAME' Completion Report

## Summary
- Total issues: $(gh issue list --milestone "$SPRINT_NAME" --json number | jq length)
- Completed issues: $(gh issue list --milestone "$SPRINT_NAME" --state closed --json number | jq length)
- Incomplete issues: $OPEN_COUNT

## Completed Issues
$(gh issue list --milestone "$SPRINT_NAME" --state closed --json number,title | jq -r '.[] | "- [#\(.number)](\(.html_url)) \(.title)"')

## Incomplete Issues
$(gh issue list --milestone "$SPRINT_NAME" --state open --json number,title | jq -r '.[] | "- [#\(.number)](\(.html_url)) \(.title)"')

---
*Report generated: $(date)*
REPORTEOF
        
        echo "Sprint completion report: $REPORT_FILE"
        
        # Close milestone
        gh milestone edit "$SPRINT_NAME" --state closed
        echo "Sprint '$SPRINT_NAME' closed."
        ;;
        
    *)
        echo "GitHub Sprint Management System"
        echo "Usage: sprint-manager.sh <command> [options]"
        echo
        echo "Commands:"
        echo "  create <sprint-name> [duration]  - Create a new sprint"
        echo "  status <sprint-name>              - View sprint status"
        echo "  burndown <sprint-name>            - Generate burndown chart data"
        echo "  close <sprint-name>               - Close and wrap up sprint"
        ;;
esac
EOF

chmod +x ~/scripts/github-cli/issue/sprint-manager.sh

Advanced Issue Analysis and Insights

1. Issue Analytics Dashboard

# Issue analysis and insights generation script
cat > ~/scripts/github-cli/issue/analytics.sh << 'EOF'
#!/bin/bash

# Issue analytics dashboard
function issue_analytics() {
    local period="${1:-30}"  # Default 30 days
    
    echo "GitHub Issue Analytics Dashboard (Last ${period} days)"
    echo "=================================================="
    echo
    
    # Basic statistics
    echo "Basic Statistics:"
    local total_issues=$(gh issue list --search "created:>=$(date -d "-${period} days" +%Y-%m-%d)" --json number | jq length)
    local closed_issues=$(gh issue list --search "created:>=$(date -d "-${period} days" +%Y-%m-%d) is:closed" --json number | jq length)
    local bug_issues=$(gh issue list --search "created:>=$(date -d "-${period} days" +%Y-%m-%d) label:bug" --json number | jq length)
    
    echo "  Total issues created: $total_issues"
    echo "  Completed issues: $closed_issues ($(( closed_issues * 100 / total_issues ))%)"
    echo "  Bug issues: $bug_issues"
    echo
    
    # Analysis by label
    echo "Analysis by label:"
    gh issue list --search "created:>=$(date -d "-${period} days" +%Y-%m-%d)" --json labels | \
        jq -r '.[] | .labels[].name' | sort | uniq -c | sort -nr | head -10 | \
        while read count label; do
            echo "  $label: $count"
        done
    echo
    
    # Analysis by assignee
    echo "Analysis by assignee:"
    gh issue list --search "created:>=$(date -d "-${period} days" +%Y-%m-%d)" --json assignees | \
        jq -r '.[] | .assignees[]?.login' | sort | uniq -c | sort -nr | head -5 | \
        while read count assignee; do
            echo "  $assignee: $count"
        done
    echo
    
    # Open issues by priority
    echo "Open issues by priority:"
    for priority in critical high medium low; do
        local count=$(gh issue list --label "priority:$priority" --state open --json number | jq length)
        echo "  $priority: $count"
    done
    echo
    
    # Long-standing open issues
    echo "Long-standing open issues (30+ days):"
    gh issue list --search "created:<$(date -d "-30 days" +%Y-%m-%d) is:open" --limit 5 --json number,title,createdAt | \
        jq -r '.[] | "  #\(.number): \(.title) (created: \(.createdAt | split("T")[0]))"'
}

# Issue health check
function issue_health_check() {
    echo "Issue Health Check"
    echo "==================="
    echo
    
    local warnings=0
    
    # Check for unassigned issues
    local unassigned=$(gh issue list --search "is:open no:assignee" --json number | jq length)
    if [[ $unassigned -gt 5 ]]; then
        echo "Too many unassigned issues: ${unassigned}"
        warnings=$((warnings + 1))
    fi
    
    # Check for unlabeled issues
    local unlabeled=$(gh issue list --search "is:open no:label" --json number | jq length)
    if [[ $unlabeled -gt 3 ]]; then
        echo "Issues without labels: ${unlabeled}"
        warnings=$((warnings + 1))
    fi
    
    # Check for stale issues
    local stale_issues=$(gh issue list --search "is:open created:<$(date -d "-60 days" +%Y-%m-%d)" --json number | jq length)
    if [[ $stale_issues -gt 10 ]]; then
        echo "Many issues are 60+ days old: ${stale_issues}"
        warnings=$((warnings + 1))
    fi
    
    # Check for high-priority issues
    local high_priority=$(gh issue list --label "priority:high,priority:critical" --state open --json number | jq length)
    if [[ $high_priority -gt 5 ]]; then
        echo "High-priority issues are accumulating: ${high_priority}"
        warnings=$((warnings + 1))
    fi
    
    if [[ $warnings -eq 0 ]]; then
        echo "Issue management is in good shape!"
    else
        echo
        echo "Improvement suggestions:"
        echo "  - Assign owners to unassigned issues"
        echo "  - Classify issues without labels"
        echo "  - Review and clean up old issues"
        echo "  - Prioritize high-priority issues"
    fi
}
EOF

chmod +x ~/scripts/github-cli/issue/analytics.sh

# Add analytics script loading to .zshrc
cat >> ~/.zshrc << 'EOF'

# Load issue analytics script
source ~/scripts/github-cli/issue/analytics.sh
EOF

source ~/.zshrc

2. Automatic Notification System

# Daily issue notification system
cat > ~/scripts/github-cli/system/daily-issue-alert.sh << 'EOF'
#!/bin/bash

# Daily issue status notification system
# Run daily as a cron job: 0 9 * * * ~/scripts/github-cli/system/daily-issue-alert.sh

ALERT_FILE="$HOME/Documents/github-automation/daily-alert-$(date +%Y-%m-%d).md"

cat > "$ALERT_FILE" << 'ALERTHEADER'
# Daily Issue Alert

## Urgent Alerts
ALERTHEADER

# Check for critical issues
CRITICAL_ISSUES=$(gh issue list --label "priority:critical" --state open --json number,title,createdAt)
CRITICAL_COUNT=$(echo "$CRITICAL_ISSUES" | jq length)

if [[ $CRITICAL_COUNT -gt 0 ]]; then
    echo "**CRITICAL priority issues unresolved: ${CRITICAL_COUNT}**" >> "$ALERT_FILE"
    echo "$CRITICAL_ISSUES" | jq -r '.[] | "- [#\(.number)](\(.html_url)) \(.title)"' >> "$ALERT_FILE"
else
    echo "No critical issues." >> "$ALERT_FILE"
fi

echo "" >> "$ALERT_FILE"

# Long-standing open issues
echo "## Long-standing open issues (7+ days)" >> "$ALERT_FILE"
STALE_ISSUES=$(gh issue list --search "is:open created:<$(date -d "-7 days" +%Y-%m-%d)" --limit 10 --json number,title,createdAt)
STALE_COUNT=$(echo "$STALE_ISSUES" | jq length)

if [[ $STALE_COUNT -gt 0 ]]; then
    echo "$STALE_ISSUES" | jq -r '.[] | "- [#\(.number)](\(.html_url)) \(.title) (created: \(.createdAt | split("T")[0]))"' >> "$ALERT_FILE"
else
    echo "No long-standing open issues." >> "$ALERT_FILE"
fi

echo "" >> "$ALERT_FILE"

# Today's tasks
echo "## Today's Tasks" >> "$ALERT_FILE"
TODAY_ISSUES=$(gh issue list --assignee @me --state open --limit 5 --json number,title)
TODAY_COUNT=$(echo "$TODAY_ISSUES" | jq length)

if [[ $TODAY_COUNT -gt 0 ]]; then
    echo "$TODAY_ISSUES" | jq -r '.[] | "- [ ] [#\(.number)](\(.html_url)) \(.title)"' >> "$ALERT_FILE"
else
    echo "No assigned issues!" >> "$ALERT_FILE"
fi

# Print summary to terminal
echo "Daily issue alert generated: $ALERT_FILE"
if [[ $CRITICAL_COUNT -gt 0 ]]; then
    echo "CRITICAL issues require attention: $CRITICAL_COUNT"
fi
if [[ $STALE_COUNT -gt 5 ]]; then
    echo "Long-standing issues need cleanup: $STALE_COUNT"
fi

# Optional: send via Slack or email
# slack-alert.sh "$ALERT_FILE" 2>/dev/null || true
EOF

chmod +x ~/scripts/github-cli/system/daily-issue-alert.sh

What’s Next

The next part, Project Management + Company/Personal Project Separation, will cover:

  • Full automation of GitHub Projects v2
  • Dynamic kanban board management
  • Separated workflows for company and personal projects
  • Team collaboration automation systems
  • Project metrics and reporting