規程文書を Google ドキュメント から GitHub に移行する

人事部の小池です。

この記事は KAYAC Advent Calendar 2022 の16日目の記事です。

カヤックの規程文書管理の仕組みを Google ドキュメント から GitHub に移行した取り組みについて紹介します。

これまでの文書管理

カヤックでは長年規程文書を Google ドキュメント で管理していました。Google ドキュメント は多くの従業員にとって親しみやすいものの、文書を管理する上でいくつかつらい点がありました。

改訂内容の差分が追いにくい・改訂の背景がわからない

Google ドキュメント なので変更履歴から過去の版を閲覧することは可能ですが手軽とはいえません。改訂の際は内容以外にも改訂に至った経緯、議論といった背景も重要ですが、これらの背景は成果物である Google ドキュメント の版の履歴からは伺うことはできません。「ある時までは確かこういった規程内容だったと思うがいつ変わったのか?どういう経緯で変わったのか?」というやり取りがしばしば発生していました。

レイアウトを揃えるのが難しい

これまでレイアウトに決まりがなく、編集者が独自にレイアウトを組み立てていました。そのため文書内もしくは文書間でレイアウトが不揃えになっている、改訂の際にレイアウトが崩れてしまうといったことがありました。文書をレビューするプロセスがないことも文書が崩れてしまう要因になっていました。

複数人による文書の改訂をマージするのが大変

ひとつの規程文書に対して複数人が変更を加えることもあります。改訂にあたり役員会に変更の提案が必要なケースがあり、Google ドキュメント に反映するまでに時間がかかることがあります。その間に別の改訂が入ってしまうと文書の整合性を保つのも一苦労です。

これらのつらい点を解消するために規程文書を GitHub 管理に移行することにしました。

GitHub による文書管理

GitHub に移行するにあたり以下の効果を期待していました。

Pull Request によるワークフロー構築

改訂内容を Pull Request として提出することで文書の変更を差分で確認できるようになり、description に関連資料を記載することで改訂の背景も追うことが可能です。更に branch protection rule を設定し文書管理チームのレビューを強制することで誤った修正が行われにくくなります。

Markdown で書き直すことによるレイアウトの統一と静的サイトの生成

Markdown であればレイアウトを統一することも容易で、かつ GitHub 上で編集内容のプレビューを表示することが可能です。文書が Markdown 化されていれば静的サイトジェネレータで静的サイトを生成し、そのまま公開することも可能ですね。

文書管理を GitHub へ移行することを検討し始めた時点で約8割の従業員が GitHub アカウントを持っており、従業員は GitHub を閲覧できるものとして移行を進めることにしました。規程文書 repository を internal repository として Organization 内で公開し、 KAYAC Organization に所属していれば誰でも閲覧、編集できる形を取りました。

一番大変と思われる文書の Markdown 化は文書管理チームの担当者が勢いで全部やってくれました。

改訂のワークフロー

  • 編集者は develop ブランチから改訂のトピックブランチを生やして文書を編集し、Pull Request を作成する
    • Pull Request では提案資料の Google スライド や議論に用いた Asana タスクなどのリンクを description に貼る
  • 文書管理チームや関係者がレビューする
  • Approve 後に編集者が develop ブランチにマージする
  • 文書管理チームが develop ブランチから main ブランチに向けて Pull Request を作成する
  • main ブランチに向けた Pull Request は文書管理責任者がレビューする
  • Approve 後に文書管理チームが main ブランチにマージする

以上のワークフローで運用しています。開発現場のブランチルールと似たような形ですね。普段 GitHub を使わない従業員もいるため事故が起きないよう branch protection rule を以下のように設定しています。

develop ブランチの branch protection rule
develop ブランチの branch protection rule
main ブランチの branch protection rule
main ブランチの branch protection rule

Code Owner は文書管理責任者です。

私はこれまで積極的に規程文書を読むことはありませんでしたが、不思議なもので Pull Request だと心理的な抵抗がなく気軽に読めるようになりました。新しい規程でもなければ差分は数行から数十行なので CI 実行待ちなどの空き時間で読むことができます。

編集者からもセルフレビューがしやすい、うっかり変なところをいじってしまうことがなくなり編集コストが下がったなどの声が上がっています。

運用の様子
運用の様子

規程の公開

社労士さんやカヤックのグループ会社の関係者など、カヤックの従業員以外の方も規程を閲覧したいというユースケースがあります。そのため Markdown の規程文書を元に静的サイトを生成しサイトを公開しています。 静的サイトジェネレータは Hugo を採用しました。

規程サイト
規程サイト

先述のワークフローで develop、main の2つのブランチが登場していました。develop ブランチがテスト環境、main ブランチが本番環境となっていて、それぞれ GitHub Actions でデプロイされています。テスト環境は規程の公開前に表示を確認することができる環境、本番環境は正式な文書として公開されている環境です。

トピックブランチを develop ブランチにマージすると GitHub Actions で Hugo が静的サイトを生成し、GitHub Pages で Organization 内でサイトが公開されるようになっています。編集者は正式公開前に GitHub Pages にてサイト上の表示を確認することができるので安心して作業することができます。

main ブランチの本番環境は KAYAC Organization 以外の方も閲覧できるよう認証を導入する必要があるので AWS を用いて認証および配信の環境を作ります。CloudFront + S3 の構成に Cognito + Google IdP による認証を加え以下のような環境を構築をしました。

インフラ構成
インフラ構成

CloudFront から直接 Cognito を呼ぶことはできないのでビューワーリクエストイベントで Lambda@Edge を起動し Cognito を呼んでいます。こちらは awslabs/cognito-at-edge というライブラリを利用しています。

github.com

README の Usage の通りに使用すると日本語を含む URL の場合に Location ヘッダの URL が URL エンコードされておらず、元の URL にリダイレクトで戻れないので自前で URL エンコードしておく必要があります。

const authenticator = new Authenticator({
  region: 'ap-northeast-1',
  userPoolId: '<userPoolId>',
  userPoolAppId: '<userPoolAppId>',
  userPoolAppSecret: '<userPoolAppSecret>',
  userPoolDomain: '<mydomain>.auth.ap-northeast-1.amazoncognito.com',
});

exports.handler = (request) => {
  return authenticator.handle(request)
    .then(res => {
      if (res.status === '302') {
        res.headers.location[0].value = encodeURI(decodeURI(res.headers.location[0].value));
      }
      return res;
    });
}

Cognito では Pre signup Lambda trigger で事前に許可したドメイン、ユーザに対してのみ signup するようにしておきます。こちらは弊社の 長田 作の handlename/cognito-gate を用いると YAML で allow list を管理することができます。

github.com

kayac.com ドメインのメールアドレスと foo@example.com に対して signup を許可する場合は以下のようになります。

---
pools:
  - id: <userPoolId>
    allows:
      - "kayac.com"
      - "foo@example.com"

YAML ファイルならエンジニアが作業せずとも allow list のメンテナンスができるので手離れがよく便利ですね。

また、CloudFront + S3 構成における Hugo の問題として、サブディレクトリにアクセスすると 403 が返ってしまうという問題があるので CloudFront のオリジンリクエストイベントで index.html を URL の末尾に追記しています。AWS のドキュメントにサンプルコードがあります。

index.htmlファイル名を含まないリクエスト URL に追加する

ルートアクセスは CloudFront のデフォルトルートオブジェクトの設定により index.html が返されるので気付きにくい点に注意が必要です。

サイトを公開したことで従業員以外の方も閲覧できるようになったほか、アンカーリンクで規程文書の内容をピンポイントで示すことができるようになりテキストベースのやり取りがスムーズになるという効果がありました。

まとめ

規程文書管理の仕組みを Google ドキュメント から GitHub に移行した取り組みについて紹介しました。規程文書以外にも様々な社内文書があるのでこれらの文書の管理の仕組みも徐々に移行していきたいですね。

明日17日目は sbee さんによる スイスドローのリプレースでフロント頑張ったという話をしたい です!お楽しみに。

カヤックではエンジニアリングで組織の課題解決や成長支援を行うコーポレートエンジニアも募集しています!

www.kayac.com