Mobile Factory Tech Blog

技術好きな方へ!モバイルファクトリーのエンジニアたちが楽しい技術話をお届けします!

巨大なリポジトリのJenkinsからCircleCIへの移行においてshallow cloneとsparse checkoutで前処理を高速化する

はじめに

こんにちは!モバイルファクトリー Advent Calendar 2019 24日目担当の@PikkamanVです。 今回は運用中のプロダクトのCIをJenkinsからCircleCIへ移行するにあたり特にハードルが高かった点の解決方法を紹介します。 オンプレのJenkinsサーバでフルテストを回すのが前提となっていたリポジトリをCircleCIで扱うにあたり、shallow cloneとsparse checkoutを活用することでテストの前準備の高速化を図りました。

背景

今回扱うリポジトリは物理サーバ上に開発環境を用意することが前提になっており、テストも同様に単一の物理サーバ上で実行されていました。長期間の運用により総コミット数は90,000回を超え、リポジトリのサイズは30 GB弱となっていましたが、社内の強力なサーバ上でJenkinsを利用することで高速にテストを実行できていました。サーバ上に常にローカルリポジトリが存在するので、最新のコミットとの差分だけをリモートリポジトリから取得すればよかったためです。

しかし、CircleCIは通常の設定のままcheckoutするとまっさらな状態からリポジトリをコピーするので、歴史ある巨大なリポジトリではテストの前処理にサイズに比例して時間がかかる問題がありました。そこで、CircleCIにおいてgitのshallow cloneとsparse checkoutを活用することで高速にリポジトリをコピーし、テストの実行開始を早めることを目指しました。

shallow clone

今回のリポジトリは約5年間の運用を経て .git のサイズは約18GBにまで大きくなっていました。リポジトリ全体のサイズが約30GBなので、その占める割合が分かります。そのため、通常のgit clone を行うと大変時間がかかりました。しかし、想定しているCI環境においては対象のブランチの最新コミットに対してのみテストが実行できれば十分です。そこで、shallow cloneを使うことよりcheckoutの時間を短縮しました。

command: |
      git init
      git remote add origin "$CIRCLE_REPOSITORY_URL"
      git fetch --depth=2 origin "$CIRCLE_BRANCH"
      git fetch --depth=1 origin HEAD:refs/remotes/origin/HEAD
      git checkout "$CIRCLE_BRANCH"
      git reset --hard "$CIRCLE_SHA1"

sparse checkout

また歴史的経緯からリポジトリには画像などのサイズの大きいアセットが含まれており、約8.5GBを占めていました。これらをリモートリポジトリからコピーするには時間がかかります。よってsparse checkoutによって、サイズの大きいアセットはclone時に除外することを考えました。sparse checkoutは以下のようにcheckoutするディレクトリを .git/info/sparse-checkout に指定することで設定可能です。あるディレクトリAに含まれる特定のディレクトリBだけを除きたい場合は、ディレクトリA!ディレクトリA/ディレクトリB を両方指定することで実現できます。

command: |
      git config core.sparsecheckout true
      echo 'ディレクトリ1
      ディレクトリ2
      ...
      !除外するディレクトリ1
      !除外するディレクトリ2
      ...
      ' >> .git/info/sparse-checkout

しかし、除外したアセットに対してもそのファイルの存在を確認するテストなどが書かれていました。ですがサイズの大きなアセットこそが前処理の高速化においてボトルネックになっていたため、sparse checkoutはぜひ導入したい機能でした。ここでテストの中身に注目すると、テストされていた機能はめったに変更が入らず、また他の機能への影響も少ないものであることが分かりました。そこで、日中の開発中は対象のテストを除外して高速化を行う一方、1日1回すべてのテストを実行し、テスト実行時間と網羅性のバランスを取ることにしました。 まずは通常トリガされる build workflowの他に、1日1回実行される nightly workflowを用意します。nightly workflowでは、sparse checkoutによるアセットの除外を行わない checkout_code_full を設定しています。(上の例で !除外するディレクトリ1 などを削除するイメージです)

workflows:
  version: 2
  build:
    jobs:
      - checkout_code
      - frontend:
          requires:
            - checkout_code
      - backend:
          requires:
            - checkout_code
  nightly:
    triggers:
      - schedule:
          # UTC表記 平日の午前7時20分から実行
          cron: "20 22 * * 0-4"
          filters:
            branches:
              only:
                - develop
                - /base-.*/
    jobs:
      - checkout_code_full
      - frontend:
          requires:
            - checkout_code_full
      - backend_full:
          requires:
            - checkout_code_full

さらにアセット関連のテストも実行する backend_full ジョブにおいて環境変数 BUILD_TIME を設定します。

  backend_full:
    docker:
      - image: ...
        environment:
          ...
          BUILD_TIME: nightly
          ...

そして対象のテストの始めに環境変数を見てテストをスキップするかどうかの処理を追加しました。

use Test::More;
...

if($ENV{BUILD_TIME} ne 'nightly') {
    plan skip_all => 'No images';
}

subtest 'subtest_name' => sub {
    ...
}

done_testing;

こうして1日1回だけ実行されるnightlyジョブでアセット関連のテストを行うことができるようになりました。

まとめ

以上のように、shallow cloneとsparse checkoutを組み合わせた上にCircleCIのworkflowを使い分けることで

  • 日中の開発中はサイズの大きいアセットを除いてテストすることで実行時間を短縮し、開発のストレスを減少させる
  • 1日1回すべてのアセットを含んだテストを実行することでテストの網羅性を確保し、重大な開発の手戻りを防止する

の両方を実現することができました。巨大なリポジトリをCircleCIへ移行するにあたってヒントになれば幸いです。

はじめての技術イベント ~Vue.js for 2020に参加してきました!~

モバイルファクトリー Advent Calendar 2019の23日目の記事です。

ヒューマンリレーションズ部の@overallfactoryです。 普段は新卒の総合職採用を中心に活動しています!

はじめに

12/11(水)に開催された「Vue.js for 2020」にスポンサー企業としてブースを展示させていただきました! 私も非エンジニアながら会社の宣伝をするべく、ブース展示に協力をすることになっていたのですが、 1つ問題が…それは、私がエンジニア向けのイベントに参加したことが今までなかったことです…

参加を依頼された時は、「技術的な話ができない私では、参加しても価値がないかも」 「自分が技術的なことを話せないあまり会社が悪く見えたらどうしよう」など考え過ぎてしまい、イベントに参加するまで緊張と不安でいっぱいでした。

この記事では、そんなエンジニア向けイベント初体験で不安だらけだった私が、イベントに参加して感じたことを書いていきます。 初めて技術イベントに参加される方に、少しでも参考になればと思います!

自分が持っている技術の知識では、全く話の理解ができない

控えめに言って、登壇されてる方のプレゼン内容は全く理解できなかったです。 ちょっとだけ、私もプログラミングをかじったことがあったので、多少はわかるかなと考えていたのですが、甘かったです。 自分が学生時代にかじった程度の知識など全く通用しなかったです。

また、モバイルファクトリーのブースにてエンジニアの方とお話しをしたのですが、 繰り出される質問が全く理解できず、懇親会の序盤はテンパりまくってしまいました。

会社を良く見せようと、「会社のことについての質問はどんなものでも、明快に答えよう」と準備をしていましたが、 凄い勢いで、知らないワードが投げかけられるため、全然うまく質問に答えられず、冷汗が止まらなかったです。

開始数分で、技術的な質問はわからないと正直に言おうと心に決めました。 ちょっとのプログラミング経験で、知ったかぶりをしたところで誰の価値にもならないと思います。 自分には知識がないことを認めて、わからないと言うことも時には大事です。

f:id:overallfactory:20191223114949j:plain

「わからない」ことを「わからない」と言うことは重要

プレゼン中、懇親会中と、あまりにも自分には理解のできないワードが飛び交っていたので、 途中で自分の恥を捨てて、「技術のことわからないんです!」って言うことにしました。

周りから「な〜んだ、お前技術のことわからないのかよ!」って思われてしまい、 ブースから人が離れていってしまうんじゃないかと不安だったのですが、そんことはなかったです。

むしろ、「技術はわからないんです!」と伝えたら、 「じゃあ、どんな企業なんですか?」「なんでブロックチェーン事業をやっているんですか?」と、 企業についての質問をたくさんしてくれました。

企業説明となれば、技術がわからない私でも話せます。 「面白そうな取り組みですね!」「こんな会社があったんだ!」と驚いてくれる人がいたのを見ると、 少しは私も会社の宣伝に貢献できた気がします。

また、逆にこちらから「どんな技術に興味あるんですか?」「どんなことがその技術でできるんですか?」と聞くと 私にもわかるように、わかりやすい言葉で皆さんが説明してくれました。 エンジニアの皆さんが優しすぎて感動しました。技術的に難しいことを優しく話せる方って本当にすごい! 自分も会社のことや事業のことを、もっとわかりやすく話せるようにならねばと強く感じました。

参加者の知的探究心が高い

モバイルファクトリーのブースでは、「Vue.jsの好きなAPI」のアンケートとサンプルコードを展示していたのですが、 ブースの前を通る方のほとんどの方が足を止めて、サンプルコードをかじりつくようにみていました。 サンプルを見て気になることがあれば質問していただいたり、近くの人と議論したりと、本当に皆さん知的好奇心が高いなぁと 終始感心させられっぱなしでした。

師走の忙しさで最近インプットをサボり気味だったのですが、参加者の方を見て、自分も採用や広報のことをもっと深く学んでいかないとと刺激をもらいました。

ちなみに、「好きなAPI」についてのアンケートにはブースに来てくれたほとんどの方が回答してくれました! 約来場者の30人の方が回答してくれて15票でComposition APIが一番人気であるという結果になりました。 ご協力してくださった皆さんありがとうございました!

f:id:overallfactory:20191223115020j:plain

speakerdeck.com

お酒は偉大だ。。。

懇親会でお酒が入ってくると、緊張が抜けてきて、 エンジニア、非エンジニア関係なくざっくばらんにお話をすることができました。

モバイルファクトリーでは、冷凍みかんをスポンサーとして120個ほど提供したのですが、 参加者の方や他のスポンサーの方から「なんで冷凍みかんを選んだのか?」と質問攻めにされました。

まさか冷凍みかんの話で盛り上がると思っていなかったですが、たくさんのエンジニアの方とお話しできるきっかけになって よかったです。冷凍みかんありがとう笑

f:id:overallfactory:20191223115028j:plain

まとめ

以上が私がイベントに参加して感じたことです。 参加してみるまで、「エンジニアの方は技術的な話を参加者は求めているだろう」と決めつけて、 「エンジニアの方と何を話したらいいんだろう?」「相手にメリットのある話ができるかな?」って不安になっていました。

でも、それは自分の勝手な思い込みでした。 実際に「技術のことは話せない」と伝えた上でも、「会社の事業やミッション」「会社の風土」について聞いてくれる方はたくさんいましたし、 話を聞いた上で「面白い」「こんな会社があったなんて知れてよかった!」と、言ってくれる方もいました。

変にカッコつけてなんでも答えようとせず、「自分は技術のことは話せないが、これなら話せる!」と相手に伝えてあげたからこそ、 コミュニケーションが円滑に進み、自分が一番伝えたかった会社のことを伝えることができたと思います。