GitHub Actionsのon:に書かれるイベントでよく見るもの

## イベントとは
GitHub Actionsのワークフローを定義するyamlにはそのワークフローを**どのタイミングで実行するのか**を設定する項目があります。

```yml
name: Test
on: # ここ
  pull_request:
    types:
      - opened
      - synchronize
jobs:
  ...
```

この「どのタイミング」に該当するものをイベントと呼びます。
ドキュメントでは[**ワークフローをトリガーするイベント**](https://docs.github.com/ja/github-ae@latest/actions/using-workflows/events-that-trigger-workflows)ページにその一覧がまとまっていますが、今回はその中から実際によく見かけるものをいくつかピックアップしてご紹介したいと思います。


## 対象読者
- 非公開のリポジトリでチーム開発を行っている
- ↑の中で動いているワークフローを読んでみたい/書いてみたい

既にがっつり触っている方にとっては目新しい情報はないと思われます。

## [pull_request](https://docs.github.com/ja/github-ae@latest/actions/using-workflows/events-that-trigger-workflows#pull_request): PRが○○されたら
まずは一番使われているであろうところから。テストを実行したり環境を立ち上げたり色々します。

```yml
name: Test
on:
  pull_request:
    types:
      - opened
      - synchronize
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: |
          do my test
```

この例ではPRが作成されたタイミングとPRが立っているブランチの内容が更新されたタイミングでそれぞれテストが実行されます。`types`のデフォルトが`opened`/`synchronize`/`reopene`なのでシンプルに

```yml
on:
  pull_request:
```

とだけ書かれている場合も多いです。

またそれだと走りすぎなんだよな～という場合に`branches`と`paths`という2つのフィルターを使って実行を制限することがあります。

```yml
name: Test
on:
  pull_request:
    types:
      - opened
      - synchronize
    branches:
      - develop
      - release
      - main
    paths:
      - "*"
      - src/**
      - "!**.md"
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: |
          do my test
```

ここでは同様のタイミングのうち

- PRの対象(マージ先)がdevelop/release/mainのいずれか

かつ

- 変更されたファイルが以下のいずれか
    - トップレベルにあり、拡張子が.mdではない
    - srcディレクトリ配下にあり、拡張子が.mdではない

である場合にテストが実行されます。論理演算がちょっと複雑ですが意外とすぐ慣れるので頑張りましょう。

## [push](https://docs.github.com/ja/github-ae@latest/actions/using-workflows/events-that-trigger-workflows#push): リモートにpushされたら

リモート側でコミットメッセージを検証したり解析したりといった用途で使われることが多いです。

```yml
name: Commit Message
on:
  push:
    branches:
      - feature/**
jobs:
  msg:
    runs-on: ubuntu-latest
    steps:
      - run: echo "${{ github.event.head_commit.message }}"
```

こちらも`pull_request`と同様`branches`と`paths`のフィルターで実行を制限することが可能です。

### テスト実行のトリガーとして`on: push`が使われる場面

ブランチの保護ルールで[`Require branches to be up to date before merging`](https://docs.github.com/ja/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches#require-status-checks-before-merging)がオンになっていない場合、featureブランチでテストを通したのに他のPRとの兼ね合いでdevelopが壊れてしまった！という事態が起こり得ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245527/8ba78126-5033-c710-3f8d-4e577414e1be.png)

そういった場合に`push`イベントを併用して

1. feature/** → developのPRでテスト
1. マージ後のdevelopブランチでもう一度テスト

というフローが採用されることがあります。

```yml
name: Test
on:
  pull_request:
    types:
      - opened
      - synchronize
    branches:
      - develop
      - release
      - main
    paths:
      - "*"
      - src/**
      - "!**.md"
  push:
    branches:
      - develop
      - release
      - main
    paths:
      - "*"
      - src/**
      - "!**.md"
jobs:
  test:
    name: Test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: |
          do my test
```

`Require branches to be up to date before merging`を常にオンにしておけばいいだけでは？と思われるかもしれませんが、それはそれで複数のPRが存在する場合に1つPRを取り込むたび他の全てのPRでテストを再実行せねばならず実行時間が大変なことになったりするのでまあそこは運用次第という感じです。場合によってはreleaseブランチはオンにして安全に倒し、developブランチはオフにして`push`と併用ということもあります(git-flowの場合、かつdevelop/release/main全てのブランチに保護がかかっている前提)。

## [workflow_call](https://docs.github.com/ja/github-ae@latest/actions/using-workflows/events-that-trigger-workflows#workflow_call): 他のワークフローに呼ばれたら
いわゆる[**再利用可能ワークフロー**](https://docs.github.com/ja/actions/using-workflows/reusing-workflows)と呼ばれるものです。

```yml: my-org/repo1/.github/workflows/echo.yml
name: Echo
on:
  workflow_call:
    inputs:
      msg: 
        required: true
        type: string
jobs:
  echo:
    runs-on: ubuntu-latest
    steps:
      - run: echo "${{ inputs.msg }}"
```

```yml: my-org/repo2/.github/workflows/caller.yml
name: 
on:
  workflow_dispatch:
jobs:
  echo:
    uses: my-org/repo1/.github/workflows/echo.yml@main
    with:
      msg: hoge!
```

これはシンプルな例ですが、実際にはシークレットが絡んで結構面倒くさめだったりもするので[**こちらの項目**](https://docs.github.com/ja/actions/using-workflows/reusing-workflows#using-inputs-and-secrets-in-a-reusable-workflow)だけでも読んでおくことをおすすめします。

## [workflow_dispatch](https://docs.github.com/ja/github-ae@latest/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch): 手動で呼ばれたら

`on`に`workflow_dispatch`が指定されている場合、そのワークフローは手動で実行されることを期待しています。

```yml

name: Environment
on:
  workflow_call: # 他のワークフローからも呼ばれる
    inputs:
      pr_num:
        required: true
        type: string
      action:
        required: true
        type: string
  workflow_dispatch: # 手動で実行することもできる
    inputs:
      pr_num:
        required: true
        type: string
      action:
        required: true
        type: string
jobs:
  run:
    runs-on: self-hosted
    if: inputs.action=='run' # どちらのイベントでトリガーされた場合でもコンテキストにinputsが存在するため正常に動く
    steps:
      - run: |
          run environment
```

実行の手順は[**このページ**](https://docs.github.com/ja/actions/using-workflows/manually-running-a-workflow)の通り。
注意点として、手動実行が可能なのは`workflow_dispatch`を指定したワークフローがデフォルトブランチに存在する場合のみです。

## [schedule](https://docs.github.com/ja/github-ae@latest/actions/using-workflows/events-that-trigger-workflows#schedule): 指定した時刻になったら

```yml
name: Announce
on:
  schedule:
    - cron: "0 0 * * *" # 毎日9時(JST)
jobs:
  announce:
    runs-on: ubuntu-latest
    steps:
      - id: count
        run: |
          pr_count=$(gh pr list -s open --json number --jq length)
          echo "pr_count=$pr_count" >> $GITHUB_OUTPUT 
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - uses: slackapi/slack-github-action@v1.24.0
        with:
          channel-id: ${{ secrets.SLACK_CHANNEL_ID }}
          payload: |
            {
              "text": "今朝のPRは${{ steps.count.outputs.pr_count }}件です"
            }
        env:
          SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
```

デフォルトブランチに存在する`schedule`が指定されたワークフローは`cron`の時刻に実行されます。ただし…

- 遅延します([参考](https://docs.github.com/ja/github-ae@latest/actions/using-workflows/events-that-trigger-workflows#schedule))
- 自動的に無効となる場合があります([参考](https://docs.github.com/ja/actions/using-workflows/disabling-and-enabling-a-workflow))

ということは覚えておいた方がいいかもしれません。

## おわりに
というわけで本当に極一部ですが`on:`の読み方についてご紹介しました。
`pull_request`や`workflow_call`の項はそれだけで記事1本文になってしまいそうで頑張って削ったのですが、どこかのタイミングで削った部分についても改めて記事を出せればと思います。

それでは。