📥

ActivityPub実装をローカルやCIでテストする

2023/11/03に公開1

自分用のActivityPub実装を趣味で作っています。

https://github.com/mkizka/unsocial

このリポジトリではNext.jsを使った自作の実装に加えて、Docker ComposeでMisskey、Mastodonを起動し、PlaywrightでActivityPub実装のテストをしています。

構成としては以下のようになっています。

Docker内のNginxを経由して自作実装、Mastodon、Misskeyが相互接続している様子を表した図

ざっくりまとめると、Nginxを経由して$ next devで起動した自作実装、DockerコンテナのMastodon、Misskeyとが相互通信できるようになっています。

これらを整備するにあたって調べたことなどをまとめて紹介します。

なお、開発環境はWSL2、Dockerはdocker-ce( https://get.docker.com )を使用しています。

ActivityPub実装をローカルでテストする方法

ActivityPubを実装するにあたっては自作の実装と、MastodonやMisskeyといった他の実装とを通信させることで動作確認を行うと思います。

ActivityPubを利用したやりとり(以下、連合)には基本的に独自ドメインとhttpsでの接続が必要です。通常はテストしたい実装と連合相手とをそれぞれどこかのサーバーにデプロイして動作確認すると思いますが、とても手間がかかります。

自分の場合はローカルやCIでテストをしたかったのでDocker Composeを使いました。さらに独自ドメインとhttps接続の問題は以下のようにして解決しました。

ドメインとして.localhostを使う

.localhostについては以下の記事などを参照してください。

https://zenn.dev/kanahebi/articles/ab31fa0fe1c5d2

localhostにアクセスする際、実はfoo.localhostなどとしても同様にアクセスすることが出来ます。

これを利用してmisskey.localhostやmastodon.localhostへのリクエストを単一のNginxに受けさせ、リクエスト先のドメインを見て各実装に振り分けることで「独自ドメインでアクセスする」という条件を満たしています。

https接続にNginxとmkcertを使う

Nginxを経由して各実装にアクセスできれば、あとはNginxへ証明書を配置するだけです。

証明書の作成にはmkcertを使いました。使用方法はいろいろな解説ページがあると思うので省略します。

https://github.com/FiloSottile/mkcert

各設定ごとのつまづきポイント

各実装ごとの設定を準備する中でつまづいたポイントをまとめます。

Mastodonの設定

Mastodonの設定は環境変数から指定します。以下の内容が必要でした。

  • SSL_CERT_FILE=/path/to/rootCA.pem
    • Mastodon(Ruby)がmkcertの証明書を使って他実装にhttpsでリクエストを送るのに必要
  • ALLOWED_PRIVATE_ADDRESSES=172.0.0.0/8
    • 他のDockerコンテナからのリクエストを受け付けるのに必要

Misskeyの設定

Misskeyの設定はymlファイルから指定します。特に変わった指定は必要ありませんでしたが、変わりに以下が必要でした。

  • NODE_EXTRA_CA_CERTS=/path/to/rootCA.pem
    • Misskey(Node.js)がmkcertの証明書を使って他実装にhttpsでリクエストを送るのに必要
  • NODE_ENV=development
    • E2Eの実行中にレートリミットでエラーになることがあるのでそれを無効化するのに必要

Nginxの設定

自作実装用の設定です。詳細は各コメントの通りです。

https://github.com/mkizka/unsocial/blob/1e85c64c347a086df8ccc827054898b8ed61965f/docker/nginx/confs/unsocial.conf

自作実装のみ、プロキシ先をDockerコンテナではなくhttp://host.docker.internal:3000としています。

これはNode.jsでの開発はDockerを使わないほうが何かと良い印象があり、自作実装で使用しているNext.jsのnext devコマンドで起動するローカルサーバーにそのまま繋がるようにするためです。

Docker Composeに以下のように記述することで、host.docker.internalが使える(Dockerからホスト側のサーバーに接続できる)ようになります。

extra_hosts:
  - host.docker.internal:host-gateway

次にMisskey用の設定です。Playwrightでアクセスするとなぜかローディングが終わらないことが何度かあり、原因?と思われるsw.jsを叩けないようにしています。
https://github.com/mkizka/unsocial/blob/1e85c64c347a086df8ccc827054898b8ed61965f/docker/nginx/confs/misskey.conf

最後にMastodon用の設定。公式リポジトリのnginx.confを参考にしました。
https://github.com/mkizka/unsocial/blob/1e85c64c347a086df8ccc827054898b8ed61965f/docker/nginx/confs/mastodon.conf

PlaywrightでE2Eテスト

起動した自作実装、Mastodon、Misskeyに対して、相互に連合出来るかを確認するE2Eテストを作っています。

例として、自作実装とMastodonとの連合のテストはこのように記述しています。

https://github.com/mkizka/unsocial/blob/1e85c64c347a086df8ccc827054898b8ed61965f/e2e/federation.test.ts#L123-L135

runTest関数はフォロー → 投稿 → いいね → いいね削除 → 投稿削除 → フォロー解除のような連合の全機能を網羅した一連のシナリオを実行するようにしています。

そして引数にはMyhostUnsocialHandler, RemoteUnsocialHandler, MastodonHandler, MisskeyHandlerの4つのクラスを実装して、自作実装同士、自作実装からMastodonとその逆、自作実装からMisskeyとその逆、の系5パターンのテストケースを用意しています。

https://github.com/mkizka/unsocial/blob/1e85c64c347a086df8ccc827054898b8ed61965f/e2e/fediverse/unsocial.ts#L5-L7

もし今後サポートしたいActivityPub実装が増えたとしても、それぞれの基底クラスであるFediverseHandlerを継承するだけでE2Eテストが増やせます。

これらをGitHub Actionsで各実装ごとに並列実行していて、最短5分ほどで動作確認ができます。リファクタリングなどに不具合があるとすぐテストが落ちるので、とても便利です。

おわり

ActivityPub実装をローカルやCIでテストするにあたって、自分がやった設定やつまづいたポイントを紹介しました。

同じようなことをやってみる方は参考にしてみてください。

GitHubで編集を提案

Discussion

takecchitakecchi

気軽にテストできず困っていたので大変助かりました...!