GitHub Issues

プロジェクト管理チケット管理課題追跡Gitオープンソース開発統合

プロジェクト管理ツール

GitHub Issues

概要

GitHub IssuesはGitHubに統合されたイシュー追跡システムです。プルリクエスト、プロジェクトボード、マイルストーンと連携し、開発ワークフローに直接統合されたバグ・機能要求管理を提供します。オープンソースプロジェクトのデファクトスタンダードとして広く使用されており、GitHub Actionsとの連携により、CI/CDパイプラインと密接に統合できます。

詳細

GitHub IssuesはGitリポジトリと完全に統合されており、コード変更と課題管理をシームレスに結びつけます。Issue、Pull Request、Project Boardが相互に連携し、開発者にとって最も馴染み深いワークフローを提供します。

主な特徴

  • Git統合: コミット、ブランチ、プルリクエストとの自動連携
  • プロジェクトボード: カンバンスタイルの視覚的プロジェクト管理
  • マイルストーン: リリース管理と進捗追跡
  • ラベルシステム: 柔軟なカテゴリ分類とフィルタリング
  • テンプレート: 一貫性のあるIssue・PRの作成
  • メンション機能: チームメンバーとのコミュニケーション促進
  • GitHub Actions統合: 自動化とCI/CDとの連携
  • REST/GraphQL API: 豊富な自動化とカスタマイズオプション

対象プロジェクト

  • オープンソースプロジェクト
  • GitHubホスティングのソフトウェア開発
  • アジャイル開発チーム
  • 小〜中規模の開発プロジェクト

メリット・デメリット

メリット

  • GitHubエコシステムとの完全統合
  • オープンソースプロジェクトでの標準的な使用
  • 無料で基本機能をすべて利用可能
  • 開発者にとって学習コストが低い
  • 強力なAPI・Webhook・GitHub Actions連携
  • マークダウン対応で技術文書の記述が容易

デメリット

  • 複雑なプロジェクト管理機能が不足
  • 非技術者には使いにくいインターフェース
  • 時間追跡やリソース管理機能がない
  • カスタムフィールドの制限
  • エンタープライズ向け機能が限定的
  • Gitリポジトリが必要(スタンドアロン使用不可)

参考ページ

書き方の例

基本セットアップ

# GitHub CLIのインストール
# macOS
brew install gh

# Windows
winget install GitHub.cli

# 認証
gh auth login

# リポジトリのクローン
gh repo clone owner/repo
cd repo

# Issueの作成
gh issue create --title "バグ修正" --body "詳細な説明"

プロジェクト作成

# プロジェクトボードの作成(GitHub CLI)
gh project create --title "Sprint 1" --body "第1スプリントの進捗管理"

# Issueテンプレートの作成
mkdir -p .github/ISSUE_TEMPLATE
cat > .github/ISSUE_TEMPLATE/bug_report.yml << 'EOF'
name: Bug Report
description: バグレポートの提出
title: "[Bug]: "
labels: ["bug", "triage"]
body:
  - type: markdown
    attributes:
      value: |
        バグレポートをありがとうございます!
  - type: input
    id: contact
    attributes:
      label: 連絡先
      description: 追加情報が必要な場合の連絡先
      placeholder: ex. [email protected]
    validations:
      required: false
  - type: textarea
    id: what-happened
    attributes:
      label: 何が起こりましたか?
      description: バグの詳細を教えてください
      placeholder: バグの詳細...
    validations:
      required: true
  - type: dropdown
    id: version
    attributes:
      label: バージョン
      description: どのバージョンを使用していますか?
      options:
        - 1.0.2 (Default)
        - 1.0.1
        - 1.0.0
    validations:
      required: true
EOF

課題管理

# Issueの操作
gh issue create \
  --title "ユーザー認証機能の実装" \
  --body "OAuth2.0を使用したユーザー認証機能を実装する" \
  --assignee "@me" \
  --label "enhancement,backend" \
  --milestone "v1.0"

# Issueの更新
gh issue edit 123 \
  --title "新しいタイトル" \
  --body "更新された説明" \
  --add-label "priority:high" \
  --remove-label "priority:low"

# Issueの一覧表示
gh issue list --state open --assignee "@me" --label "bug"

# Issueの詳細表示
gh issue view 123 --comments

# Issueのクローズ(コミットから)
git commit -m "fix: ログイン画面のバグを修正

Fixes #123"

ワークフロー設定

# .github/workflows/issue-automation.yml
name: Issue Automation

on:
  issues:
    types: [opened, labeled]
  issue_comment:
    types: [created]

jobs:
  auto-assign:
    runs-on: ubuntu-latest
    if: github.event.action == 'opened'
    steps:
      - name: Auto-assign to project
        uses: actions/[email protected]
        with:
          project-url: https://github.com/orgs/company/projects/1
          github-token: ${{ secrets.GITHUB_TOKEN }}

  auto-label:
    runs-on: ubuntu-latest
    if: contains(github.event.issue.body, 'bug')
    steps:
      - name: Add bug label
        uses: actions/github-script@v6
        with:
          script: |
            github.rest.issues.addLabels({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              labels: ['bug', 'triage']
            })

  stale-issues:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/stale@v8
        with:
          stale-issue-message: 'この課題は30日間非アクティブです。必要に応じて再開してください。'
          close-issue-message: '60日間非アクティブのため自動クローズします。'
          days-before-stale: 30
          days-before-close: 60

レポート機能

// GitHub REST API - 統計情報取得
const { Octokit } = require('@octokit/rest');

const octokit = new Octokit({
  auth: process.env.GITHUB_TOKEN
});

// リポジトリの統計情報
async function getRepositoryStats(owner, repo) {
  // オープンなIssueの数
  const openIssues = await octokit.rest.issues.listForRepo({
    owner,
    repo,
    state: 'open',
    per_page: 1
  });

  // クローズされたIssueの数(過去30日)
  const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
  const closedIssues = await octokit.rest.issues.listForRepo({
    owner,
    repo,
    state: 'closed',
    since: thirtyDaysAgo.toISOString(),
    per_page: 100
  });

  // ラベル別統計
  const labelStats = {};
  for (const issue of openIssues.data) {
    for (const label of issue.labels) {
      labelStats[label.name] = (labelStats[label.name] || 0) + 1;
    }
  }

  return {
    openCount: openIssues.data.length,
    recentlyClosed: closedIssues.data.length,
    labelStats
  };
}

// マイルストーンの進捗
async function getMilestoneProgress(owner, repo, milestoneNumber) {
  const milestone = await octokit.rest.issues.getMilestone({
    owner,
    repo,
    milestone_number: milestoneNumber
  });

  const total = milestone.data.open_issues + milestone.data.closed_issues;
  const progress = total > 0 ? (milestone.data.closed_issues / total) * 100 : 0;

  return {
    title: milestone.data.title,
    progress: Math.round(progress),
    openIssues: milestone.data.open_issues,
    closedIssues: milestone.data.closed_issues,
    dueDate: milestone.data.due_on
  };
}

チーム連携

# .github/workflows/slack-notification.yml
name: Slack Notifications

on:
  issues:
    types: [opened, closed]
  pull_request:
    types: [opened, closed, merged]

jobs:
  notify:
    runs-on: ubuntu-latest
    steps:
      - name: Notify Slack
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          custom_payload: |
            {
              attachments: [{
                color: '${{ github.event.action == 'opened' ? 'good' : 'warning' }}',
                title: '${{ github.event.issue.title || github.event.pull_request.title }}',
                title_link: '${{ github.event.issue.html_url || github.event.pull_request.html_url }}',
                text: '${{ github.event.action }} by ${{ github.actor }}',
                fields: [{
                  title: 'Repository',
                  value: '${{ github.repository }}',
                  short: true
                }, {
                  title: 'Labels',
                  value: '${{ join(github.event.issue.labels.*.name, ', ') }}',
                  short: true
                }]
              }]
            }
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

# プロジェクトボードの自動化
- name: Add to project board
  uses: actions/[email protected]
  with:
    project-url: https://github.com/orgs/company/projects/1
    github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
    labeled: bug,enhancement
    label-operator: OR