logo hsb.horse
← ブログ一覧に戻る

ブログ

Go で microCMS CLI を作った

管理画面を開かずにターミナルから microCMS のコンテンツを操作できる CLI ツールを Go で作った。複数サービス管理・スキャンキャッシュ・バックアップなど主要機能と、設計で判断したことをまとめる。

公開日:

管理画面を開かなくてもいい場面が増えてきた。

デプロイスクリプトの中でコンテンツの存在確認をしたい、複数サービスのスキーマを横断的に把握したい、バックアップを cron で定期取得したい——どれも管理画面では完結しない。AI エージェントが microCMS を操作できる手段も欲しかった。人間がターミナルで叩く用途と、エージェントがツールとして呼び出す用途の両方を想定している。

そこで Go で microcms CLI を作った。

https://github.com/hsblabs/microcms-cli

何ができるか

サービスの登録・切り替え、コンテンツの取得、マネジメント API の呼び出し、全コンテンツのバックアップ、シェル補完スクリプトの生成まで、ターミナルから一通り操作できる。

microcms service add # サービス登録(対話式)
microcms service scan # API スキーマをスキャン・キャッシュ
microcms content list <ep> # コンテンツ一覧取得
microcms content get <ep> [id] # 単一コンテンツ取得
microcms management api list # API 一覧(マネジメント API)
microcms backup --out ./backup # 全コンテンツのバックアップ
microcms completion zsh # シェル補完スクリプト生成

最初にやることは2つ。service add でサービスを登録し、service scan でスキーマをキャッシュする。これだけで補完が効いた状態でコンテンツ操作が始められる。

Terminal window
$ microcms service add
? Service ID: my-blog
? Content API Key: ********
? Management API Key (optional): ********
Service "my-blog" added.
$ microcms service scan
Scanning service "my-blog"...
blogs (list, 5 fields)
categories (list, 2 fields)
banner (object, 3 fields)
Found 3 APIs (2 list, 1 object)
$ microcms content list blogs --limit 3

技術スタック

CLI フレームワークは cobra、対話式入力には charmbracelet/huh を使った。API キーの暗号化は AES-256-GCM で、暗号鍵は go-keyring を通じて OS のキーチェーンに格納する。出力は text/tabwriterencoding/jsongopkg.in/yaml.v3 をフォーマットに応じて切り替える構成だ。

設計で決めたこと

複数サービスの管理

開発用・本番用など複数サービスを使い分けるのが前提で、git のブランチ切り替えに近い UX を意識した。

Terminal window
$ microcms service use production
Active service: "production"

サービス定義は ~/.config/microcms/service/<id>.json に保存し、API キーは AES-256-GCM で暗号化する。暗号鍵は macOS Keychain / Linux Secret Service / Windows Credential Manager に格納されるので、ファイルを直接読んでもキーは取り出せない。

スキャンキャッシュによる動的補完

service scan がマネジメント API からスキーマを取得し ~/.cache/microcms/scan/my-blog.json にキャッシュする。このキャッシュがシェル補完とバリデーション両方を担う構造だ。

microcms content list の後で Tab を押すとエンドポイント名が候補に出る。存在しないエンドポイントを指定した場合は typo サジェスト付きでエラーになる。

Terminal window
$ microcms content list bloggs
Error: Endpoint "bloggs" not found in service.
Did you mean "blogs"?
Run 'microcms management api list' to see all available endpoints.

TTL はデフォルト 24h で自動リフレッシュされるため、普段は意識しなくていい。

設定の3層レイヤー

設定値の解決順序は「CLI フラグ > 環境変数 > config.json > ビルトインデフォルト」にした。

Terminal window
# config.json に保存
$ microcms config set output.format json
# 環境変数で上書き
$ MICROCMS_OUTPUT_FORMAT=yaml microcms content list blogs
# フラグが最優先
$ microcms content list blogs --format table

設定ファイルは XDG Base Directory 準拠($XDG_CONFIG_HOME/microcms/config.json)。

デフォルト出力を JSON にした理由

content コマンドのデフォルト出力は JSON だ。microCMS のレスポンスは繰り返しフィールドやコンテンツ参照でネストが深く、テーブル表示では情報が落ちる。jq とパイプで加工するケースが主なので、テーブルよりも JSON の方が都合がいい。

Terminal window
# jq と組み合わせる
$ microcms content get blogs abc123 | jq '.title'
# 人の目で確認したいときは table
$ microcms content get blogs abc123 --format table
KEY VALUE
createdAt 2024-01-15T10:00:00.000Z
title Hello World
tags (array, 3 items)

エラーメッセージの構造

すべてのエラーを「何が起きたか → なぜ → どうすればいいか」の3層構造にした。

Terminal window
$ microcms service scan
Error: Permission denied: Forbidden
Check that your API key has the required permissions enabled.
For management API operations, enable permissions in the 'マネジメントAPI' tab
of your API key settings.

終了コードもエラー種別ごとに分けている。一般エラー(1)、使い方エラー(2)、設定エラー(3)、認証エラー(4)、権限エラー(5)、レート制限(6)、リモート API エラー(7)、ネットワークエラー(8)だ。スクリプトでの分岐判定に使える。

バックアップ

全 API のコンテンツを並列で取得してローカルに保存する。

Terminal window
$ microcms backup --out ./backup --parallel 8
backup/
├── manifest.json
├── apis.json
├── schemas/
├── blogs.schema.json
└── categories.schema.json
└── contents/
├── blogs/
├── abc123.json
└── def456.json
└── categories/
└── news.json

--dry-run で実行計画だけ確認できる。

実装で工夫した点

API キーのフォールバック

microCMS では1つの API キーにコンテンツ API とマネジメント API 両方の権限を付与できる。マネジメント API キーが未設定の場合、コンテンツ API キーをフォールバックとして使うようにした。

mgmtKey := svc.ManagementAPIKey
if mgmtKey == "" {
mgmtKey = svc.ContentAPIKey
}

リトライとバックオフ

HTTP クライアントにエクスポネンシャルバックオフ + ジッターを実装した。429(レート制限)や 5xx エラーで自動リトライする。

interval := baseInterval * 2^attempt
if jitter {
interval *= (0.5 + rand * 0.5)
}

Atomic な設定ファイル書き込み

設定ファイルの更新は「一時ファイルへの書き込み → os.Rename」のパターンで原子的に行う。書き込み途中のクラッシュでファイルが壊れるのを防ぐためだ。

インストールとセットアップ

Terminal window
# Homebrew
brew install hsblabs/tap/microcms
# Go
go install github.com/hsblabs/microcms-cli@latest
# サービス登録
microcms service add
# スキーマスキャン(補完を有効化)
microcms service scan
# シェル補完(zsh の例)
microcms completion zsh > "${fpath[1]}/_microcms"

microCMS を日常的に使っていて、管理画面を開く手間が気になっている場面があれば試してみてほしい。フィードバックや PR は歓迎だ。