GithubActionsを使ってGithubプロジェクトを使いやすくする

株式会社ミクシィが運営するカラオケ動画コミュニティサービス[KARASTA(カラスタ)](https://karasta.net/)の開発チームでリーダーをしている@cgetcです。
今年になって初めてマネージャーになり、タスクを管理において実行したことを紹介します。

#Githubプロジェクトは機能が足りない
Githubプロジェクトを用いてカンバン方式でissueを管理してるのですが、担当者が分からなかったり、どのバージョンでリリースされるのかを把握するのに困っていました。
issueに担当者やマイルストーンを設定することで解決しますが、設定するのが手間で疎かになりがちだったので、GithubActionsを使って設定を自動化しました。

#issueの担当者を自動設定する
GithubActionsのマーケットプレイスにある[pozil/auto-assign-issue](https://github.com/marketplace/actions/auto-assign-issue)を利用して、issueの担当者を自動で設定するようにしました。

マーケットプレイスにはランダムで担当者を設定するものもありますが、設定したユーザをすべて割り当てるGithubActionsをチームでは採用しました。
担当者が少なく、タスク量を調整する必要があるため、全候補を最初に設定するものを採用しました。設定の手間はさほど軽減はされませんが、担当者未割り当て状態が可視化されるので、タスク割当の調整が必要なことに気づきやすくなるメリットもありました。

## ワークフロー例
```yaml
name: Automatically assign members to issues

on:
  issues:
    types: opened

jobs:
  assign:
    name: Set assignees
    runs-on: ubuntu-18.04
    steps:
      - name: Set assignees
        uses: pozil/auto-assign-issue@v1
        with:
            assignees: user_x,user_y # 変えたければここを変える
```

#マイルストーンを自動設定する
リリース対象となるissueが分かりにくいので、リリースするバージョンをタイトルにしたマイルストーンを作成し、issueに設定する運用をしています。
issueにマイルストーンを自動設定するGithubActionsはあるはずもないので、[GithubActionsを作成](https://github.com/marketplace/actions/automatically-set-milestone-to-issue)しました[^1]。

開発チームは[Githubフロー](https://tracpath.com/bootcamp/learning_git_github_flow.html)/[セマンティック・バージョニング](https://semver.org/lang/ja/)を採用し、フィーチャー開発にはマイナー/メジャーバージョンを、それ以外のバグフィックスなどはパッチバージョンを割り当てるようにしています。
試行錯誤の結果、以下のルールに落ち着きました。

1. 最小のマイナーバージョンより小さく、最大のパッチバージョン
2. 最小のマイナーバージョンより大きく、最小のパッチバージョン
3. 最小のマイナーバージョン

詳しくは以下のユースケースを見てもらうのが分かりやすいと思います。

## ユースケース
※　太字のバージョンのマイルストーンが設定されます

### 通常のケース
- **v0.1.1** （リリース待ちなどのため設定しない）
- v0.2.0 
- v0.2.1 

### リリース待ちのバージョンがあるケース
- v0.1.1 （リリース待ちなどのため設定しない）
- **v0.1.2** （前のリリース内容が確定したときに作成する）
- v0.2.0 
- v0.2.1 （マイナーバージョンに依存したリリース）

### マイナーバージョンが対象のケース
- **v0.2.0** （マイナーバージョンアップをリリース予定） 
- v0.3.0 

### リリース待ちのマイナーバージョンがあるケース
- v0.2.0 （リリース待ちなどのため設定しない）
- **v0.2.1** (マイナーバージョンに依存した修正) 
- v0.3.0 


## ワークフロー例
```yaml
name: Set milestone to issue
on:
  issues:
    types:
      - opened
      - reopened

jobs:
  issue_milestone:
    name: Set milestone to the issue
    if: ${{ !startsWith( github.event.issue.milestone.title, 'v' ) }}
    runs-on: ubuntu-latest
    steps:
      - uses: cgetc/automatically-set-milestone-to-issue@v0.1.0
        with:
          github-token: ${{secrets.GITHUB_TOKEN}}
```

[^1]: 作成したGithubActionsはワークフローのイベント設定によってPullRequestにも自動設定できるようになっています。

#Githubリリースの下書きを自動作成する
下書きのGithubリリースにPullRequestをマージするごとに内容を追記し、リリース確定後にPublishする運用をしています。
そこで、マイルストーンを作成すると同時に下書きのGithubリリースを作成するようにしました。
マイルストーンを作成するGithubActionsもマーケットプレイスにいくつか存在します。しかしGithubリリースを作成するにはタグが必須のため採用せず[^2]、[新たにGithubAcitonsを作成](https://github.com/marketplace/actions/create-github-release-simply)しました。
（誤操作で公開してしまわないように、タグが空の下書きのGithubリリースを作成しています。）

[^2]: マーケットプレイスで公開されているGithubActionsはOctokitを利用しているものしかなく、[Octokitはタグが必須](https://octokit.github.io/rest.js/v18#repos-create-release)です。

## ワークフロー例
```yaml
name: Create Release Draft

on:
  milestone:
    types:
      - created

jobs:
  create_release_draft:
    runs-on: ubuntu-latest
    if: ${{ startsWith( github.event.milestone.title, 'v' ) }}
    steps:
      - name: Create release_body
        run: |
          cat << EOF > release_body.txt
          ## リリース日
          $(date '+%Y')-XX-XX
          ## Version
          ${{ github.event.milestone.title }}
          EOF
      - name: Create draft release
        uses: cgetc/create-github-release-simply@v0.1.0
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          repository: ${{ github.repository }}
          name: ${{ github.event.milestone.title }}
          body-path: release_body.txt
          draft: true
```

#リリース後にマイルストーンを自動的に閉じる
リリース後にはマイルストーンが不要になるので、リリース公開後に自動的にマイルストーンを閉じるようにしました。
マイルストーンを閉じるGithubActionsはマーケットプレイスに公開されている[Beakyn/gha-close-milestone](https://github.com/marketplace/actions/close-milestone-action)を利用しました。
## ワークフロー例
```yaml
name: Close milestone on release published

on:
  release:
    types:
      - published

jobs:
  close_milestone:
    name: Close Milestone
    if: ${{ startsWith( github.event.release.tag_name, 'v' )
    runs-on: ubuntu-latest
    steps:
      - uses: Beakyn/gha-close-milestone@v1.1.1
        env:
          GITHUB_TOKEN: ${{ github.token }}
        with:
          repository: ${{ github.repository }}
          milestone-title: ${{ github.event.release.tag_name }}
```

#issueのマイルストーンをPullRequestにコピー
Githubプロジェクトではissueのみ管理しており、issueのみ自動的にマイルストーンを設定しています。
しかしPullRequestにもマイルストーンがあるほうが見やすいので、[issueのマイルストーンをPullRequestにコピーするGithubActions](https://github.com/marketplace/actions/copy-milestone-from-issue-to-pull-request)を作成しました。


## ワークフロー例
```yaml
name: Set milestone from issue to PR

on:
  pull_request:
    types:
      - opened
      - edited
      - reopened

jobs:
  set_milestone:
    name: Set milestone
    runs-on: ubuntu-latest
    if: ${{ !github.event.pull_request.milestone }}
    steps:
      - name: Copy milestone from issue to pull request
        uses: cgetc/copy-milestone-from-issue-to-pr@v0.1.1
        with:
          github-token: ${{secrets.GITHUB_TOKEN}}
```

# 総括
ルールで縛るよりも自動化。
指摘する方もされる方も気持ちよくない。
自由に仕事ができる環境を作るのが大事。