git-pr-releaseしてくれるGitHub Actions作ったよ

[GitHub Actions](https://developer.github.com/actions/)がlimited public betaになったので、さっそく使ってみました。
本当はCIを作りたかったのですが、CircleCIに慣らされすぎててなかなか難しかったので、練習がてらに「issueを作ったらgit-pr-releaseを動かしてくれるActions」を作ったので紹介します。

## git-pr-releaseとは？

- git flowで例えるとrelease branchからmasterへのPull requestで差分に含まれているPull requestをリストアップしてdescriptionに記載してくれる便利ツール
- 詳しくは[本家へ](https://github.com/motemen/git-pr-release)

## issueを作ったらgit-pr-releaseを動かしてくれるActionsとは？

- Issueに「git-pr-release」ラベルを付けて新規作成すると、
<a href="https://gyazo.com/ed6b08acb29dc2fd4fa899872ee2d031"><img src="https://i.gyazo.com/ed6b08acb29dc2fd4fa899872ee2d031.png" alt="Image from Gyazo" width="800"/></a>
- リリースPull requestが自動作成されて、
<a href="https://gyazo.com/4b74ea8cb7501a7c1a1e0ec8ca97f88d"><img src="https://i.gyazo.com/4b74ea8cb7501a7c1a1e0ec8ca97f88d.png" alt="Image from Gyazo" width="800"/></a>
- もとのIssueが自動でcloseされる！！！
<a href="https://gyazo.com/9abb714977d0a62ede2e53b4c9c33be2"><img src="https://i.gyazo.com/9abb714977d0a62ede2e53b4c9c33be2.png" alt="Image from Gyazo" width="800"/></a>

ことができるようになります。

## 自分のRepositoryで使ってみる

[rvillage/github_pr_release_action](https://github.com/rvillage/github_pr_release_action)というRepositoryを作りました。
このRepositoryをForkまたは、中身をまるっとコピーして**Private Repository**を作ってください。

あとは以下の手順でPersonal access tokenを登録すればOKです。

1. [New personal access token](https://github.com/settings/tokens/new)でアクセストークンを作成する（名前は自由でいいですが、repoに対する許可をつけてください）
<a href="https://gyazo.com/2148c6eaf06a60d093dd1c05da6fd941"><img src="https://i.gyazo.com/2148c6eaf06a60d093dd1c05da6fd941.png" alt="Image from Gyazo" width="800"/></a>

2. Repository Settingsでアクセストークンを登録する（キャプチャ画像だと登録済ですが`GIT_PR_RELEASE_TOKEN`で登録してください）
<a href="https://gyazo.com/47c4f60bd854709bac0e4bcc9292e3ff"><img src="https://i.gyazo.com/47c4f60bd854709bac0e4bcc9292e3ff.png" alt="Image from Gyazo" width="800"/></a>

3. `git-pr-release`ラベル付きのIssueを新規作成する
<a href="https://gyazo.com/ff2e439c9d1e17ce4a13d3ea05badd29"><img src="https://i.gyazo.com/ff2e439c9d1e17ce4a13d3ea05badd29.png" alt="Image from Gyazo" width="800"/></a>


## main.workflowをひとつひとつ解説する

GitHub Actionsはmain.workflowで全体の流れを記述します。
筆者はCircleCI脳なので、これを.circleci/config.yml風に置き換えてみました。

```main.workflow
workflow "git-pr-release flow" {
  resolves = [
    "git-pr-release!",
    "debug",
  ]
  on = "issues"
}

action "new_issue?" {
  uses = "actions/bin/filter@master"
  args = ["action", "opened"]
}

action "use_git-pr-release?" {
  uses = "actions/bin/filter@master"
  args = ["label", "git-pr-release"]
}

action "git-pr-release!" {
  uses    = "docker://circleci/ruby:2.5.3-node"
  needs   = ["new_issue?", "use_git-pr-release?"]
  secrets = ["GIT_PR_RELEASE_TOKEN"]
  args    = [".github/bin/git-pr-release"]
}

action "debug" {
  uses = "actions/bin/debug@master"
}
```
```:.circleci/config.yml
version: 2.0

workflows:
  git-pr-release_flow:
    jobs:
      - new_issue?
          filters:
            only:
              - issue_events
      - use_git-pr-release?
          filters:
            only:
              - issue_events
      - git-pr-release!:
          requires:
            - new_issue?
            - use_git-pr-release?
      - debug

jobs:
  new_issue?:
    docker:
      - image: actions/bin/filter@master
    steps:
      - run: event.issue.action == "opened"
  use_git-pr-release?:
    docker:
      - image: actions/bin/filter@master
    steps:
      - run: event.issue.label == "git-pr-release"
  git-pr-release!:
    docker:
      - image: circleci/ruby:2.5.3-node
        environment:
          GIT_PR_RELEASE_TOKEN: ***
    steps:
      - checkout
      - run: ./.github/bin/git-pr-release
  debug:
    docker:
      - image: actions/bin/debug@master
    steps:
      - run: echo env
      - run: cat event.json
```

CircleCI風なので、厳密にはあっていません :bow:
筆者は.circleci/config.ymlっぽくするだけで、なにこれCircleCIわかりやすい、すごいってなりました :smile: 

### workflowブロック

workflowはactions全体の名前付けと、どのactionsがgreenになれば全体としてOKと判断するかを記述します。
また、このworkflowはどのイベントをhookするかを設定できます。

```
workflow "git-pr-release flow" {
  resolves = [         <- workflowとしてgreenと判断するためのactionsリスト
    "git-pr-release!",　 <- git-pr-release! action
    "debug",            <- debug action
  ]
  on = "issues"         <- issueのイベントをhook
}
```

### actionsブロック

actionsでは、主にコンテナイメージを定義してどんなコマンドを実行するかを記述します。

このactionsではGitHubが公式に用意してくれているコンテナイメージを使っています。
[利用可能なフィルタ](https://github.com/actions/bin/tree/master/filter#available-filters)で、新規issueが作成されたイベントをフィルタできるようにしています。

```
action "new_issue?" {
  uses = "actions/bin/filter@master" <- filter actionイメージを設定
  args = ["action", "opened"]        <- event.jsonのactionがopenedか判定
}
```

このactionsではlabelにgit-pr-releaseという文字列が設定されているかをフィルタできるようにしています。

```
action "use_git-pr-release?" {
  uses = "actions/bin/filter@master" <- filter actionイメージを設定
  args = ["label", "git-pr-release"] <- event.jsonのlabelがgit-pr-releaseを含んでいるか判定
}
```

このactionsで実際にgit-pr-releaseが実行されています。
git-pr-releaseは、「git-pr-release」ラベルが付いた新規issueが作成されたときに実行されるようにしたいためneeds設定を入れています。
secretsはパスワードといった隠蔽しておきたいパラメータを呼び出すかどうかを設定できます。
今回はaccess tokenが必要なのでGIT_PR_RELEASE_TOKENとして使えるようにしました。

git-pr-releaseスクリプトは、ただのRubyスクリプトなのでここでは細かい説明はしません。

```
action "git-pr-release!" {
  uses    = "docker://circleci/ruby:2.5.3-node"    <- circleci/ruby:2.5.3-nodeイメージを設定
  needs   = ["new_issue?", "use_git-pr-release?"]  <- 前提条件としてnew_issue? actionとuse_git-pr-release? actionがgreenであること
  secrets = ["GIT_PR_RELEASE_TOKEN"]               <- 隠蔽した環境変数の利用
  args    = [".github/bin/git-pr-release"]         <- bin/git-pr-releaseスクリプトの実行
}
```

このactionsはちょっと変わり種です。
どのコンテナイメージを使うかしか設定していないので、常にgreenを返します。
実際に起動したコンテナの中の環境変数やevent.jsonのログに出力してくれます。（[ログサンプル](https://github.com/actions/bin/tree/master/debug#example-output)）

```
action "debug" {
  uses = "actions/bin/debug@master" <- debug actionイメージを設定
}
```

### 流れをまとめると

1. workflowでissueのイベントをhookする
2. new_issue? actionで、いま発生したイベントがopenedイベントか判定する
3. （2と同時）use_git-pr-release? actionで、いま発生したイベントのラベル設定がgit-pr-releaseか判定する
4. （2と同時）環境変数とevent.jsonをログ出力する
5. （2,3がgreenになったら）git-pr-releaseを実行する

名前のとおりフローチャートのように組み合わせ次第ではいろいろなことができそうです :thumbsup:

## さいごに

GitHub Actionsを使って、GitHub内でのイベントで柔軟になにかを実行するボットの作成が簡単にできるようになりました。
いまはまだできませんが、オープンソースリポジトリでの利用や、GitHub Appsでworkflowの公開などができるようになると夢が広がりそうです。

## 参照

- [workflowがサポートするイベント一覧](https://developer.github.com/actions/creating-workflows/workflow-configuration-options/#events-supported-in-workflow-files)
- [フィルタaction](https://github.com/actions/bin/tree/master/filter)
- [デバッグaction](https://github.com/actions/bin/tree/master/debug)