blog

DeNAのエンジニアが考えていることや、担当しているサービスについて情報発信しています

2024.09.20 技術記事

IT戦略メンバーによる自己業務効率化の記録

by Shunichi Yoshii

#blog #github-actions #google-apps-script #slack #情シス

はじめに

こんにちは。IT戦略部システム開発グループ(以下、システム開発G)所属のyoshiiです。

普段は、システム開発Gで主に社内システムの内製開発やその保守、既存のSaaSシステムの運用業務を効率的に自動化するような取り組みを行っています。

今回は、私が日々の業務の中でちょっとした効率化を行なった記録をゆるく書いてみます。

その1: GitHub Enterpriseでのリリースタグ自動生成

背景

DeNAのエンジニアは、基本的にGitHub Enterpriseを使ってコードを管理しています。

そして、システム開発Gの開発フローでは、本番環境へのリリース後にリリースタグを打つことがルールになっています。

これは、git-flowを採用しているためです。(リリースタグの作成はGitHubのReleases機能を使って代用していますが、基本的な考え方は同じです)

問題

この背景において、リリース後にリリースタグを作成する作業を忘れることがたまにありました。

我々のチームの運用上、本番へのリリースのトリガーはmainブランチへのマージであり、リリースタグを作成するのはその後の作業です。

なので、リリース作業者にとってはmainブランチにマージした段階でリリース業務は完了してしまい、リリースタグを打つことを忘れることが多々ありました。

とはいえ、リリースタグを打つことは重要な作業であり、リリース後のリリースタグがあると、リリースした時点のコードにcheckoutするなどの作業がしやすくなります。

解決策

そこで、GitHub Actionsでリリース後にリリースタグを自動生成するようにしました。

仕様は以下の通りです。

  1. mainブランチへのマージ後、リリースタグを自動生成する
  2. タグ名はブランチ名から生成する
    • システム開発Gのリリースブランチ名は release-<version> または hotfix-<version> という命名規則になっているので文字列を操作して生成可能
  3. リリースタグのメッセージは、リリースに含まれるプルリクエストのタイトルから生成する

実装

Release Drafter というオープンソースのGitHub Actionsを利用して実装しています。

ドキュメントを参考に、以下のようなファイル .github/workflows/release-tag.yml を作成しました。

name: Auto Release Tag

on:
  pull_request:
    branches:
      - main
    types:
      - closed

jobs:
  release-tag:
    # プルリクエストがマージされた場合、かつリリース用ブランチの命名規則に従っている場合のみ実行する
    if: github.event.pull_request.merged == true && (startsWith(github.head_ref, 'release-') || startsWith(github.head_ref, 'hotfix-'))
    # Actionsランナーの指定
    runs-on:
      group: dena
      labels:
        - dena-small
    permissions:
      # このActionsで必要な権限を指定
      contents: write
      pull-requests: write
    env:
      # ブランチ名を環境変数に登録する
      BRANCH_NAME: ${{ github.head_ref }}
    steps:
      - name: export TAG_NAME
        run: |
          # ブランチ名からタグ名を生成する
          # prefixを除いたブランチ名を取得
          NOT_PREFIX_BRANCH_NAME=${BRANCH_NAME#*-}
          # suffixを除いたブランチ名を取得(version番号)
          VERSION=${NOT_PREFIX_BRANCH_NAME%%_*}
          # タグ名を生成
          TAG_NAME=v${VERSION}
          # 環境変数に登録
          echo "TAG_NAME=${TAG_NAME}" >> $GITHUB_ENV          
      - name: Set GHE_HOST
        run: |
          # GitHub Enterpriseのホスト名を環境変数に登録する
          echo "GHE_HOST=${GITHUB_SERVER_URL##https:\/\/}" >> $GITHUB_ENV          
      - name: Create Release Tag
        uses: release-drafter/release-drafter@v5
        env:
          # このトークンは自動生成されるのでsecretsを登録する必要ない
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag: ${{ env.TAG_NAME }}
          publish: true

mainブランチにマージされたプルリクエストが、リリース用ブランチの命名規則にしたがっている場合、ブランチ名からタグ名を生成し、リリースタグを自動生成するようになりました。

echo "GHE_HOST=${GITHUB_SERVER_URL##https:\/\/}" >> $GITHUB_ENV の箇所では、GitHub Enterpriseのホスト名を、Release Drafter で定義されている環境変数 GHE_HOST に登録しています。

また、リリースタグのメッセージ部分は以下のファイル .github/release-drafter.yml を用いて設定しています。

template: |
    $CHANGES

$CHANGES は、リリースに含まれるプルリクエストのタイトルを一覧で表示する変数です。

この辺の変数についても、 Release DrafterのREADME に詳細が記載されているので、参考にしてください。

実際にリリースタグが自動生成された様子

リリースタグが自動生成された様子

リリースタグが自動生成された様子

以上で、リリース後のリリースタグの自動生成が実装されました。

調べた感じ、GitHub Enterpriseでリリースタグ自動作成のActionsをやってる人があまりいなかったと思うので、こちらが参考になれば幸いです。

その2: アラート当番通知Google Apps Script(以下、GAS)作成

背景

システム開発Gでは、毎日内製社内システムのアラート監視を行っています。

私の所属するチームでは、基本的に毎日定例ミーティングのタイミングで、アラートを確認しシステムのエラーログを確認することになっています。

ただし、毎週火曜を個々人が作業に集中するために定例ミーティングを行わない日としており、その日に限ってはアラートを確認する人を当番制で決めています。

一応、以前までも毎週交代で当番を決めており、Slack上で「今日は私が当番です」等のコミュニケーションは行っていたのですが、当番を忘れてしまったり、逆に自分が当番と勘違いして重複してアラートを確認してしまうこともありました。

ちょっとしたコミュニケーションコストですが、これを毎週火曜の朝に誰が当番かを自動で通知させれば、もっとスムーズだなと思いました。

解決策1

自動化しようと思って、真っ先に思いついたのはSlackのリマインダー機能やワークフローを使うことでした。

ただ、困ったことにSlackのリマインダー機能で、毎週火曜の朝に通知を送ること自体は可能ですが、その通知を送る人を毎週交代で設定できないのです。

Slack側に[aさん, bさん, cさん]のようなリストを持たせ、member変数に週ごとに交代でメンバーの名前を代入し、「今日は${member}がアラート担当です」のような通知を送れたら良かったのですが、Slackの標準の機能でこれは実現できなさそうでした。

一応、検討した内容としては、以下のリマインダー設定をメンバーごとに個別で設定することで、週ごとに交代で通知を送ること自体は可能でした。

  • /remind #channel "今日はaさんがアラート確認担当です" every 3 weeks 8/6 at 9:00am
  • /remind #channel "今日はbさんがアラート確認担当です" every 3 weeks 8/13 at 9:00am
  • /remind #channel "今日はcさんがアラート確認担当です" every 3 weeks 8/20 at 9:00am

ただ、これだとメンバーが増えたり減ったりした場合に、リマインダーの設定を変更する手間がかかるのと、リマインダーの設定方法がメンバーごとに異なるため、管理が複雑になると感じました。

なので、通知の設定箇所は1箇所にまとめ、設定者が不在の状況でも設定内容の変更・無効化を簡単に行えるようにしたいと考えました。

参考

解決策2

そこで、GASを使って、毎週火曜の朝にアラート当番を通知するスクリプトを作成しました。

実際のスクリプトは以下の通りです。

// webhookUrl
// 通知先チャンネル: https://xxxx.enterprise.slack.com/archives/XXXXXXXX
// SlackApp: https://api.slack.com/apps/XXXXXXXX
const webhookUrl = "https://hooks.slack.com/services/XXXXXXXX/XXXXXXXX/XXXXXXXX";

// 2024/06/11は火曜日で、Aさんが担当の週。これを起点に、誰が担当か計算する。
const startDate = new Date("2024-06-11T00:00");

// 順番変わったり、メンバー変わったらここを変える
const members = [
  "A",
  "B",
  "C",
];

function main() {
  const now = new Date();

  // 2024/06/11から何週間経ったか計算
  const weeksPassed = Math.floor((now.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24 * 7))

  const targetMember = members[weeksPassed % members.length];

  const message = `${targetMember}さんが今週のアラート当番です。\n\n※ この通知は以下のGASから送信されています。\nhttps://drive.google.com/drive/u/0/folders/XXXXXXXXXXXXXXXX`;

  // webhookUrlにPOSTリクエストを送り、通知を送信
  const jsonData = {
    "text": message
  };
  const payload = JSON.stringify(jsonData);
  const options = {
    "method": "post",
    "contentType": "application/json",
    "payload": payload
  };

  UrlFetchApp.fetch(webhookUrl, options);
}

とくに難しいことはしていませんが、members 配列のメンバーの順番でアラート当番を通知するスクリプトを作成しました。

あとは、GASのトリガーを設定して、毎週火曜の朝にこのスクリプトを実行するようにすれば、毎朝の通知が自動で行われるようになります。

また、通知メッセージには、通知の送信元を明示するため、GASのスクリプトが配置された共有Googleドライブフォルダーのリンクを記載しています。

これにより、メンバーの変更や順番の変更があったり、そもそもこの通知をやめたくなったりした場合の対応が明確になりました。

参考

実際に通知された様子

通知された様子

通知された様子

おわりに

以上、私が日々の業務の中でちょっとした効率化を行なった記録をゆるく書いてみました。

自分やチームがやっている作業に対しては、とくに効率化の余地への嗅覚が働くため、自然と効率化のアイデアが浮かぶことが多いです。

また、システム開発Gでは、日々の業務に対して効率化の余地があればそれを柔軟に取り入れる文化が根付いており、こういったアイデアを形にしやすい環境にあると感じています。

今回の記事が、読者の方の自己業務効率化のモチベーションアップに繋がれば幸いです!

最後まで読んでいただき、ありがとうございます!
この記事をシェアしていただける方はこちらからお願いします。

recruit

DeNAでは、失敗を恐れず常に挑戦し続けるエンジニアを募集しています。