Konboi Note

Microsoft Teams の Adaptive Card を投稿前に検証する CLI `msac` を作った

· Konboi

はじめに

Microsoft Teams の Workflows 経由で Adaptive Card を投稿する機能を作っていた。実装中、Teams 側に Could not display とだけ表示されることがあった。

JSON を見直せば原因はわかるものの、カードが大きくなると問題のある場所を探すのがつらい。また、修正を環境にデプロイして確認するには、時間がかかるのもネックだった。

というわけで、Adaptive Card をローカルで検証する Go 製 CLI msac を作った。

github.com
github.com

msac check で投稿前に検証する

インストールは go install で。

go install github.com/Konboi/go-ms-adaptive-card-validator/cmd/msac@latest

カード単体を検証する場合はこんな感じ。

msac check -mode card card.json

たとえば TextBlock.wrap に boolean ではなく文字列を渡すと、JSON Pointer と問題のあるオブジェクトを表示する。

ERROR /body/0/wrap: expected boolean, but got string (in TextBlock)
{
  "type": "TextBlock",
  "text": "wrap は boolean にする",
  "wrap": "true"  <<< ERROR: expected boolean, but got string (in TextBlock)
}

エラーのパスだけでなく、周辺の JSON と問題のあるメンバーに印を付けた。大きなカードでも、どこを直せばよいか見つけやすい。

Teams Workflows の Webhook ペイロード全体も検証できる。

msac check -mode webhook payload.json

-mode auto がデフォルトで、ルートの type が message なら Webhook、それ以外はカード単体として扱う。標準入力にも対応している。

cat card.json | msac check -strict -

公式スキーマを切り替える

Microsoft の公式 Adaptive Card JSON Schema 1.1〜1.6 をバイナリに同梱した。検証時のネットワークアクセスは不要で、デフォルトは 1.6 にした。

古いバージョンを対象にする場合は -schema-version で切り替えられる。

msac check -schema-version 1.5 card.json

1.6 の metadata を含むカードを 1.5 として検証すると、以下のようになる。

ERROR /metadata: "metadata" is not an allowed property on AdaptiveCard
{
  "webUrl": "https://example.com/deployments/123"
}

ERROR /version: card version 1.6 exceeds selected schema 1.5

実装ではスキーマを go:embed で埋め込み、santhosh-tekuri/jsonschemaで検証している。公式スキーマによる型や必須プロパティの検証に加えて、Input の重複 ID や Webhook の添付形式なども確認する。

text/template にダミーデータを渡す

今回の用途では、Go の text/template から生成した JSON を確認したかった。そのため msac render も追加した。

テンプレート内では json 関数を使って値を埋め込む。

{
  "type": "AdaptiveCard",
  "version": "1.6",
  "body": [
    {
      "type": "TextBlock",
      "text": {{json .message}},
      "wrap": true
    }
  ]
}

ダミーデータを渡して、そのまま check にパイプできる。

set -o pipefail
msac render \
  -template card.json.tmpl \
  -data dummy.json \
  | msac check -strict -

実際の生成結果も確認できる。

$ msac render \
    -template examples/card.json.tmpl \
    -data examples/dummy.json \
    | jq '.body[0]'
{
  "type": "TextBlock",
  "text": "テスト環境のデプロイ完了\n担当: \"山田\"",
  "wrap": true
}

msac preview で HTML を生成する

スキーマ検証だけでは、レイアウトが意図どおりかまではわからない。そこで、ブラウザで確認するための preview コマンドも追加した。

$ msac preview card.json -o preview.html
$ test -s preview.html && echo 'preview.html was generated'
preview.html was generated

生成した HTML では light/dark と desktop/mobile 幅を切り替えられる。カード単体だけでなく、Webhook の attachments[].content も順番に表示する。

render から直接つなぐ場合は以下。

msac render -template card.json.tmpl -data dummy.json \
  | msac preview -o preview.html -

HTML はAdaptive Cards の公式 JavaScript SDKを利用して描画する。カードの JSON は Base64 で HTML 内に埋め込み、Action とリンクは実行しないようにしている。

ただし、これはあくまで近似表示になる。Adaptive Card は HostConfig やクライアントによって描画が変わるため、Teams 上の表示と完全には一致しない。最終確認は実際の Teams で行う必要がある。

また、生成した HTML は JavaScript SDK と Markdown processor を CDN から読み込むため、開くときにネットワーク接続が必要になる。

さいごに

個人的には、エラー箇所を JSON Pointer と周辺のオブジェクトで表示する機能が一番便利だった。Teams に実際に投稿して確認する回数を減らせるので、同じように Workflows 経由でカードを投稿している人に使ってもらえたらうれしい。

今後は実際に運用しつつ、Teams 固有の制約で拾えるものがあれば追加していきたい。

参考資料