Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ドキュメンテーションがうまく回っていない。 #222

Open
Tracked by #6
yanorei32 opened this issue Mar 3, 2023 · 7 comments
Open
Tracked by #6

ドキュメンテーションがうまく回っていない。 #222

yanorei32 opened this issue Mar 3, 2023 · 7 comments

Comments

@yanorei32
Copy link

目的

この Issue は、#204 #212 の本質的な原因を究明・解消するものである。
Misskeyの開発速度や、ドキュメントの完全性を考えると、将来的には完全な自動生成を行うべきであると考える。
しかし、今すぐに全てを行うのは恐らく困難で、現在のドキュメント生成を紐解き、整理する必要があると考える。

現象

1. 一部オブジェクトのドキュメント欠落

#204 にある通り、UserNote を除いた、他全てのエンティティ (型) に関するドキュメントが 2023/03/03 現在存在しない。 ページ上の挙動としては、リンクは存在するが、refが壊れており 404 Not Foud と表示されてしまう。

この現象は、例えば drive/files/create から見える DriveFile などで観測できる。

2. ドキュメント追従不全

#212 によると、存在する UserNote すらも、現在の実装とは食い違っているようだ。

原因の追跡

現在、ページはGitHub Actions/GitHub Pagesを用いて公開されており、.github/workflows/gh-pages.yml から生成を追うことができる。

run: npm run build
を見ると、npm run buildを実行している。

"build": "vuepress build src"
を見ると、 vuepress build src を実行しているようだ。

よって本題は、src/.vuepress/config.ts に移る。

async onInitialized(app) {
await getInstances(app);
await generateEndpointPages(app);
await generateRecentUpdatesPage(app);
await getRelatedPages(app);
await getChildPages(app);
},

該当ドキュメントを生成している関数は generateEndpointPagesだと思われる。

当該関数を実装するファイルは3つある。

  1. src/.vuepress/_gen-api-defs-from-openapi.ts
  2. src/.vuepress/generate-endpoint-pages-from-openapi.ts
  3. src/.vuepress/generate-endpoint-pages.ts

import { generateEndpointPages } from './generate-endpoint-pages';

を見ると、実際には src/.vuepress/generate-endpoint-pages.ts が使われていることがわかる。

const endpointsDir = locale + 'docs/api/endpoints/';
const endpointPaths = glob.sync(__dirname + '/..' + endpointsDir + '**/*.json5');
const commonDef = JSON5.parse(fs.readFileSync(`${__dirname}/..${locale}docs/api/common.json5`, 'utf-8'));

を見ると、src/docs/api/common.json5src/docs/api/endpoints/ 配下にあるAPI定義ファイルから生成しているようである。

これ自体は一見問題ないようだが、 src/docs/api/common.json5 はメンテナンスされておらず、ここにあるべき型が欠落しており、また更新されていない。

考察

これらの現象から、現在の半自動生成開発サイクルはうまく回っていないことが原因であると考えられる。

(恐らく) 自動生成されたJSONファイルを #214 のように手動で修正すると以下のような問題が新たに発生する。

  • 再生成したとき、毎回パッチを充て直す必要がある
  • API仕様変更時、修正パッチを更新する必要がある

その為、手動でのパッチ適用は、その場しのぎにはなるが、将来を考えると現実的ではない。

方針

ドキュメントの確実な生成・追従に向け、CIで生成することが望ましいと考える。

方針1. 現在のJSONをCIでの自動生成に切り替える

現在のJSONがどのように作られたかはわからないが、機械的な生成にもみえる。
その場合、CIでMisskey本体のレポジトリを参照し、自動生成する方針を取ることで常に最新を追従できるようになると考えている。

方針2. OpenAPI定義ファイルからのCIでの自動生成に切り替える

最も標準的に用いられている方針である、OpenAPI定義ファイルを使用したドキュメント生成を(過去に行った|試みた)痕跡が現在もいくつか残っている。

例えば、

  1. src/.vuepress/api.json
  2. src/.vuepress/_gen-api-defs-from-openapi.ts
  3. src/.vuepress/generate-endpoint-pages-from-openapi.ts

しかしどういうわけか、肝心の api.json の取得元である(と思われる) /api.json のエンドポイントはこの変更 でMisskey本体から削除されてしまっている。

そのため、現在継続的に更新することが出来なくなってしまっている(と思われる)。

Misskey APIを用いたアプリケーションを作る際にも、Swaggerのエコシステムは非常に有用であるため、可能ならばこのエンドポイントの再実装が望ましいと考えている。

最後に

私はWebやTypeScriptに明るくないため、的外れなことを書いていたら申し訳なく思います。

@yanorei32
Copy link
Author

yanorei32 commented Mar 3, 2023

欠如しているであろう型

以下が src/.vuepress/api.json .components.schemas.* より生成した型一覧である。

jq -r '.components.schemas | keys[]' ./src/.vuepress/api.json | sort
Antenna
App
Blocking
Channel
Clip
DriveFile
DriveFolder
Emoji
Error
FederationInstance
Following
GalleryPost
Hashtag
MeDetailed
MeDetailedOnly
MessagingMessage
Muting
Note
NoteFavorite
NoteReaction
Notification
Page
QueueCount
User
UserDetailed
UserDetailedNotMe
UserDetailedNotMeOnly
UserGroup
UserList
UserLite

しかし src/docs/api/common.json5 にあるのは NoteUser のみである。
また、api.jsonに依ると、例えばUserはUserLiteとUserDetailedのUnionになっているようだが、現在のドキュメントには全くその様子がない。

現在の実装

https://github.com/misskey-dev/misskey/tree/7e8700514f18409874737cd5b439280bb03b829c/packages/backend/src/models/schema に(恐らく)現在のスキーマが存在する。が、最終更新が14日前と活発に更新されており、これを手動にて追従するのはやはり困難を極めると思われる。

@myConsciousness
Copy link
Contributor

@yanorei32

PRでも書きましたが、更新された最新のOpenAPI定義や実ソースをもとにドキュメントを自動生成してデプロイするのがベストです。説明などの情報も自動生成するなら断然OpenAPIのマニフェストを使用すべきですね。

@yanorei32
Copy link
Author

yanorei32 commented Mar 4, 2023

api.json は参考に出来るほど新しいのか

grep export -R ./packages/backend/src/models/schema | sed -r 's/^.+packed(\w+)Schema.+$/\1/' | sort

にて得られたMisskey 13.8.1 / 647ce174b33a58d00956c5fea13f5b4a69a4b590現在最新の型一覧は以下の通りです。

Antenna
App
Blocking
Channel
Clip
DriveFile
DriveFolder
EmojiDetailed
EmojiSimple
FederationInstance
Flash
Following
GalleryPost
Hashtag
MeDetailed
MeDetailedOnly
Muting
Note
NoteFavorite
NoteReaction
Notification
Page
QueueCount
User
UserDetailed
UserDetailedNotMe
UserDetailedNotMeOnly
UserList
UserLite

現在本レポジトリにあるapi.jsonとは以下の差分があることがわかり、本レポジトリのapi.jsonも既にoutdatedであることが伺えます。

diff <(jq -r  '.components.schemas | keys[]' ./misskey-hub/src/.vuepress/api.json | sort) <(grep export -R ./misskey/packages/backend/src/models/schema | sed -r 's/^.+packed(\w+)Schema.+$/\1/' | sort)
8,9c8,9
< Emoji
< Error
---
> EmojiDetailed
> EmojiSimple
10a11
> Flash
16d16
< MessagingMessage
28d27
< UserGroup

@sei0o
Copy link
Contributor

sei0o commented Mar 5, 2023

api.json については misskey-dev/misskey#9677 次第だと思います。

@yanorei32
Copy link
Author

misskey-dev/misskey#10281
とりあえずこのPR待ちな気がしています。

@Cj-bc
Copy link

Cj-bc commented Mar 14, 2023

misskey-dev/misskey#10281 とりあえずこのPR待ちな気がしています。

これに関してはひとまずはmergeされたようです。

@Cj-bc
Copy link

Cj-bc commented Mar 15, 2023

これはこちらに挙げるべきかmisskey本体にissueを立てるか悩んだのですが、一旦こちらに追記しておきます。
OpenAPIv3.0.0に関してですが、そもそもMisskeyの根本的な実装が則していないため、きちんと正しいドキュメントを生成するのは不可能なように思います。
現在のSecuritySchemesは以下のように定義されていますが:

securitySchemes: {
  ApiKeyAuth: {
    type: 'apiKey',
    in: 'body',
    name: 'i'
  }
}

OpenAPI3.0.0の定義ではtype: 'apiKey' に対して in: 'body' は有効な値として存在しません。有効なのは 'query', 'header', 'cookie'の三種類です。
(尚、現在misskeyが生成しているのが3.0.0なので3.0.0の定義を挙げましたが、現在最新のバージョンである3.1.0でも同様です。)

API Keyの渡し方としては確かにbodyを使用しているため、有効な値のどれかに変更することも適切とはいえません。もしもきちんと対応するのであれば、API自体を書き換える必要が出てくると思います(まぁmisskeyならそれ起きてもおかしくない気もしますが)

言語によっては、そのくらいの曖昧さなら気にしないで使えるかもしれませんが、型が厳密な言語ではそもそも型定義に合わずにコンパイルすることが出来ないです(例えば、HaskellのOpenAPIパッケージにあるApiKeyLocationでは型レベルで上記3種類以外を受け付けなくなっており、現状のOpenAPIドキュメントはパースに失敗します)。
現状はここだけはOpenAPIドキュメント自体にパッチを当てて適当な値にし、securityScheme周りを触らないという回避策を取ろうとしています。


但し、きちんと正しいものでなくとも「それっぽいもの」で十分な状況もあるとは思うため、出来る限りの対応を行うことには賛成です。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants