スタディサプリ Product Team Blog

株式会社リクルートが開発するスタディサプリのプロダクトチームのブログです

GitHub Actions で Working out Loud を効率化しよう!

GitHub Actions × Working out Loud

最終更新日: 2024年10月30日(水)

1. ご挨拶

こんにちは。 前回の「社内技術ドキュメンテーションを科学する」から10ヶ月の投稿になります、@hayat01sh1daです(実はエントリーはあったのですが没になりまして...アウトプット欲はいつでもあるのです)。
22年人生を共にした愛猫を今年の4月に亡くし、しばらくかなり傷心していたのですが、今は作業デスクから優しく見守ってもらいつつ毎日を過ごしています。

Nana

近々新しい子をお迎えする予定ですが、写真の彼のことは一生忘れずに愛でたいと思います。

2. 今回のトピック

閑話休題、皆さんは Working out Loud されていますか?
私はしている...つもりなのですが、気を抜くと作業開始宣言をついつい忘れてしまいます。
ですが、重要性は重々理解しています(当部署から良い記事が出ていますので、「Working Out Loud 大声作業(しなさい)、チームメンバー同士でのトレーニング文化の醸成」を是非ご通読下さい)。

プログラマは「3回同じことを繰り返す作業は仕組み化せよ!」と言われますが、それは作業だけでなく失敗にも当てはまることですね。
そういう訳で、同じ失敗を3回繰り返したということは仕組み化する絶好の好機と捉え、みんな大好き GitHub Actions(以下 GHA) でワークフローを組みました。
とっっっても簡単なので、読んで下さる皆さんも是非ご自分なりのアレンジを加えて活用してみて下さい。

3. 要件

「気を抜くと忘れてしまう」と先述しましたが、その理由は以下の3つの一連の作業の面倒さが私の潜在意識にありました。

  1. PBI/SBI に自分をアサインする。
  2. PBI/SBI の URL をコピーする。
  3. 2 でコピーした URL を貼り付けると共に「〇〇の作業をやります!」と作文し投稿する。

上記1-3の手順は着手する PBIs/SBIs の数だけ、すべからくN倍回繰り返さなければなりません。

あまつさえ、私のチームでは「作業を外部要因で手放す時も宣言しよう」という Working Agreement がありますので、さらに以下の3つの一連の作業が加わります。

  1. PBI/SBI の Assingees から自分を外す。
  2. PBI/SBI の URL をコピーする。
  3. 2 でコピーした URL を貼り付けると共に「〇〇の作業を断念します!」と作文し投稿する。

上記1-3の手順も手放する PBIs/SBIs の数だけ、すべからくN倍回繰り返さなければなりません。
塵も積もれば山となり、相当な労力と時間を地味ではありますが費やすことになります。
同じ失敗を3回繰り返した今こそ、上述の面倒で冗長な作業から解放されるべく、仕組み化するための全力を費やす時です!
Be hardworking to be lazy!

4. 仕様

私には School Career チーム という所属先がありますので、School Career Work Initiation というラベルを1つ作り、Issue 上での当該ラベルの脱着によって GHA の以下のそれぞれのワークフローを発火させます。

Issue の Assignees の制御には auto-assign-issue 、Slack 通知には slack-github-action (こちらは Slack 公式) の Third-party Libraries を活用させて頂きました。

4-1. School Career Work Initiation ラベル付与時

  1. GHA の Actor (発火させた人)を Issue の Assignees に加える。
  2. Payload のテンプレートに埋め込んだ変数を展開し、Slack の指定チャンネルにメッセージを通知する。

.github/workflows/school-career-work-initiation.yml

name: School Career Work Initiation

on:
  issues:
    types:
      - labeled # `School Career Work Initiation` ラベル付与時に発火

jobs:
  notify:
    if: github.event.label.name == 'School Career Work Initiation'
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - name: Auto-assign The Actor
        uses: pozil/auto-assign-issue@v2
        with:
          assignees: ${{ github.actor }} # GitHub Actions の Actor (発火させた人) を Assignees に入れる
      - name: Slack Notification
        uses: slackapi/slack-github-action@v1
        env:
          SLACK_BOT_TOKEN: ${{ secrets.SLACK_APP_TOKEN }}
        with:
          channel-id: ${{ 通知先 channel-id }}
          payload: | # この Payload はお好きなように!
            {
              "blocks": [
                {
                  "type": "header",
                  "text": {
                    "type": "plain_text",
                    "text": "作業開始宣言"
                  }
                },
                {
                  "type": "section",
                  "text": {
                    "type": "mrkdwn",
                    "text": "From: @${{ github.actor }}"
                  }
                },
                {
                  "type": "section",
                  "text": {
                    "type": "mrkdwn",
                    "text": "To: @school-career-devs @school-career-tpms"
                  }
                },
                {
                  "type": "section",
                  "text": {
                    "type": "mrkdwn",
                    "text": "PBI/SBI: <${{ github.event.issue.html_url }}|${{ github.event.issue.title }}>"
                  }
                },
                {
                  "type": "section",
                  "text": {
                    "type": "mrkdwn",
                    "text": "Message: 作業に着手します!"
                  }
                }
              ]
            }

4-2. School Career Work Initiation ラベル除去時

  1. GHA の Actor (発火させた人)を Issue の Assignees から外す。
  2. Payload のテンプレートに埋め込んだ変数を展開し、Slack の指定チャンネルにメッセージを通知する。

.github/workflows/school-career-work-abortion.yml

name: School Career Work Abortion

on:
  issues:
    types:
      - unlabeled # `School Career Work Initiation` ラベル除去時に発火

jobs:
  notify:
    if: github.event.label.name == 'School Career Work Initiation'
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - name: Auto-unassign The Actor
        uses: pozil/auto-assign-issue@v2
        with:
          assignees: n/a # Assignees を空にする(ここは他に Assinees がいた場合空になるとまずいので要改良)
          allowNoAssignees: true
          removePreviousAssignees: true
      - name: Slack Notification
        uses: slackapi/slack-github-action@v1
        env:
          SLACK_BOT_TOKEN: ${{ secrets.SLACK_APP_TOKEN }}
        with:
          channel-id: ${{ 通知先 channel-id }}
          payload: | # この Payload はお好きなように!
            {
              "blocks": [
                {
                  "type": "header",
                  "text": {
                    "type": "plain_text",
                    "text": "作業断念宣言"
                  }
                },
                {
                  "type": "section",
                  "text": {
                    "type": "mrkdwn",
                    "text": "From: @${{ github.actor }}"
                  }
                },
                {
                  "type": "section",
                  "text": {
                    "type": "mrkdwn",
                    "text": "To: @school-career-devs @school-career-tpms"
                  }
                },
                {
                  "type": "section",
                  "text": {
                    "type": "mrkdwn",
                    "text": "PBI/SBI: <${{ github.event.issue.html_url }}|${{ github.event.issue.title }}>"
                  }
                },
                {
                  "type": "section",
                  "text": {
                    "type": "mrkdwn",
                    "text": "Message: 作業を断念します :pray:"
                  }
                }
              ]
            }

5. 結果

School Career Work Initiation の脱着で以下の挙動が実現出来ました。

  1. 初期状態として Labels も Assignees も空である。
    Work Initiation Step1
  2. ラベルを付与し、GHA が発火してからページをリロードすると Assignees に自分が入っている。
    Work Initiation Step2
    Work Initiation Step3
  3. ラベルを除去し、GHA が発火してからページをリロードすると Assignees から自分が外れている。
    Work Abortion Step1
    Work Abortion Step2
  4. Slack にも通知が飛んでいる。
    Slack Notifications

.github/workflows/school-career-work-abortion.yml > Auto-unassign The Actor > with > assigneesn/a ではなく、既存の Assignees を取得してその中から ${{ github.actor }} を除去して差集合を求める必要がありますね。
私のチームでは複数人が1つのチケットにアサインされるのはレアケースなので、修正はゆっくり行いたいと思います。

次回は「Ruby/Python + Shellscript + GitHub Actions でカオスな GitHub Wiki に秩序を与えて治安改善を行なった話」をエントリーしたいと思います。
それでは、皆さんも良き Working out Loud ライフを!