主にプログラミング関連のメモ帳 ♪(✿╹ヮ╹)ノ
書いてあるコードは自己責任でご自由にどうぞ。記事本文の無断転載は禁止です。
2022/04/23
みなさん Git LFS を使用していますか?
わたしは VRChat のアバタープロジェクトをまるまる GitHub へあげているついでに、 Git LFS で 3D モデルやテクスチャーも状態を保存しています。
そこで困るのが、 GitHub のストレージ課金です。 50GB で 60USD/year かかるのですが、これをオンラインストレージで換算すると、微妙に高くない?となります (Wasabi とか 72USD/year で 1TB だしね)。
例えば、ウチのプロジェクトの場合、大きいもので数十 GB くらいあったりするので、それをアップロードするとオシマイです。
そうなるとどんどん高くなって行っちゃうので、個人的には S3 とかにバックアップしたい気持ちがあります。ということで、 Git LFS サーバーを実装してみました。
といっても必要なのは1つだけで、以下のエンドポイントを実装すれば OK です。
POST /objects/batch
わたしは認証機能を付けたかったので、 POST /:user/:repository/objects/batch
として実装していますが、基本的にこのエンドポイントだけ実装してあげれば、 Git LFS サーバーとして必要最低限の機能が動くようになります。
レスポンスも簡単で、次のような型を持つレスポンスを返せば OK です。
type GitLfsObject = {
oid: string;
size: number;
authenticated: boolean;
actions: {
upload: {
href: string;
expiresIn?: number;
headers?: any;
},
download: {
href: string;
expiresIn?: number;
headers?: any;
}
}
};
type GitLfsResponse = {
transfer: "basic" | "lfs-standalone-file" | "ssh";
objects: GitLfsObject[];
};
簡単ですね。
Git LFS クライアントからのリクエストは以下の通り。
type GitLfsRequest = {
operation: "verify" | "upload" | "download";
transfers: string[];
objects: { oid: string; size: number; }[];
};
基本的には、 operation == upload
のときには、 actions.upload
、 operation == download
のときには actions.download
を返してあげれば問題ありません。
それぞれの中身も、 href
に、それぞれの操作に対応した S3 の Pre-Signed URL を詰め込んで返せば、 Git LFS クライアントが良い感じにしてくれます。
ということで、 Git LFS サーバーの実装についてお話ししてみました。
具体的なコードについて知りたい場合は、下記リポジトリに Vercel にデプロイ可能なコードを置いているので、参考にしてみて下さい。