チケット管理をGitHub IssueとProjectでおこなう方法

## この記事はなに？

みなさんはタスク管理にどんなツールを使っていますか？
asana？ Jira？ それともNotion？

本記事は、GitHub issueとGitHub Projectを活用してタスクを管理する方法と運用についてまとめます。

また、本記事内では「プロジェクト」という言葉を以下のように使い分けます。

- プロジェクト: 開発案件、タスクといった実際の仕事
- Project: GitHub Projectのサービス名


## Output（こんな運用が可能です）

### 複数リポジトリをまたいだタスク確認

弊社はプロダクトごとに複数のリポジトリを管理しています。
チームのタスクとリソースの確認にGitHub Projectが活躍します。

Projectにアクセスすると、今どのプロダクトがどのタスクを持っているのか、そして誰の稼働率が高くなっているのかを表形式で確認することができます。

![スクリーンショット 2024-10-22 9.27.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/7cef514c-95bb-6f6e-a651-3009342ba4ac.png)

右側の大きなエリアでは、リポジトリごとに区分けされたissue一覧を確認することができます。
左側の小さなエリアでは、Assignees = 担当者 がいくつのタスクを抱えているかを見ることができます。

表の項目やソート対象は自由に設定可能です。


## スケジュールで進捗確認

Projectは自由にタブを設定することができ、タブごとに何をどのように表示するかを設定できます。
スケジュールを使えば各タスクの開始〜完了日を確認することができます。

![スクリーンショット 2024-10-25 11.03.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/db4f4821-110f-0ae7-4b7f-03e1f180cee8.png)


issueがProjectに紐づけられると、スケジュール上に自動で表示されます。
チャート内でのスケジュール設定は感覚的におこなうことが可能です。

画像のように、リポジトリごとにスケジュールをグルーピングできるのもポイントです。

### 自分のタスクをカンバンリストで確認

GitHub Projectでは、各issueをステータスごとにカンバン形式で表示することができます。

![スクリーンショット 2024-10-22 11.22.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/50e670ed-2eb0-b5a5-3069-e5af660a4c98.png)

このとき、表示条件に`assignee:@me`を含めることで、自分に紐づけられたissueを表示することが可能です。
毎朝のタスク確認をこの1ページだけで済ませることが可能です。
また、ステータスは`Todo`, `In Progress`, `Done`以外に設定することも可能です。

issueカードをドラック&ドロップすることでステータスを更新することが可能です。
ステータスがDoneになると、issueは自動的にcloseされます。
表示条件を`is:open`にしておくと、closeされたissueはProjectから非表示になります。

### 検証環境の使用状況を確認

先ほど紹介したスケジュールチャートはプロジェクト全体のスケジュールです。
それとは別に、検証環境の使用日程を表示するスケジュールチャートも作成しました。

これにより、同じプロダクトで別案件が同時に走っているときに検証環境の競合がおきないようにスケジュール調整をすることができます。

![スクリーンショット 2024-10-22 11.41.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/6770a69b-7c44-b979-a77a-36fa59403b9c.png)

GitHub Projectでは項目を自由に設定可能と伝えましたが、各項目ごとにタブを使用することでチームにとって必要な情報を見やすく表示することが可能です。

### テンプレートからissueの作成

新規issueはProject、もしくは各リポジトリから作成することができます。
このとき、テンプレートを複数用意することができます。

![スクリーンショット 2024-10-22 9.25.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/e642f98e-c063-597d-e05a-1ad827c510e0.png)

作成されたissueは、自動でProjectに紐づけられます。
また、紐づけ時のStatusのデフォルト値を指定することも可能です。


### その他の嬉しいポイント

#### 項目設定が「されていない」タスクを確認することができる

チームミーティングでスケジュールページを共有することで、各項目が設定されていないタスクに対してアナウンスすることが可能になります。
例えばスケジュールやステータス、担当者など、タスクにとって重要な項目が設定されていないタスクに対して、

- ただ設定を忘れているだけなのか
- 設定できない理由があるのか
  - どうなれば設定可能なのか

を確認するきっかけになります。


#### issueとプルリクを紐づけられる

issueページの`Development`からプルリクを選択することで、issueとプルリクを紐づけることができます。

![スクリーンショット 2024-10-22 11.48.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/d1b38766-a8e9-27c3-1a2d-0820fc0df873.png)

これによって嬉しいことが2つあります。

**1, プルリクコメントにチケット概要を改めて記載する必要がなくなる（二重管理抑止）**

PRコメントにチケット概要を書いている場合は、issueとプルリクを紐づけることでその手順を削減することができます。
レビューに必要なタスク背景は全てissueに書いてあるので、それを参照しましょう。

**2, プルリクから検証環境反映日やリリース日を簡単に追うことができる**

複数のプルリクを同時にリリースする際に、プルリクの反映が漏れてしまう不具合の経験はありますか？
Projectのスケジュールを見れば、プロジェクト完了日（リリース日）をタスクを串刺しにした状態で確認することが可能です。

これにより、リリースタイミングでマージされていないプルリクの存在に気づくことができます。

![スクリーンショット 2024-10-22 11.59.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/9bef489f-e38e-e8e1-e6c3-eb8ccf06087a.png)


### issueはリポジトリ間で移動可能

issueはリポジトリに強く紐づいていますが、紐づけ元のリポジトリを変更することが可能です。
issueページの右側に小さくある「`→ Transfer issue`」をクリックしてみてください。
すると、以下の警告文とともに紐づけ元のリポジトリを選択することができます。

　![スクリーンショット 2024-10-25 20.25.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/7198f563-2f81-bc67-4499-96910fe8cb11.png)

警告文は、以下の内容が書かれています。

> issueの転送は、いかなるissue内容も消去しません。テキストの参照など、他の課題、プルリクエスト、プロジェクト、チームに関する内容は、この課題の説明とコメントに残ります。担当者、ラベル、およびマイルストーンは、ターゲットリポジトリに存在する場合に転送されます。

つまり、転送元と転送先リポジトリの設定が同じであればデータは完全に残るという意味です。

この機能は、ただ単にリポジトリを移動することだけを目的とせずに、次のような活用も考えられます。

どのリポジトリに紐づければ良いのか分からない、または完全に新規案件でリポジトリが無いチケット置き場として、「unattached」のようなリポジトリを作成します。
上記に当てはまるチケットや、プロダクトに関係ないオペレーション改善系のチケットを**とりあえずこのリポジトリに**issueを作成します。
（とにかくチケットを切ることが大切。slack上で発生した、管理されない隠れタスクにリソースが逼迫されているエンジニアを救い出せるのはあなたが作成するチケットです。）
のちに適切なリポジトリが発生したらunattachedから移動させれば良いのです。

### issueに書いたメモが資産になる

エンジニアにメモ魔が多いのは、自分のやったことを**忘れても良いようにするため**です。
我々は、明日の自分と今日の自分が別人であることを知っています。
メモは将来の資産になります。

調査やフィードバックのやりとりがslackに残っているチームも多いと思います。
仕様や実装背景を記憶に頼らず、記録に残すのにissueは適しています。
上でも書いた通りissueはPRに紐づけることができるため、以下の流れで過去の文章にたどり着くことができます。

- このコードなんでこうなってるんだっけ？
- GitHubの機能で変更されたPRを探索
- PRからissueを見る
- issueに背景が書いてある
  - または、そのやりとりがされているslackのチャットURLが残されている

これで、過去のやりとりを探すためにslackで17通りの検索キーワードを試す必要はありません。


### ドキュメントが宙に浮かない

これまで紹介した機能は、Notionでも実現可能かもしれません。
しかしNotionは手軽で誰でも触れるが故に、作ったきりどこからアクセスできるのか分からない（=宙に浮いた）ページが存在しやすくなります。
PRやissueは必ずリポジトリに紐づくため、アクセスにストレスが発生しません。

あなたは3ヶ月前のタスクページに5クリック以内でアクセスできますか？
それを実現するためにブラウザのブックマークが過多になっていませんか？


## 設定方法

ここからは、具体的にissueとGitHub Projectの設定方法を説明していきます。

公式ドキュメントは以下になります。

https://docs.github.com/ja/issues/planning-and-tracking-with-projects/creating-projects/creating-a-project

### 紐づけ先のProjectを用意する

#### Projectの新規作成

GitHubのユーザー（もしくはオーガニゼーション）Topページから、`Projects`を選択します。
緑色の`New Project`からProjectを新規作成します。
このとき、いくつかGitHub側で用意されたテンプレート（`Featured`）が表示されます。
それを利用しても良いですし、自分でカスタムしても良いと思います。

Projectを作成したら左上の鉛筆アイコンからProject名を編集することができます。

#### テーブルビューの作成

はじめに、テーブルビューで項目（カラム）を設定してきます。
設定する前に、各カラムの管理元はissueとProjectの2種類であることを理解する必要があります。

| 項目名 | 管理元 | 説明 |
|---|---|---|
| Title | issue | issueのタイトル |
| Labels | issue | bug, enhancement など 値はユーザーが設定可能 |
| Assignee | issue | 担当者 |
| Pull Request | issue | PRの紐づけ |
| Status | Project | Todo, In Progress, Done 値はユーザーが設定可能 |
| 開始日 | Project | ユーザーによる追加項目 |
| 完了日 | Project | ユーザーによる追加項目 |

このように、Projectに表示する項目は管理元が分かれています。
ここで意外なのは、Statusはissueではなく、Projectが管理する項目だということです。
つまり、Statusの操作はissueに対しておこなうものではなく、紐づけ先のProject内でおこなう必要があることを意味しています。

:::note warn
**不便ポイント**
Labelsはissueが管理する項目です。
そしてissueはリポジトリに内包されています。
つまりLabelsをオリジナルで作成する場合、管理するすべてのリポジトリに対してLabelsを定義する必要があります。
ただし設定さえしてしまえばその後は設定した内容で運用可能なので、最初だけ根気が必要になります。
:::

さて、Projectにカラムを追加していきましょう。
カラムの追加は、テーブルビューのカラム部分にある`+`をクリックすることで選択できます。

![スクリーンショット 2024-10-22 13.25.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/0f63e4a4-3909-6e4b-85ed-6724c6bdd851.png)

はじめに「開始日」を追加します。
「+ New field」からField nameを記入し、Field type（型）をDateに設定します。
型によって後々できることが変わるので、色々実験してみてください。

![スクリーンショット 2024-10-22 13.27.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/8623052c-36ad-33c5-5b39-b400cc5f6420.png)

同様に、「完了日」も追加します。

設定後は、右上にある緑の`Save`をクリックして保存します。

![スクリーンショット 2024-10-22 19.32.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/1175fc96-fbf1-56a4-920d-adc95b4c3ac5.png)


#### スケジュールビューの追加

Projectのタブから「New view」をクリックすると、ビューを追加することができます。
各選択肢は以下の機能を持っています。

- Table: テーブルビュー
- Boad: カンバンビュー
- Roadmap: スケジュール（ガントチャート）ビュー

![スクリーンショット 2024-10-22 13.33.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/36651847-1d2d-6aa5-055e-6cec6e54b6c4.png)

今回はスケジュールを作成するので、Roadmapを選択します。
画面右側に「Date fields」という項目が表示されています。

![スクリーンショット 2024-10-22 13.35.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/28c8c567-d75a-a68c-749a-c165b4f4869c.png)

ここをクリックすると、スケジュールの起点となる項目を設定することができます。
今回は、先程設定した「開始日」と「完了日」をそれぞれStart date, Target dateに設定します。

![スクリーンショット 2024-10-22 13.36.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/3b30dcf0-fff1-b68a-7a0d-ae6176766fc1.png)

すると、スケジュール上に開始日〜完了日のグラフが表示されるようになります。


### グルーピングの設定

それぞれのビューにおいて、情報をリポジトリや担当者ごとにグルーピングすることができます。

はじめに、タブの右側にある「▼」を設定します。
すると、Configurationという項目で「Group by」を選択することができます。
ここを「Repository」に設定することで、リポジトリごとにグルーピングすることができます。

![スクリーンショット 2024-10-25 21.05.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/3eb0828d-eeeb-5cd9-2c6a-957f2bb36a5f.png)

同様に、「Slice by」を選択すると、左側に小さなエリアを作成することができます。


### issueのテンプレートを設定する

GitHubには、issueのテンプレートをコード上で管理する機能があります。
今回は、`.github/ISSUE_TEMPLATE`配下にyml形式でissueテンプレートを作成する方法を紹介します。

ここの詳細は公式ドキュメントに任せることにします。

https://docs.github.com/ja/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#creating-issue-forms

このとき、タイトル、ラベル、紐づけ先Project、担当者のデフォルト値を設定することができます。
issueが作成されると、ここで指定したProjectに自動で紐づきます。
Projectの指定の仕方は`"user|org/project_number"`になります。

:::note
この設定は、テンプレートファイルがGitHubのデフォルトブランチに含まれている必要があります。
挙動を確認したい場合は、SettingsからDefault branchを変更してください。

![スクリーンショット 2024-10-21 19.05.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/0cdc18ef-e463-363c-7dc2-5bb16125c1a9.png)
:::

#### issueテンプレート例

今回私が作成したテンプレートを共有します。

<details open><summary>サンプル</summary>

```yml:issue_template.yml
name: issueテンプレート
description: issueテンプレート
labels: "運用"
projects: "ユーザー名/projectナンバー" # https://github.com/users/ysk91/projects/4の場合、"ysk91/4"
body:
  - type: markdown
    attributes:
      value: | # ここの値は作成後のissueに記載されない
        チケット作成にご協力いただきありがとうございます！
        右側のlabelsから該当のものを選択してください。
        スケジュールはissue作成後に設定することができます。
  - type: textarea
    id: require
    attributes:
      label: 要件
      description: 要件を記載してください。資料のURLも添付可能です。
      placeholder: マークダウン記法で入力可能です。
    validations:
      required: true
  - type: textarea
    id: conversation
    attributes:
      label: 会話履歴
      description: Slack等の会話履歴を記入してください
    validations:
      required: false
  - type: markdown
    attributes:
      value: |
        # これ以降はチケット作成後に記載する内容です
  - type: textarea
    id: mermaid
    attributes:
      label: スケジュール
      description: スケジュール確認要
      value: | # タスク単位のガントチャートをマーメイド記法で書くことも可能です
        <!-- 要件の開始日、テストレビュー日、各項目の工数を記入する -->

        ```mermaid
        gantt
            title プロジェクト
            dateFormat  YYYY-MM-DD
            excludes    weekends

            section 社内
                要件 :active, a1, 2024-10-10, 10d
                要件Fix : milestone, m1, after a1, 0d
                開発 :active, a2, after a1, 10d
                テストレビュー : milestone, m2, 2024-10-27, 0d
                QA :a3, after a2, 5d
            section 社外
                UAT :active, b1, after a3, 10d
            section リリース
                リリース : milestone, m3, after b1, 1d
        ```
  - type: textarea
    id: tasks
    attributes:
      label: 進捗
      description: 進捗確認用
      value: | # issueにtaskの進捗度合いが表示されるようになります
        - [ ] 要件
        - [ ] 要件fix
        - [ ] 開発
        - [ ] テストレビュー
        - [ ] QA
        - [ ] UAT
        - [ ] リリース
        - [ ] 先方確認
  - type: textarea
    id: qa
    attributes:
      label: QA
      value: テスト仕様書のリンクを貼って下さい
    validations:
      required: false
  - type: textarea
    id: man-hours
    attributes:
      label: 工数
      value: |
        - PM
        - エンジニア
        - QA
    validations:
      required: false
```
</details>

:::note
ちなみに、ここでチェックボックスを[tasklist]に設定するとProjectのビューで「Tracks」という項目が使用できるようです。
Tracksとは、ビュー上でチェックリストの進捗状況が確認できる項目です。
しかし、この機能は現在OrganizationからのWaitlistに登録する必要があるそうです。

https://blog.lufia.org/entry/2023/08/21/121850
:::

### （任意）config.ymlを作成する

`.github/ISSUE_TEMPLATE`配下にconfig.ymlを作成すると、新規issueを作成する際に複数のテンプレートから選択することができます。
また、テンプレートだけではなく、リンクを設定することも可能です。

![スクリーンショット 2024-10-22 19.44.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/77bdf987-c20c-b7f3-7d77-d6cea075d0c4.png)

今回は、1種類のテンプレートと紐づけ先Projectのリンクを設定しました。

config.ymlがない場合、このページは上で作成したテンプレートだけが表示されます。

config.ymlの公式のサンプルは以下から参照することができます。
https://docs.github.com/ja/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser

### Project Workflowを設定する

GitHub Projectには、Project Workflowという機能があります。

https://docs.github.com/ja/issues/planning-and-tracking-with-projects/automating-your-project/using-the-built-in-automations

これを用いて、以下の機能を実装していきます。

詳細は公式ドキュメントに任せるとして、今回は以下の機能をONにします。

- Item added to project
  - Projectに紐づいたissueのStatusを`ToDo`に変更する
- Item closed
  - issueがcloseされたとき、Statusを`Done`に変更する
- Auto-close issue
  - Statusが`Done`になったissueをcloseする

最終的に以下の3つがONになります。

  ![スクリーンショット 2024-10-22 19.55.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2688241/bba702be-2c43-74c7-acc0-bfe6d82fffd1.png)


### 実際にissueを作成してみる

さて、設定は以上で完了です。
実際にissueを新規作成してみましょう。
Projectにissueがきれいに並んだら成功です🎉

## 試したけどやめたこと

ここからは、自分が上記にいたるまでに試したけどやめたことをまとめます。
issueやProjectの操作にGitHub Actionsが必要だと思い、3,700円の本を買ったのですが出番はありませんでした🥲

### GitHub ActionsでissueをProjectに紐づける

https://github.com/actions/github-script を使用すると、GitHub Actionsを使用してissueをProjectに紐づけることができます。
ただ、Issue formを使用することでProjectへの紐づけをデフォルトで設定することができるので、これは不要と判断しました。

### GitHub ActionsでProjectに紐づけたあとのStatusを'ToDo'にする

https://github.com/actions/github-script を使用すると、GitHub Actionsのスクリプト上でJavaScriptやTypeScriptを使用することができます。
この性質を利用して、IssueのデフォルトStatusを'ToDo'にすることを考えました。
しかし、Project Workflowを使用することでIssueのデフォルトStatusを設定することができるため、これは不要と判断しました。

### GitHub Actionsでcloseされたissueをアーカイブする

上と同様に、github-scriptを活用してcloseされたissueをアーカイブすることを考えました。
しかし、Projectの表示条件に`is:open`を指定することでcloseされたissueは非表示になるため、アーカイブする必要はないと判断し、この機能は不要と考えました。

## まとめ

issueからはじめよ


## 参考

https://zenn.dev/ncdc/articles/55cc05c1a65292

https://qiita.com/itkr/items/0d4c0015da28827b2bb7

https://developer.mamezou-tech.com/blogs/2022/10/22/renewed-github-projects-automation/