⚙️

ZennのPublicationのコンセプトに沿った、ストレスフリーな執筆・レビュー環境を作る

2023/12/01に公開

こんにちは!島田です。
Social Databank Tech Blog Advent Calendar 2023の1日目です。
今回はAdvent Calendar初回ということで、組織のTech Blogのストレスフリーな執筆・レビュー環境を構築した方法について話していきます。
この記事やアドベントカレンダーもその環境を使用して執筆されています。

※2023-12-22 追記
ZennのPublication Proの情報が公開されましたね。
レビュー機能が追加され、コメントやステータス管理ができるようになるみたいですね。
GitHub連携との相性がどうなるのか不明ですが、Gitに慣れていない人でも気軽にレビューしてもらえるのは良いことですね。
https://zenn.dev/zenn/articles/publication-pro-features

問題1. Zennのブラウザエディタはレビューしにくい

当初はZennのブラウザエディタで記事を執筆していました。
Zennのブラウザエディタ
シンプルで分かりやすいZennのブラウザエディタ
しかし、GitHubのようなレビュー機能が存在しないため、文章校正に難があります。

  • 誤字・脱字やテクニカルライティングの指摘が面倒
  • テキストコミュニケーションなら尚更

解決策1. GitHubでレビューすればいいじゃん!

使い慣れたGitHubであれば、下記のようにレビューがしやすくなります。

  • Suggestionで正確に指摘や修正が可能になる
  • そもそも自動校正ツールを使えば、人がレビューする量を減らせる
  • PullRequestにおけるAssignee、Reviewer、Labelなどの活用による管理コストの削減

また、ZennにはGitHub連携機能があり、ZennのアカウントとGitHubのリポジトリを連携させることで、GitHubでレビュー→Zennに公開を簡単に実現できます。
https://zenn.dev/zenn/articles/connect-to-github

問題2. ZennのGitHub連携機能とPublicationの相性が悪い

ZennのPublicationのコンセプト

弊社ではTech BlogをZennのPublicationを使って管理しています。
Publicationには以下のようなコンセプトがあります。

私たちは、記事は著者本人の持ち物であり、退職後も本人が管理できるべきだと考えています。 Publicationを脱退した著者は、Publicationに投稿した記事をそのまま残しておくことも、個人の記事に変更することもできます。どちらを選択しても、記事は著者の成果物としてプロフィールに残ります。

「それでは会社の資産とならない」と心配する経営者もいるかもしれませんが、この自由がメンバーが記事を書くことを促し、より会社のブランディングや採用につながるのではないかと考えています。
https://zenn.dev/publications

このコンセプトのおかげで、会社を退職しても、会社のTech Blogに執筆した記事を個人の資産にできます。
そのため、インターン生などの一定期間で離職する可能性が高い人にも、気軽に投稿してもらうことができます。

組織のGitHubリポジトリとZennのPublicationを連携させることができない

しかし、上記のコンセプトがあるため、PublicationはGitHubと連携させることができません。

  • ZennのGitHub連携機能はZennアカウントに対して連携ができるものである(A)
  • PublicationはZennアカウントとして投稿した記事を、組織の記事として公開できるものである(B)
  • GitHubのリポジトリとPublicationは連携できません(C,D)

ZennのGitHub連携とPublication

「GitHubの個人リポジトリ→Zennの個人アカウント→Publicationとして公開」とした場合、レビュアーは各個人のリポジトリに出入りしレビューをする必要があり、非常に面倒です。

組織用のZennアカウントを作成しGitHubリポジトリと連携させることもできますが、執筆者が全て組織用アカウントとして公開されてしまい、個人の資産として切り離すことが困難になります。

全ての記事の筆者が組織アカウントになってしまう

解決策2. 組織のリポジトリでレビュー→個人のリポジトリに反映・公開

組織のリポジトリでレビューし、変更内容を個人のリポジトリに反映させることで、ZennのPublicationのコンセプトに沿った形で組織のTech Blogを実現しました。

  1. 組織のリポジトリ上で執筆・PR作成・レビュー
  2. 個人のリポジトリに変更内容を反映
  3. 個人のリポジトリの変更をZennの記事として公開(ZennのGitHub連携機能を使用)
  4. 個人の記事を組織の記事としても公開(Publicationの設定を使用)

構成図

こうすることで以下のようなメリットが生まれました。

  • 退職時にGitHub Appsをアンインストールすることで、簡単に個人の資産とできる
  • 執筆・レビューを組織のリポジトリにまとめることで、レビュアーが組織のリポジトリだけ見れば良くなった

GitHub Appsの作成手順

組織のリポジトリから個人のプライベートリポジトリにアクセスするためのGitHub Appsを作ります。

  1. 組織のGitHubリポジトリでGitHub Appsを作成する(このときpublicにする)
  2. 個人のGitHubリポジトリにZennと連携するためのリポジトリを作成する
  3. 作成したリポジトリにGitHub Appsをインストールする

処理の流れ

  1. PullRequestがマージされるとGitHub Actionsが発火する
  2. PullRequestのAuthorを取得する
  3. Authorのリポジトリにpushする
    1. 記事の公開設定をtrueにしてpublishできる状態にする
    2. Authorのリポジトリにpushするためのトークンを発行する
    3. Authorのリポジトリに変更内容をpushする
name: Authorのリポジトリにpushする
on: 
  pull_request:
    types: 
      - closed
    paths-ignore: # 記事に関係ない変更時には発火させない
      - '.github/**'
      - 'README.md'
      - '.gitignore'

jobs:
  fetch-author:
    name: Authorを取得する
    runs-on: ubuntu-latest
    if: github.event.pull_request.merged == true
    permissions:
      pull-requests: write
      contents: read
    outputs:
      author: ${{ steps.fetch-author.outputs.author }}
    steps:
      - uses: actions/checkout@v4
      - name: Fetch Author
        id: fetch-author
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          PR_NUM: ${{ github.event.pull_request.number }}
        run: echo "author=`gh pr view ${PR_NUM} --json author | jq -r .author.login`" >> $GITHUB_OUTPUT

  push-articles:
      name: Authorのリポジトリにpushする
      if: github.event.pull_request.merged == true
      runs-on: ubuntu-latest
      needs: fetch-author
      env:
        AUTHOR: ${{ needs.fetch-author.outputs.author }}
      steps:
        - uses: actions/checkout@v4
        - name: 公開設定をtrueにする
          run: |
            sed -i 's/published: false/published: true/' $AUTHOR/articles/*.md
            cat $AUTHOR/articles/*.md | grep published:
        - name: Github App Tokenの生成
          uses: actions/create-github-app-token@v1
          id: app-token
          with:
            app-id: <GitHub AppsのAppId>
            private-key: <GitHub AppsのPrivateKey>
            owner: ${{ env.AUTHOR }}
            repositories: "tech-blog"
        - name: Authorのリポジトリに変更内容をpush
          env:
            GH_TOKEN: ${{ steps.app-token.outputs.token }}
          run: |
            gh auth status
            gh repo view https://github.com/$AUTHOR/tech-blog --json url,issues
            git config --global user.email <botのメールアドレス>
            git config --global user.name <botのユーザー名>
            git clone "https://<botのユーザー名>:${GH_TOKEN}@github.com/$AUTHOR/tech-blog.git"
            rm -rf tech-blog/articles
            rm -rf tech-blog/books
            rm -rf tech-blog/images
            mv -f $AUTHOR/* tech-blog/
            cd tech-blog
            git add .
            git commit -m "test"
            git push

注意点

GitHubホステッドランナー

GitHubホステッドランナーには様々なパッケージが含まれています。
GitHub CLIやgitはもちろん、jqなどもデフォルトで入っているので、追加のパッケージインストールは不要です。
https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2204-Readme.md

botのメールアドレスやユーザー名

botのメールアドレスやユーザー名はhttps://api.github.com/users/<アプリ名>[bot]から調べることができます。

  • ユーザー名:<login>
  • メールアドレス:<id>+<login>@users.noreply.github.com

https://www.memory-lovers.blog/entry/2022/11/18/113500
https://docs.github.com/en/rest/users/users?apiVersion=2022-11-28#get-a-user

おわりに

GitHub Actionsを使うことで、ZennのPublicationのコンセプトを損なうことなく、ストレスフリーな執筆・レビュー環境を作ることができました。
まだ始めたばかりなので、GitHub上での執筆・レビューがベストかは分かりませんが、続けてみます。
今後は制度面(Tech Blogを執筆することによって得られる個人のインセンティブ)などについて深めていき、よりメンバーが技術発信していきやすい環境を整えていこうと考えています。

テックブログあるある:テックブログの体制構築の経緯をテックブログにする。

ソーシャルデータバンク テックブログ

Discussion