27
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CircleCIで.gitディレクトリをキャッシュしてチェックアウトを高速化する

Last updated at Posted at 2018-06-25

最近でCircleCIおじさんになっているりんご(@mstssk)です。

今やっているプロジェクトのgitリポジトリが大きくなりすぎて、CircleCIでの checkout の実行に何分もかかってしまっています。
以前は2〜3分だったのが、先日は8分もかかってました。

思い切って.gitディレクトリをキャッシュしてしまうようにして、10秒前後で済むようにしてみました。

追記2019/02/19
本記事の内容を試す前に、あなたがCircleCIで使っているDockerイメージにgitとsshがインストールされているか確認しましょう。
gitとsshが無い場合、CircleCIがFallbackしてチェックアウトを行ってくれるのですが、これはイメージ上のgitとsshを使うより遅いようです。
FallbackしているかどうかはCircleCIの各ジョブのページでCheckout codeステップのログを見ればわかります。

参考記事

やった内容は、下記の公式ドキュメントとクラウドワークスさんのエンジニアブログ記事を参考にしたものです。

クラウドワークスさんの記事には、.gitのキャッシュではなく、shallow cloneすることでチェックアウトを高速化する手段が書かれていますが、私は.gitをキャッシュする方法を選択しました。
キャッシュの方法は公式ドキュメントに記載されているからというのもありますが、CircleCI上でshallow cloneするには別途GitHubのアクセストークンを用意する必要があり管理上の手間が増えてCIの管理が属人化しすぎるのを嫌ったためです。

CircleCIで .git ディレクトリをキャッシュする

実際のCircleCIの設定ファイルは以下のように記述しています。

.circleci/config.yml
version: 2
jobs:
  foobar-job:
    steps:
      # 公式ドキュメントに書いてある.gitをキャッシュするやり口
      # https://circleci.com/docs/2.0/caching/#source-caching
      - restore_cache:
          keys:
            - dot-git-cache-{{ .Environment.CACHE_KEY }}-{{ .Branch }}-{{ .Revision }}
            - dot-git-cache-{{ .Environment.CACHE_KEY }}-{{ .Branch }}-
            - dot-git-cache-{{ .Environment.CACHE_KEY }}-
      # レストア時にワーキングディレクトリがcleanじゃないことがあったのでhard reset。echoはexit code食わせるため
      - run: git reset HEAD --hard || echo ng
      - checkout
      - save_cache:
          key: dot-git-cache-{{ .Environment.CACHE_KEY }}-{{ .Branch }}-{{ .Revision }}
          paths:
            - ".git"
  • restore_cachekeys を複数指定しているのは、合致するキャッシュがなければ別コミット・別ブランチのCIのキャッシュを拾うためです。
  • {{ .Environment.CACHE_KEY }} は任意にキャッシュをクリアするため。CircleCIで CACHE_KEY という環境変数に適当な文字列を入れておいて、キャッシュをクリアしたいときに値を変えることでキャッシュのキーを変えてしまっています。
  • git reset HEAD --hard || echo ng は、レストア時にワーキングディレクトリがcleanじゃないことがあったためです。キャッシュをレストアしない場合は git reset が失敗するので、echoでexit code食わせてごまかしています。
  • .gitディレクトリをキャッシュからレストアした状態で、CircleCIの checkout を使うと、ちゃんとレストアした.gitを使ってくれるので、差分だけの取得になり高速になります。

このやり方の注意点として、変なブランチ名の付け方をしてしまったときに、キャッシュ済みのリポジトリ情報と新しいブランチ名が衝突してうまくチェックアウトできない場合があります。
具体的には feature/foo/bar というブランチを作ったあと、それを消して feature/foo というブランチを作ると、キャッシュからレストアした.gitディレクトリに feature/foo/ が既にいるので feature/foo のチェックアウトに失敗します。
めったにないことですし CACHE_KEY を変更すれば済むので、これについては特別な対応はしていません。

27
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?