シンクロ・フード エンジニアブログ

飲食店ドットコムを運営する、株式会社シンクロ・フードの技術ブログです

はてなブログの記事を GitHub で管理する | HatenaBlog Workflows Boilerplate の導入

はじめに

こんにちは、第四開発Gの四之宮です。
最近は、求人飲食店ドットコムグルメバイトちゃんの開発・レビューのほか、Claude Code に Figma の URL を渡してマークアップを生成する仕組みづくりと、その精度改善に取り組んでいます。
また、当エンジニアブログの編集チームにも所属しており、今回の導入もその立場で進めたものです。

このたび、当エンジニアブログの運用に HatenaBlog Workflows Boilerplate(β) を導入し、記事の執筆からレビューまでを GitHub 上で完結できるようにしました。

この記事では、導入に至った経緯と、実際にどのような運用になったのかを紹介します。

導入前の運用と課題

このブログの執筆者は社内のエンジニア全員ですが、はてなブログの管理者は編集チームの数人だけでした。そのため、以下のような運用になっていました。

  1. 執筆者が esa(社内で利用しているドキュメント共有サービス)で記事を書く
  2. esa 上でレビューを行う
  3. 編集チームが、完成した記事をはてなブログの管理画面に転記する

この 3 の「転記」がなかなか厄介でした。
記法の異なる 2 つのサービス間で内容をコピーすることになるため、以下のような問題が起きていました。

  • Markdown の記法が異なる
    • esa とはてなブログで記法に差があるため、転記後に表示が崩れていないかを確認し、都度直す必要がありました
  • 画像のアップロードが面倒
    • esa に貼られた画像を 1 枚ずつダウンロードし、はてなフォトライフに上げ直す必要がありました
  • 反映後の修正が面倒
    • 公開後に修正が入ると、esa とはてなブログのどちらを直すのかという話になります。片方だけ直すと、両者の内容が少しずつずれていきます

なお、はてなブログには複数人でブログを編集・管理できるブログメンバーという機能があり、執筆者を寄稿者として招待すれば、自分のアカウントで直接記事を書くこともできます。
実際にこちらを利用していた執筆者も数人いましたが、多くはその方法を選ばず、大半の記事は先ほどのフローで公開されていました。

執筆者と編集チームが分かれていること自体は体制上避けられないのですが、その間に人力のコピー作業が挟まっている状態は効率が悪いため、改善したいと考えていました。

導入の前後で、記事を公開するまでの流れは以下のように変わりました。

導入前と導入後の記事公開フロー

HatenaBlog Workflows Boilerplate とは

HatenaBlog Workflows Boilerplate(β) は、企業がはてなブログで技術ブログを運営する際の、運営フローを支援する目的ではてなから提供されているリポジトリテンプレートです。

GitHub Actions と blogsync を組み合わせることで、はてなブログとリポジトリの記事を同期します。特徴的なのは、下書きを作成すると自動的にプルリクエストが作成される点です。これにより、記事のレビューを普段のコードレビューと同じ仕組みに乗せることができます。

執筆者が書いたものがそのままはてなブログに同期されるのであれば、課題であった「転記」の工程自体をなくせます。そこが導入の決め手になりました。

セットアップ

GitHub Enterprise Server での導入は見送った

当初は社内の GitHub Enterprise Server(以下 GHES)で導入を進めようとしていたのですが、途中で方針を変えました。

Boilerplate の各 workflow は、それ自体は処理を持っておらず、はてなが github.com 上で公開している hatena/hatenablog-workflows の Reusable Workflow を呼び出すだけのラッパーになっています。

jobs:
  create-draft:
    uses: hatena/hatenablog-workflows/.github/workflows/create-draft.yaml@8564b85b51cda20eb962f0dec3bf3fcff3dd0326 # v2.0.7

しかし GHES には、github.com 上で定義された Reusable Workflow を直接呼び出せないという制約があります。

You cannot directly use reusable workflows defined on GitHub.com. Instead store a copy of the reusable workflow on your GitHub Enterprise Server instance, and call the workflow from that path.

Reusable workflows reference - GitHub Enterprise Server Docs

GHES で動かすには、はてなが提供している workflow 一式を自社インスタンスにコピーして持ち込む必要がある、ということです。

コピーを持つこと自体は不可能ではありません。ただ、この Boilerplate は「参照している Actions のバージョンを Renovate や Dependabot で更新すれば、機能追加やバグ修正が反映される」という前提で設計されています。コピーを抱えると、その更新に自前で追随し続けることになります。

また、blogsync ははてなブログの AtomPub API を利用するため、実行時にもランナーから外部への通信が必要になります。

ブログ運用のためにそこまでのコストを払う必要はないと判断し、github.com 上のリポジトリで運用する形に落ち着きました。

実際にやったこと

セットアップ手順は README に詳しく記載されているので、ここでは要点だけ挙げます。

  1. Boilerplate リポジトリの「Use this template」から新しいリポジトリを作成する
  2. blogsync.yaml にブログのドメインとオーナーのはてな ID を記述する
  3. リポジトリの Variables に BLOG_DOMAIN を、Secrets にブログオーナーの API キー OWNER_API_KEY を登録する
  4. Actions の Workflow permissions を Read and write permissions に変更し、Allow GitHub Actions to create and approve pull requests を有効にして、Actions からプルリクエストを作成できるようにする
  5. Branches の設定から、main ブランチに対する branch protection rule を作成する
  6. General の設定から、Allow auto merge を有効にする
  7. initialize workflow を実行して、既存の記事をリポジトリに同期する
  8. はてなブログ側の編集モードを Markdown モードに設定する

7 を実行すると、これまで公開してきた記事がすべて含まれたプルリクエストが作成されます。これをマージすることで、はてなブログとリポジトリの状態が揃います。当ブログは 2016 年から記事があるので、それらがまとめてリポジトリに入ってくるのはなかなか壮観でした。

実際の運用フロー

導入後は、以下の流れで記事を公開しています。

1. 下書きを作成する

Actions から create draft を実行し、記事タイトルを入力すると、下書き記事のファイルを含むプルリクエストが自動で作成されます。あとは作成されたブランチで draft_entries/ 配下のファイルを書いていくだけです。

先ほど触れた寄稿の形で書きたい場合は、はてなブログ側で下書きを作成してから pull draft from hatenablog で取り込む方法もあります。記事の署名が執筆者個人のアカウントになるのが、こちらの利点です。取り込んだ後はリポジトリ上の記事ファイルになるため、以降はどちらの方法でも同じフローに乗せられます。

2. プルリクエスト上でレビューする

あとは通常のコードレビューと同じように、プルリクエスト上で指摘し、修正していきます。当ブログでは、まず執筆者のチーム内でレビューを行い、そのうえで編集チームにレビューを依頼する、という二段階にしています。

下書き記事に限り、ブランチにプッシュした時点ではてなブログに同期されます。そのため、実際のブログでの見え方をプレビューで確認しながらレビューを進められます。記法の違いによる崩れを公開後に見つける、ということがなくなりました。

当リポジトリでは .github/PULL_REQUEST_TEMPLATE/draft.md を用意し、プルリクエストの作成時に編集画面の URL やプレビュー URL が自動で埋め込まれるようにしています。

なお、記事内で相対パス指定した画像は、upload images to fotolife という自動コミットではてなフォトライフへアップロードされ、記事内の URL もあわせて書き換わります。画像を手で上げ直す必要はありません。

画像を追加すると自動でフォトライフへアップロードされる

3. 公開する

Boilerplate の標準的なフローでは、記事の先頭にある Draft: true の行を削除してプルリクエストを main にマージすると、記事が公開されます。同時に、記事ファイルが draft_entries/ から entries/ へ自動的に移動します。

ただし当ブログでは、はてなブログの予約投稿機能を使いたいという事情がありました。
Boilerplate から予約投稿を行うことはできないため、README に記載されている手順に沿って、以下の運用にしています。

  1. プルリクエストをクローズする
  2. はてなブログの編集画面から予約投稿を設定する
  3. 記事が公開されたら pull from hatenablog を実行し、公開済みの記事をリポジトリに同期する

3 については、実行しても同期用のプルリクエストが作成されるだけなので、それをマージするところまでが必要です。ここは定期実行にしてもよさそうだと考えています。

また、タグ・カテゴリ・アイキャッチ画像については、記事の内容を踏まえて編集チームが判断し、はてなブログの編集画面から設定しています。ここはリポジトリ側で完結していない部分です。

公開後に修正が必要になった場合も、リポジトリ上で修正して main にマージすれば、はてなブログに反映されます。「どちらが正なのか」で悩むことはなくなりました。

はてなブログ向けに書くときの注意点

運用してみると、はてなブログの Markdown に固有の注意点がいくつか見つかりました。同じことをやろうとしている方の参考になるかもしれないので、挙げておきます。

  • 改行したい行の末尾には半角スペース 2 つが必要
    • これを忘れると、意図したところで改行されません
  • 見出しは ## から使う
    • #h1 に変換されるため、記事タイトルと重複してしまいます
  • 画像は Markdown 記法で書く
    • HTML で書くと下書きに反映されません。横に並べたい場合など HTML を使いたいときは、先に画像をアップロードしておく必要があります
    • 画像は記事と同じ階層に置き、記事内では相対パスで指定します
  • コードブロックにファイル名を表示したい場合は一工夫必要

このあたりは、社内のドキュメントに執筆時の注意事項としてまとめ、プルリクエストのテンプレートからも参照できるようにしています。

Claude Code と組み合わせる

記事がリポジトリ上の Markdown ファイルとして管理されているということは、記事をそのままツールに読ませられるということでもあります。そこで、レビューの一部を Claude Code に任せる仕組みも用意しました。

まず CLAUDE.md に、ディレクトリ構成・記事のフォーマット・公開までのフローを記述しています。これにより、記事を書いてもらう際の前提を毎回説明せずに済みます。

そのうえで、いくつかのスキル(スラッシュコマンド)を用意しました。

/review-draft

下書き記事を、企業のエンジニアブログという観点でレビューさせるスキルです。
これまでレビュアーが毎回頭の中で確認していた項目です。機械的に確認できる部分を先に洗い出しておけば、人間のレビューは記事の内容そのものに集中できます。

/suggest-tags

はてなブログの topics ページに記事が掲載されるよう、記事の内容から適切なタグを提案させるスキルです。トピックと設定すべきタグの対応表を持たせておき、記事を読ませて該当するものを選ばせています。

前述の通り、タグの設定自体は編集チームが行うため、執筆者は出力された候補を編集チームに伝える形になります。コマンド 1 つで候補が出てくるので、依頼時のひと手間が減りました。

整形の自動化も検討中

前述した「改行したい行の末尾に半角スペース 2 つ」のようなルールは、内容ではなく形式の問題なので、人間が気をつけるよりも機械にやらせたほうが確実です。現在、この整形を行うスキルを追加しようとしているところです。

はてなブログ固有の整形処理はこの先も増えていきそうなので、1 つのスキルに集約していく想定でいます。

なお、この記事自体も /review-draft を通したうえで公開しています。

導入してみて

まず大きいのは、転記作業がなくなったことです。執筆者が書いたものがそのまま反映されるため、記法の違いによる表示崩れの確認や、画像の貼り直しといった作業から解放されました。

もう 1 つは、レビューの履歴が GitHub 上に残るようになったことです。どの指摘を受けてどう修正したのかがプルリクエストに残るため、後から経緯をたどれます。エンジニアにとっては使い慣れた場所なので、レビューを依頼する側・される側の双方にとって、心理的なハードルも下がったように感じています。

まとめ

HatenaBlog Workflows Boilerplate を導入したことで、エンジニアブログの執筆からレビューまでを GitHub 上で完結できるようになりました。

「ドキュメントツールで書いて、編集チームが管理画面に転記する」という運用に課題を感じている場合は、選択肢の 1 つとして検討してみてはいかがでしょうか。GHES で運用したい場合には前述の制約がある点と、予約投稿を使いたい場合は別途手順が必要になる点だけ、ご注意ください。

最後になりますが、シンクロ・フードでは一緒に働く仲間を募集しています。ご興味のある方は採用ページをご覧ください。