GitHub Actions上に構築したDangerをPull Requestに変更があったときだけでなく、レビューされたときにも動かしたくて試行錯誤したメモ。 同じような状況の方がいれば試してみてほしい。

環境

  • Danger: 6.3.0

背景

先述の通り、Dangerをレビューされたときにも動かしたくて、Actionsのワークフローの設定を以下のようにした。 (実際にはキャッシュなどが入るが、記事のために省略)

name: Danger
on:
  pull_request:
  pull_request_review:
jobs:
  danger:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Setup Ruby
      uses: actions/setup-ruby@v1
      with:
        ruby-version: '2.5'
    - name: Setup gems
      run: |
        gem install bundler
        bundle install --jobs 4 --retry 3
    - name: Run Danger
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: bundle exec danger

試しにレビューコメントを残してみると、以下のようなログを残してDangerの実行はスキップされてしまった。

Dangerのソースコードを読むと、原因はCIごとに分かれているオブジェクトのGitHub Actionsのものの中でイベントを弾いてしまっていることのようだった。

    def self.validates_as_pr?(env)
      env["GITHUB_EVENT_NAME"] == "pull_request"
    end

danger/github_actions.rb at 057037ce7bd7e7bca5a9ff2c5bf43cfde37cac3b · danger/danger

Issueを立てて、なにか方法がないか聞いてみると、2つの方法を提案された。

  1. Danger JSを使う
  2. どうにかして情報を集めて pull_request イベントとして走らせる

1のDanger JSは追加でNodeの環境を作るのもめんどくさいのでなし。 2の方法で頑張ってみる。

解決策

先程のdanger/github_actions.rbを読んでみると、やっている事自体は簡単で GITHUB_EVENT_PATH にあるJSONファイルからPRの番号とリポジトリのクローン用のURLを取得しているだけだった。 GITHUB_EVENT_PATH 自体はActionsのドキュメントによるとトリガーされたイベントのPayloadがそのまま出力されたもので、おそらく従来のGitHubのWebhookのペイロードと同じ気がする。 目的の pull_request_review イベントの場合はこんな感じで、必要な情報は

  • PR番号 → .pull_request.number
  • クローンURL → .repository.clone_url

にありそう。 特にクローンURLはすでにDangerが読みに行っている場所にあるので、PR番号だけをどうにか持ってくれば良さそうだ。 GitHub Actions HostedのLinux環境には jq コマンドが入っているようなのでこれを利用する。

そうして最終的に動作したYAMLファイルは以下のようになった。

name: Danger
on:
  pull_request:
  pull_request_review:
jobs:
  danger:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Setup Ruby
      uses: actions/setup-ruby@v1
      with:
        ruby-version: '2.5'
    - name: Setup gems
      run: |
        gem install bundler
        bundle install --jobs 4 --retry 3
    - name: Run Danger
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
        # デフォルトの JSON のパスを取得
        event_path=${{ github.event_path }}

        if [ $GITHUB_EVENT_NAME = "pull_request_review" ]; then
          echo "Override event json file for pull_request_review event."

          # 読み込む JSON のパスを書き換え
          event_path="event.json"
          # jq コマンドを使って加工した JSON を↑で置き換えたパスに出力する
          cat ${{ github.event_path }} | jq '. |= .+ {"number": .pull_request.number}' > $event_path 
        fi

        # イベントのパスとイベント名を明示的に指定して Danger を走らせる
        GITHUB_EVENT_PATH=$event_path GITHUB_EVENT_NAME=pull_request bundle exec danger

これで無事動作した。

注意点としては、

  • 最初はデフォルトのJSONファイルを↓のように直接上書きしていたがうまく動いてくれなかった。
    • cat ${{ github.event_path }} | jq '. |= .+ {"number": .pull_request.number}' > ${{ github.event_path }}
    • リダレクトの > と、YAMLの文法やActionsの変数展開がバッティング?
    • 別のファイルに逃がすことで動作した。
  • この設定でレビューで起動したときは、Pull RequestのCheckのステータスが In Progress にならない。
    • Dangerの実行が終われば SucceededFailed になるのでまあいいかなという気持ち

とりあえず、最初の目的は達成できた。

参考・関連リンク