Gunosy Tech Blog

Gunosy Tech Blogは株式会社Gunosyのエンジニアが知見を共有する技術ブログです。

企業テックブログのレビューを GitHub 上でおこなっている話

はじめに

こんにちは m-hamashita です。

この記事は Gunosy Advent Calendar 2023 の 4 日目の記事です。 3 日目の記事は TksYamaguchi さんのいろんなやり方の読書会をやってみたら当日音読その場でまとめ方式が最高だった話でした。

今回はテックブログのレビューを GitHub 上でするようになって 1 年ほど経ったので、その経緯とリポジトリの紹介をしたいと思います。 個人的にかなり運用が楽になったので、ぜひ見てもらえると嬉しいです。

今までのブログレビュー

今まではブログ用の Slack チャンネルで有志にレビューをお願いし、スレッドでレビューをおこなっていました。

Slack でのレビューの様子

そこでは以下のような問題を感じていました。

  • レビュー箇所をコピー&ペーストしてレビューするのが面倒
  • レビュー内容が反映されないことがあった
  • レビューされないまま公開される場合があった
  • 毎回同じようなレビュー(例:スペースの使い方の統一)をおこなっていた

現在のブログレビュー

GitHub リポジトリでブログを管理することで、先述した問題の解決を試みました。 最近公式でテンプレートリポジトリが公開されたので、これからレビューリポジトリを作成する場合はこちらを使用し、この記事で使えそうな部分があればそれを取り入れるという形が良さそうです。

github.com

GitHub でのレビューの様子

レビュー箇所を指定してレビューすることができるようになり、レビュー箇所をコピー&ペーストする必要がなくなりました。 また、commit suggestion を使うことで、レビューされた側の修正も楽になりました。

現在のレビューの流れは以下のようになっています。

  • main ブランチからブランチを切る
  • はてなブログ上で下書きを作成し、カスタム URL を設定する
  • ./pull (後述)を実行して、下書き(markdown)を取得する
  • リモートにプッシュして、(完成していなければ draft で)Pull Request を出す
  • markdown を編集して記事を書く
    • プッシュすると CI によって下書きが同期される
    • (画像アップロード等)はてなブログ上で編集した場合は、./pull(or ./fetch) を実行することで同期する
  • 書ききったら Ready for Review にして、レビューを依頼する
  • レビューが完了したら、記事を公開(予約投稿)する

ブログの同期

はてなブログとリポジトリの同期には blogsync を用いました。 blogsync は、はてなブログ用の CLI クライアントです。これを使うと、ブログのダウンロードや、更新などをおこなうことができます。

github.com

パッケージのインストールには aqua を使っています。今回インストールしたパッケージは以下のようになっています。

registries:
  - type: standard
    ref: v4.92.2 # renovate: depName=aquaproj/aqua-registry
packages:
  - name: x-motemen/blogsync@v0.20.1
  - name: stedolan/jq@jq-1.7
  - name: a8m/envsubst@v1.4.2

blogsync では blogsync.yaml というファイルを用いて、はてなブログの設定をおこないます。 一方弊社ではテックブログデータ分析ブログの 2 つのブログを運用しています。そのため、単一の blogsync.yaml では設定をおこなうことができず、少し工夫が必要でした。

ブログの取得

はてなブログ上にあるブログを取得する pull は以下のようになっています。ここでは、はてなブログの API キーなどを Secrets Manager に保存しています。 先述したように 2 つのブログを運用しているため、今回は template ファイルと envsubst を用いて、ブログごとに設定を変えるようにしています。

#!/bin/bash
set -e

SECRET=$(aws secretsmanager get-secret-value --secret-id "techblog" | jq -r '.SecretString')
export API_KEY=$(echo "$SECRET" | jq -r '.api_key')
export USER_NAME=$(echo "$SECRET" | jq -r '.user_name')

if [ "$#" -eq 1 ] && { [ "$1" == "data" ] || [ "$1" == "tech" ]; }; then
    envsubst < "${1}_blogsync.yaml.template" > blogsync.yaml
    blogsync pull "gunosy-${1}.hatenablog.com"
    rm blogsync.yaml
elif [ "$#" -eq 0 ]; then
    envsubst < "data_blogsync.yaml.template" > blogsync.yaml
    blogsync pull "gunosy-data.hatenablog.com"
    rm blogsync.yaml
    envsubst < "tech_blogsync.yaml.template" > blogsync.yaml
    blogsync pull "gunosy-tech.hatenablog.com"
    rm blogsync.yaml
else
    echo "Usage: $0 [data|tech]"
    exit 1
fi

上記で指定されている template ファイルは以下のようになっています。

gunosy-tech.hatenablog.com:
  username: ${USER_NAME}
  password: ${API_KEY}
default:
  local_root: ./

リポジトリと下書きの同期

リポジトリを作成してすぐの頃は、手動で GitHub とはてなブログを同期していました。そうすると、GitHub 上では修正されているのに、はてなブログ上では修正されていなかったり、逆にはてなブログ上では修正されているのに、GitHub 上では修正されていなかったりすることがありました。

これを解消するために、Pull Request を作成すると CI によって、ブログの下書きが更新されるようにしました。これによって、レビューをおこなう際に GitHub と下書きの内容が同期されるようになりました。

以下は、(テック)ブログの下書きを更新する GitHub Actions の設定です*1*2。 これによって GitHub とはてなブログの下書きが同期され、手動で同期する必要がなくなり、上記の問題を解消することができました。

name: push to tech blog
on:
  pull_request:
    paths:
      - gunosy-tech.hatenablog.com/entry/**
jobs:
  push:
    name: push
    runs-on: ubuntu-latest
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    steps:
      - uses: actions/checkout@v3
      - name: Get changed files
        id: changed-files-specific
        uses: tj-actions/changed-files@v35
        with:
          files: gunosy-tech.hatenablog.com/entry/**
      - uses: aquaproj/aqua-installer@v2.0.2
        with:
          aqua_version: v1.34.2
      - name: Setup tech blogsync
        run: |
          echo "${{ secrets.TECH_BLOG_CONFIG_YAML }}" > blogsync.yaml
      - name: push blog to hatena blog
        run: |
          for file in ${{ steps.changed-files-specific.outputs.all_changed_files }}; do
            blogsync push $file
          done

余談ですが、pull がすべてのブログを更新するのに対して、指定したブログのみを更新したいときに使う fetch は以下のようになっています。

#!/bin/bash

set -e

SECRET=$(aws secretsmanager get-secret-value --secret-id "techblog" | jq -r '.SecretString')
export API_KEY=$(echo "$SECRET" | jq -r '.api_key')
export USER_NAME=$(echo "$SECRET" | jq -r '.user_name')

tech_blog_pattern="*gunosy-tech.hatenablog.com/entry/*"
data_blog_pattern="*gunosy-data.hatenablog.com/entry/*"

if [ "$#" -eq 1 ] && [[ "$1" == $tech_blog_pattern ]]; then
    envsubst < "tech_blogsync.yaml.template" > blogsync.yaml
    blogsync fetch "$1"
    rm blogsync.yaml
elif [ "$#" -eq 1 ] && [[ "$1" == $data_blog_pattern ]]; then
    envsubst < "data_blogsync.yaml.template" > blogsync.yaml
    blogsync fetch "$1"
    rm blogsync.yaml
else
    echo "Usage: $0 <path/to/file>"
    exit 1
fi

textlint の導入

似たようなレビューを繰り返していたので、機械的に検知できる部分は CI に任せたいという思いがありました。 そこで、textlint を導入しました。 textlint は、テキストファイルの構文や文章の書き方をチェックするツールで、プラグインを利用することで、様々なチェックをおこなうことができます。

また、action-textlint を用いることで、 textlint の結果を Pull Request のコメントとして表示することができます。 自動修正可能なものについては変更を suggest してくれるため、修正も容易です。

reviewdog による commit suggestion

以下に GitHub Actions の設定を示します。

name: reviewdog
on: [pull_request]
jobs:
  textlint:
    name: runner / textlint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true
      - name: textlint-github-pr-review
        uses: tsuyoshicho/action-textlint@v3
        with:
          github_token: ${{ secrets.github_token }}
          reporter: github-pr-review
          level: warning
          textlint_flags: "**/*.md"

現在はルールをあまり設定していません。これはルールをたくさん設定すると、GitHub Actions のコメントで埋まってしまう & 人によって流儀が異なるといったことがあったため、いったん最低限の設定にしています*3

導入した結果

導入した結果、過去のレビューの問題点がどのようになったか、また反省点について振り返ります。

  • 問題点振り返り
    • レビュー箇所をコピー&ペーストしてレビューするのが面倒
      • → GitHub でレビューできるようになり、レビュー箇所を指定してレビューできるようになった
      • commit suggestion を使うことで、修正も楽になった
    • レビュー内容が反映されないことが多々あった
      • →場所を指定してレビューできるので、修正されているか確認しやすくなった
    • レビューされないまま公開される場合があった
      • →(意識的な問題か)レビューされずに公開されることはなくなった
    • 毎回同じようなレビューをおこなっていた
      • → textlint で多少カバーできているが、まだ同じような指摘をおこなうことがある*4
  • 反省: 環境構築が難しい人がいた
    • 全エンジニアが AWS CLI を入れていると思っていたがそうではなかった
    • → README を手厚く書いたり、導入をサポートした。それでも難しい人のために、代替案を用意した

まとめ

今回は、ブログのレビューを GitHub リポジトリでおこなうことで、レビューの効率化をおこないました。 今後はブログレビューをより効率化するために以下のことをしていきたいと思っています*5

  • hatenablog-workflows などのエッセンスを取り入れる
    • 下書き作成から pull までを一貫して実行
  • textlint の設定を拡充する
    • はてなブログに合わせたルールの自作
  • ブランチルールによる draft Pull Request の自動作成

明日は hyamamoto さんが稼働中のデータ基盤を安全に dbt 移行する仕組みについて書くそうです!とても楽しみです!

*1:blogsync.yaml の取得に secrets コンテキストを用いていますが、 pull でおこなったように修正したいですね

*2:最近 blogsync に GitHub Actions が追加されていましたのでこちらを使うと良さそうです https://github.com/x-motemen/blogsync?tab=readme-ov-file#github-actions

*3:個人的に設定したいルールはたくさんあります

*4:ルールを実装しようと思っていましたが間に合いませんでした

*5:このブログを書いているときに GPT でのレビューが追加されていました。雰囲気良さそうな部分もあったので、ブログでも初手のレビューとして GPT を動かすというのも良さそうです