kintoneにレコードを登録するだけでCybozu Techを更新するシステムを作った
こんにちは。@sakay_yです。
今日はお題の通り、システムを作ったのでちょっと記事にしたいと思います。もし似たようなことをする場合に、参考になると嬉しいです。でも正直似たようなケースは少ないと思ってます…。
まとめ3行
kintone+CircleCI Enterprise+Github REST APIで、yamlファイルを自動的にcommit&pushしてWebサイトを更新してくれるシステムを作ったよ
kintoneにはIPアドレス制限やカスタマイズ不可とか制約が多かったので、ちょっと複雑になってしまったよ
Cybozu Techはサイボウズのエンジニアの技術情報発信をまとめているので、どうぞよろしくお願いします
Cybozu Techとは?
Cybozu Techとは、サイボウズのエンジニアの技術情報発信をまとめたエンジニアサイトです。過去にサイボウズのメンバーが発表したスライドや動画をまとめたり、各ブログの新着記事などを掲載しています。私はこのサイトの運用管理者の一人です。どうぞ、Cybozu Techをよろしくお願いします。
システムを作った背景
掲載作業の変化
もともと、掲載したいスライドの情報を社内で集めたり、サイトを更新したりというところを1人でやっていました。スライドの掲載には、スライドの情報をまとめたyamlファイルをリポジトリに追加すればOKです。なので、CLIでコマンドを叩けばyamlファイルを生成する仕組みまで作って、満足していました。
kintoneと連携する仕組みを考えたこともあったのですが、後述の通り制約も多く、面倒だったのでやめてしまいました。
そんな感じで細々と更新していましたが、あるときよりチームメンバーが手伝ってくれるようになりました。スライド掲載するための情報を社内より集めてきてくれて、kintoneにレコード登録して、掲載の依頼をしてくれます。
こうなってくると、これは二度手間だな、と感じるようになってきました。
情報の蓄積
もう一つ。スライドを掲載するにあたり、著者やタグをつけるようにしています。継続して掲載してきた結果、著者の管理やタグの管理が厳しくなってきました。著者はただのJSONファイルで、タグに至ってはフリーフォーマットです。JSONにある100名近い著者の中から探して選ぶのは面倒です(今回整理したら重複している人もいました…)。タグも乱立してしまって、利用者としても扱いづらいのではないでしょうか。
この状況を解消すべく、著者やタグもkintone上で管理したほうが良いのだろうなと感じていました。
システムの制約と要件
要件
必要な情報をkintoneにレコードを追加することで、Cybozu Techにスライドが掲載される
即時性は必要ない(もともとベストエフォート対応)
著者やタグの検索性の向上、および無秩序な状態を避ける
あとは、できれば勉強のためにAWSやCIを利用したいなと思っていました。
制約
kintoneにはIPアドレス制限があり、社外のネットワークから接続することはできない。ただし、一部例外があり、CircleCI EnterpriseやGithub Actionsのセルフホストランナーからは接続可能
kintoneのJavaScriptカスタマイズで外部通信することはセキュリティルールにより不可
Cybozu Techのリポジトリは、全社管理のOrganizationのプライベートリポジトリなので、気軽にGithub Actionsをセルフホストランナーで利用できない(管理者権限が必要)
システムの技術要素
利用したWebサービス
kintoneとCircleCI EnterpriseとGithub REST API(とNetlify)でサイトを自動更新します。
構成図とシステムの動作概要
構成の概略は以下のとおりです。
ジョブのimageをAmazon ECRから取得しているのは、Docker Hubを利用すると、社内ネットワークを圧迫して他チームに影響を与えてしまうためです。(あとは勉強のため)
kintoneとgithub.com間で直接やり取りしてGithub Actionsを利用できればシンプルになりそうですが、これは上述の制約により諦めました。
システムの詳細
kintone
kintoneにはスライドに必要な情報を登録できるようにします。
公開URL
著者(名前、Twitter ID)
タグ
公開日
著者やタグは別のアプリで管理して、ルックアップにします。また、それぞれ複数指定可能なので、テーブルにしておきます。
あとは小ネタですが、REST APIで取り扱うので、フィールドコードもいい感じに設定しておいたほうが良いですね。
公開状態を管理するために、プロセス管理も設定しておきます。下書き中、公開待ち、公開済み、みたいな感じです。
CIでREST APIを実行したいので、APIトークンの設定も必要です。レコード取得と、ステータスを更新するためにレコード編集の権限を付与してください。
CircleCI Enterprise
config.yamlはこんな感じです。main.tsを呼んでいる以外のことはほぼやってません。
version: 2
workflows:
version: 2
ci:
triggers:
- schedule:
cron: "0 * * * *"
filters:
branches:
only:
- main
jobs:
- slide-upload-job
jobs:
slide-upload-job:
docker:
- image: xxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/xxxxxxx:mynode-17.3.0
steps:
- checkout
- restore_cache:
keys:
- v1-npm-cache-{{ checksum "jobs/slide-upload-job/package-lock.json" }}
- v1-npm-cache-
- run:
working_directory: jobs/slide-upload-job
command: npm ci
- run:
working_directory: jobs/slide-upload-job
command: |
mkdir -p /tmp/output
npx ts-node main.ts
rm -rf /tmp/output
プロジェクトの設定でAWS Permissionの設定をし、環境変数にGithub Personal TokenやkintoneのAPIトークンも置いておきます。
main.tsでやっていることとしては、以下のとおりです。
kintoneのレコード一括取得APIを叩いて、公開待ちのレコードを取得
スライド掲載に必要な情報を収集
整形
js-yamlでyamlファイルにして書き出し
kintoneのステータス更新APIでレコードを編集
ちなみに、TypeScriptでkintoneやGithubのREST APIを使う場合、以下のクライアントを使うと楽です。
ファイルのやりとりですが、base64にしてPUTする必要があります。
色々方法はあると思うんですが、自分は一旦成果物としてyamlファイルを確認したかったため、書き出してCircleCIに成果物として保存しつつ、base64で読み込むという方法を取りました。
import { Octokit } from "@octokit/rest";
import * as fs from "fs";
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
octokit.repos.createOrUpdateFileContents({
owner: ORGANIZATIONS,
repo: REPOS,
path: PATH_TO_UPLOAD_FILE,
message: `upload slide from kintone: ${FILE_NAME}`,
content: fs.readFileSync(PATH_TO_YAML_FILE, { encoding: "base64" })
});
ファイルに書き出す必要はなくなった(yamlファイルが想定通りの構造をしていたのを確認できた)ので、リファクタリングする余地がありそうです。
最後に
今回の記事が、誰かのkintoneを使った自動化の参考になれば嬉しいです。
あとは、繰り返しになりますが、Cybozu Techには、今回の仕組みを作ったように、サイボウズのエンジニアが公開したスライドや動画を多数掲載しています。見ていただけると嬉しいです。