GitHub Actions + merged-pr-stat + datadog で開発生産性を可視化する

5 min read読了の目安(約5000字

はじめに

GW中に何か一つアウトプットしたいと思い、普段から考えていた「開発の生産性」の可視化に取り組んでみました‼️
とりあえずエレガントさは気にせず、必要な情報が取れればいい!という考えで作ったのであしからず・・

作ったもの

@shiba_yu36 さんがつくられたmerged-pr-statにて取得できるプルリクエストの解析情報をDatadogにカスタムメトリクスとして送信するGitHubActionsです。

merged-pr-statの詳細にについては以下のブログを参照ください。

https://blog.shibayu36.org/entry/2020/08/24/173000

https://github.com/shibayu36/merged-pr-stat

merged-pr-statで取得できる値にgithub.merged_pr_statをプレフィックスとして設定し、Datadogのカスタムメトリとして参照できるようにしました。

項目 内容 datadogメトリクス
count マージされたPullRequestの数 github.merged_pr_stat.count
authorCount PullRequestsを作成した作成者の数 github.merged_pr_stat
additionsAverage 追加された行数の平均 github.merged_pr_stat.additionsAverage
additionsMedian 追加された行数の中央値 github.merged_pr_stat.additionsMedian
deletesAverage 削除された行の数の平均 github.merged_pr_stat.deletesAverage
deletesMedian 削除された行数の中央値 github.merged_pr_stat.deletesMedian
LeadTimeSecondsAverage 最初のコミット日とPullRequestのマージ日の間の平均秒数 github.merged_pr_stat.LeadTimeSecondsAverage
LeadTimeSecondsMedian 最初のコミット日とPullRequestのマージ日の間の秒の中央値 github.merged_pr_stat.LeadTimeSecondsMedian
timeToMergeSecondsAverage 作成されたPullRequestとマージされたPullRequestの間の平均秒数 github.merged_pr_stat.timeToMergeSecondsAverage
timeToMergeSecondsMedian 作成されたPullRequestとマージされたPullRequestの間の秒の中央値 github.merged_pr_stat.timeToMergeSecondsMedian

GitHub Actions

実際に作成したワークフローは以下です。

name: Merged PullRequest statistics DataDog metric

on:
  schedule:
    - cron: '0 0 * * MON'
  workflow_dispatch:

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2

    - name: Set up Python 3.9
      uses: actions/setup-python@v2
      with:
        python-version: 3.9
        
    - name: Install datadog
      run: |
        python -m pip install --upgrade pip
        pip install datadog

    - name: Set Up Node.js
      uses: actions/setup-node@v1
      with:
        node-version: 14
        
    - name: Install merged-pr-stat
      run: |
        npm install -g shibayu36/merged-pr-stat

    - name: Check version
      run: |
        dog -v
        merged-pr-stat -V

    - name: Post merged_pr_stat datadog metrics
      env:
        TZ: 'Asia/Tokyo'
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY }}
        DATADOG_APP_KEY: ${{ secrets.DATADOG_APP_KEY }}
      run: |
        start_time=$(date -d '-7 day' '+%Y-%m-%dT00:00:00')
        end_time=$(date -d '-1 day' '+%Y-%m-%dT23:59:59')
        json=$(merged-pr-stat --start=$start_time --end=$end_time --query="repo:$GITHUB_REPOSITORY base:main")
        echo $json | jq -rc 'to_entries[] |[.key, .value] | @tsv' | xargs -n2 bash -c 'dog metric post github.merged_pr_stat.$0 $1 --tags "repository:$GITHUB_REPOSITORY"'

以下から設定の内容を簡単に説明します。

merged-pr-statコマンドの実行

start_time=$(date -d '-7 day' '+%Y-%m-%dT00:00:00')
end_time=$(date -d '-1 day' '+%Y-%m-%dT23:59:59')
json=$(merged-pr-stat --start=$start_time --end=$end_time --query="repo:$GITHUB_REPOSITORY base:main")

集計範囲の期間を動的に設定

今回は週次での統計の取得を想定しているので、start_timeに7日前0時、end_timeに前日の23時59分を設定しています。

例)
実行時間:05/03(月) 09:00
集計範囲:04/26(月) 00:00 ~ 05/02(日) 23:59

JSTで時刻を取得するようにTZ変数を設定しています。

      env:
        TZ: 'Asia/Tokyo'

また、スケジュール実行の時間も月曜の9時に設定しています。

on:
  schedule:
    - cron: '0 0 * * MON'

GITHUB_TOKENの設定

merged-pr-statコマンドを実行するには、アクセストークンの取得が必要です。
しかしGitHub Actionsを利用するとGITHUB_TOKENシークレットが自動で生成されます。

https://docs.github.com/ja/actions/reference/authentication-in-a-workflow

その為、個別のでアクセストークンは発行せず、シークレットの値を変数の値として設定することでアクセストークンを設定できます。

      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

queryの設定

クエリでは集計対象のリポジトリと、プルリクの条件をmainブランチに対するプルリクエストに指定しています。

query="repo:$GITHUB_REPOSITORY base:main"

リポジトについては、このActionsが実行されているリポジトリ名を、環境変数より取得して設定しています。

https://docs.github.com/ja/actions/reference/environment-variables

Datadogへのメトリクスの送信

echo $json | jq -rc 'to_entries[] |[.key, .value] | @tsv' | xargs -n2 bash -c 'dog metric post github.merged_pr_stat.$0 $1 --tags "repository:$GITHUB_REPOSITORY"'

Datadogへのメトリクスの送信はDogshellコマンドを使って送信しています。

https://docs.datadoghq.com/ja/developers/guide/dogshell-quickly-use-datadog-s-api-from-terminal-shell/

DatadogAPIキーの設定

Datadogへ接続するためのAPIキーは、シークレット変数としてリポジトリに設定することで、セキュアに設定できるようにしています。

      env:
        DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY }}
        DATADOG_APP_KEY: ${{ secrets.DATADOG_APP_KEY }}

https://docs.github.com/ja/actions/reference/encrypted-secrets

メトリクスの送信

dog metric post github.merged_pr_stat.$0 $1 --tags "repository:$GITHUB_REPOSITORY"

複数のリポジトにてメトリクスを送信したときに、Datadogでリポジトリ単位でフィルタできるように、タグとしてリポジトリ名を設定しています。
ダッシュボード作成時などは、タグを指定することで、任意のリポジトリの集計を確認することが可能です。

まとめ

今回はとりあえずDatadogへメトリクスとしてデータを収集できる仕組みまで入れました。
Actionsを利用するとGITHUB_TOKENの発行が不要なのが便利なのと、スケジュール実行させることで一度組み込めば継続的にデータを収集できるのが便利です!

これでいつでもDatadog上で可視化させることが可能なので、生産性の可視化としてどのようなダッシュボードを作ればいいか考えて、開発側へ展開していきたいと思います!