ランブック

コマンドラインで Jira のスプリントレポートを生成する

ストーリーポイント、サイクルタイム、担当者ごとの内訳、完了状況の指標を含むスプリントデータを CSV に出力します。振り返りにそのまま使えます。

この処理の内容

このランブックでは、任意の Jira スプリントについて詳細な CSV レポートを生成します。スプリント内のすべての課題を取得し、サイクルタイム(作成から解決までの日数)を計算して、合計ストーリーポイント、完了率、課題タイプ別の内訳を含むサマリー統計を出力します。スプリント ID を指定しない場合は、現在アクティブなスプリントが対象になります。

前提条件

クイックスタート

# Report for a specific sprint
./sprint-report.sh --project DEV --sprint 42 --output "sprint-42.csv"

# Report for the current active sprint
./sprint-report.sh --project DEV

# Use a specific auth profile
./sprint-report.sh --project DEV --sprint 42 --profile prod

ランブックスクリプト全文

sprint-report.sh

#!/bin/bash
# Jira Sprint Report Generator
#
# Generates a CSV report for sprint issues with story points and cycle time metrics.
# Useful for retrospectives and velocity tracking.
#
# Usage:
#   ./sprint-report.sh --project PROJ --sprint 42 --output sprint-42.csv
#
# Output CSV columns:
#   - Issue Key, Summary, Type, Status, Story Points, Assignee,
#     Created, Resolved, Cycle Time (days)
#
# Requirements:
#   - atlassian-cli installed and configured
#   - jq for JSON processing

set -euo pipefail

# Configuration
PROJECT=""
SPRINT_ID=""
PROFILE="default"
OUTPUT_FILE="sprint_report_$(date +%Y%m%d).csv"

# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

log() {
    echo -e "${GREEN}[$(date +'%H:%M:%S')]${NC} $*"
}

warn() {
    echo -e "${YELLOW}[WARN]${NC} $*"
}

# Parse arguments
parse_args() {
    while [[ $# -gt 0 ]]; do
        case $1 in
            --project)
                PROJECT="$2"
                shift 2
                ;;
            --sprint)
                SPRINT_ID="$2"
                shift 2
                ;;
            --profile)
                PROFILE="$2"
                shift 2
                ;;
            --output)
                OUTPUT_FILE="$2"
                shift 2
                ;;
            *)
                echo "Unknown option: $1"
                exit 1
                ;;
        esac
    done

    if [ -z "$PROJECT" ]; then
        echo "Project key required (--project PROJECT)"
        exit 1
    fi
}

# Build JQL query
build_jql() {
    local jql="project = $PROJECT"

    if [ -n "$SPRINT_ID" ]; then
        jql="$jql AND Sprint = $SPRINT_ID"
    else
        # Get active sprint if no sprint specified
        jql="$jql AND Sprint in openSprints()"
    fi

    echo "$jql"
}

# Calculate cycle time in days
calculate_cycle_time() {
    local created="$1"
    local resolved="$2"

    if [ -z "$resolved" ] || [ "$resolved" = "null" ]; then
        echo "N/A"
        return
    fi

    # Convert to timestamps (simplified - may need date parsing)
    local created_ts
    created_ts=$(date -d "$created" +%s 2>/dev/null || echo "0")
    local resolved_ts
    resolved_ts=$(date -d "$resolved" +%s 2>/dev/null || echo "0")

    if [ "$created_ts" -eq 0 ] || [ "$resolved_ts" -eq 0 ]; then
        echo "N/A"
        return
    fi

    local diff_days
    diff_days=$(( (resolved_ts - created_ts) / 86400 ))

    echo "$diff_days"
}

# Fetch sprint issues
fetch_issues() {
    local jql="$1"

    log "Fetching sprint issues..."
    log "JQL: $jql"

    atlassian-cli jira issue search \
        --profile "$PROFILE" \
        --jql "$jql" \
        --output json
}

# Generate CSV report
generate_report() {
    local issues="$1"

    log "Generating report: $OUTPUT_FILE"

    # Write CSV header
    echo "Issue Key,Summary,Type,Status,Story Points,Assignee,Created,Resolved,Cycle Time (days)" > "$OUTPUT_FILE"

    local total
    total=$(echo "$issues" | jq '. | length')

    if [ "$total" -eq 0 ]; then
        warn "No issues found"
        return
    fi

    log "Processing $total issues..."

    # Process each issue
    echo "$issues" | jq -r '.[] | @json' | while IFS= read -r issue_json; do
        local key
        key=$(echo "$issue_json" | jq -r '.key')
        local summary
        summary=$(echo "$issue_json" | jq -r '.fields.summary' | sed 's/"/""/g')
        local issue_type
        issue_type=$(echo "$issue_json" | jq -r '.fields.issuetype.name')
        local status
        status=$(echo "$issue_json" | jq -r '.fields.status.name')
        local story_points
        story_points=$(echo "$issue_json" | jq -r '.fields.customfield_10016 // "N/A"')
        local assignee
        assignee=$(echo "$issue_json" | jq -r '.fields.assignee.displayName // "Unassigned"')
        local created
        created=$(echo "$issue_json" | jq -r '.fields.created')
        local resolved
        resolved=$(echo "$issue_json" | jq -r '.fields.resolutiondate // "null"')

        # Calculate cycle time
        local cycle_time
        cycle_time=$(calculate_cycle_time "$created" "$resolved")

        # Write CSV row
        echo "\"$key\",\"$summary\",\"$issue_type\",\"$status\",$story_points,\"$assignee\",\"$created\",\"$resolved\",$cycle_time" >> "$OUTPUT_FILE"
    done
}

# Generate summary statistics
generate_summary() {
    log "Generating summary statistics"

    local total_issues
    total_issues=$(tail -n +2 "$OUTPUT_FILE" | wc -l | tr -d ' ')

    local total_points
    total_points=$(tail -n +2 "$OUTPUT_FILE" | cut -d',' -f5 | \
        grep -v "N/A" | awk '{sum+=$1} END {print sum+0}')

    local completed_issues
    completed_issues=$(tail -n +2 "$OUTPUT_FILE" | cut -d',' -f4 | \
        grep -i "done\|resolved\|closed" | wc -l | tr -d ' ')

    local avg_cycle_time
    avg_cycle_time=$(tail -n +2 "$OUTPUT_FILE" | cut -d',' -f9 | \
        grep -v "N/A" | awk '{sum+=$1; count++} END {if(count>0) print int(sum/count); else print 0}')

    echo ""
    log "Sprint Summary:"
    echo "  Total Issues: $total_issues"
    echo "  Completed: $completed_issues"
    echo "  Total Story Points: $total_points"
    echo "  Avg Cycle Time: $avg_cycle_time days"
    echo ""

    # Issue breakdown by type
    log "Issues by Type:"
    tail -n +2 "$OUTPUT_FILE" | cut -d',' -f3 | \
        sed 's/"//g' | sort | uniq -c | \
        awk '{printf "  %s: %d\n", $2, $1}'

    echo ""
}

# Main execution
main() {
    parse_args "$@"

    log "Starting sprint report generation"
    log "Project: $PROJECT | Profile: $PROFILE"

    local jql
    jql=$(build_jql)

    local issues
    issues=$(fetch_issues "$jql")

    generate_report "$issues"
    generate_summary

    log "Report saved to: $OUTPUT_FILE"
}

main "$@"

仕組み

1

対象スプリントを指定する。--project と、必要に応じてスプリント ID を指定した --sprint を渡します。スプリントを指定しない場合、スクリプトは JQL の openSprints() 関数を使って現在アクティブなスプリントを自動的に対象にします。

2

スプリントの課題をすべて取得する。CLI の jira issue search コマンドが、スプリント内のすべての課題を JSON として取得します。ストーリーポイント(customfield_10016)、担当者、ステータス、解決日などのフィールドも含まれます。

3

サイクルタイムを計算する。解決済みの課題ごとに、作成から解決までの日数を計算します。未解決の課題は N/A と記録されます。

4

CSV レポートを書き出す。各課題が出力 CSV の 1 行になり、列は Issue Key、Summary、Type、Status、Story Points、Assignee、Created、Resolved、Cycle Time です。ファイル名にはデフォルトで当日の日付が入ります。

5

サマリー統計を表示する。CSV の生成後、スクリプトはコンソールにサマリーを出力します。課題の総数、完了数、合計ストーリーポイント、平均サイクルタイム、課題タイプ別(Bug、Story、Task など)の内訳が含まれます。

関連ランブック

コピーしました