おいちゃんと呼ばれています

ウェブ技術や日々考えたことなどを綴っていきます

Wercker で「Storing artifacts failed: Size exceeds maximum size of 1000MB」エラー

Wercker でテスト実行後の Store 時に毎回 Storing artifacts failed: Size exceeds maximum size of 1000MB というエラーが出てこけるようになったのでメモしておく。遭遇したら思い出してほしい。

忙しい現代人のための 4行まとめ

  • Wercker では環境変数 WERCKER_OUTPUT_DIR または WERCKER_ROOT で指定している場所に保存された内容を pipeline の結果とみなして、次の pipeline に引き継ぐようにしている。この内容が 1000MB を超えている、というのが今回のエラーだった
  • Photoshop や Sketch のファイルを富豪的に突っ込んでバージョン管理していたため .git/objects が 1GB に達していた
  • 根本的な対応は Photoshop や Sketch のファイルを Git の履歴から完全に削除してリポジトリの容量を削減することだが、履歴を変更するのは影響範囲が大きく、骨の折れる作業なので避けた
  • WERCKER_OUTPUT_DIR の場所にダミーデータを突っ込むことでエラーを回避するようにした

以下、詳細。

このエラーは何なのか?

公式ドキュメントによると、Wercker では、環境変数 WERCKER_OUTPUT_DIR で指定している場所に保存された内容を pipeline の結果とみなして、次の pipeline に引き継ぐようにしているようだ。

なお、WERCKER_OUTPUT_DIR の場所が空の場合は WERCKER_ROOT の内容を pipeline の結果とみなすとのこと。

そして、その際に保存される内容が 1000MB つまり 1GB を超えるとエラーになる。ソースコードでいうと下記あたり。

今回 WERCKER_OUTPUT_DIR の場所には何も保存していなかったので、WERCKER_ROOT の場所つまりアプリケーションののルートの容量が 1GB を超えてしまったようだ。

どうしてそんなにリポジトリの容量が大きいの?

いやいや、そんな、1GB もないだろうと思って確認したら、本当にあった。

$ du -d 1 -k | sort --numeric --reverse
5616664 .
2361264 ./log
1741916 ./tmp
1282332 ./.git
79432   ./fonts
66560   ./node_modules
58904   ./sketch
21544   ./spec
3908    ./app
...

log や tmp はバージョン管理していないから置いといて、.git が 1.2GB ある。まじか。

$ du -d 1 -k .git | sort --numeric --reverse
1282332 .git
1281856 .git/objects
320     .git/logs
40      .git/hooks
12      .git/refs
8       .git/info

容量の大きなファイルを見つけ出す

容量の大きなファイルを、既に削除しているものも含めて見つけ出すには git verify-packgit rev-list を使う。下記が詳しい。

が、ちと面倒なので、Atlassian の人が便利スクリプトを用意してくれている。スクリプトの中で git verify-packgit rev-list を使っているのでやっていることはまあ一緒。

$ chmod 777 git_find_big.sh
$ ./git_find_big.sh

All sizes are in kB's. The pack column is the size of the object, compressed, inside the pack file.
size   pack   SHA                                       location
59483  40021  b1b3f0689a81222d5c3ce6e97b4f2d8b82122149  vendor/material-ui-kit/ecommerce.psd
52574  34323  160ef6db3c55fb1d2aed3ec3cb0cc0acec3ea305  vendor/material-ui-kit/walkthroughs.psd
48220  31339  4281b5217cff689196331e5b67cbf6d6d8f312bb  vendor/material-ui-kit/activity.psd
46329  32777  6978c5ed776c090952196f66410c1ca72f4660cc  vendor/material-ui-kit/profiles.psd
32288  23156  5df556fafe3b3db377c583a4be65de7a88425fe4  sketch/xxxx.sketch
28356  17284  8fa703c88432deb84ee684e069774ec7eccda229  vendor/material-ui-kit/menus.psd
26536  21886  30e4ac5b28ae38088517cd8ee7b0bc0cb8224a67  sketch/xxxx.sketch
26494  15927  14b654b8c42bf81357c90462113e421b8b35b340  vendor/material-ui-kit/signups.psd
20456  11372  abdbe045c64f57ca5bd6acf64ed46f10b86dca80  sketch/xxxx.sketch
19848  17705  16f50a332493d652182f6e15131667a40185e9ea  sketch/xxxx.sketch

Photoshop や Sketch のファイルを富豪的に突っ込んで、バージョン管理したため .git/objects が 1GB に達していた。

Git の仕組みをおさらい

Photoshop や Sketch のファイル、これらのファイルはひとつあたり 50MB だったが、Git ではファイルを更新してコミットする度に blob オブジェクトとして .git/objects に保存される。リポジトリからファイルを削除しても、歴史に刻まれている以上 .git/objects の中には残り続ける。

このあたりの説明は『入門 Git』(濱野純)が図解付きでとても分かりやすかった。

入門Git

入門Git

根本的な対応方法

根本的な対応はリポジトリの容量を減らすということになるのだが、それは前述の Photoshop や Sketch のファイルを「最初からバージョン管理対象としなかった」ことにすることであり、歴史の大幅な書き換え作業になるので、だいぶ影響範囲が大きく骨の折れる作業になる。

やるとするならば、下記の git filter-branch を使うか、もしくは、それをもう少し扱いやすくした BFG Repo-Cleaner を使うことになる。

ひとまずエラーを回避する

今回はリポジトリのほうはいじらず、WERCKER_OUTPUT_DIR の場所にダミーデータを保存するようにした。

具体的には、wercker.yml に下記のように記述した。

steps:
  # ...
  - script:
      name: output dummy file
      code: touch $WERCKER_OUTPUT_DIR/dummy

これでひとまず Wercker のエラーを回避できるようになった。

いまの気持ち

そろそろ Git LFS(Large File Storage)を試してみようかな。