CircleCI 2.0でbuild_dirを指定する


今更ながらCircleCIを2.0にアップデートしました。
対応する機能がない部分等で若干詰まったのでメモします。

# CircleCI 1.0の設定

1.0では以下のような設定でcheckoutした後のcurrent directoryを指定できました。

```yaml:circle.yml

general:
  # ここで設定することでrepository内のdirectoryを指定できた
  build_dir: api

test:
  override:
    # run local unit tests
    # test_runner.pyがapi/以下にある場合でもこのまま実行できる。
    - python test_runner.py $HOME/google_appengine .
    
    # もし指定しない場合は毎回cdする必要があった。
    - cd api && python test_runner.py $HOME/google_appengine .

```

こうするとことでrepositryのルートにないプロジェクトのテストが行えました。
（逆に複数プロジェクトが含まれるケースは面倒でした）

# CircleCI 2.0では、、

2.0では対応する設定はありませんでした。
working_directoryという設定がありますが、これはレポジトリのcheckout前に指定するもので、
checkoutした先のディレクトリはグローバルに設定することはできません。

- [Equivalent of CircleCI 1.0 build_dir](https://discuss.circleci.com/t/equivalent-of-circleci-1-0-build-dir/12840/4)

上の会話にありますが、回答としては、runコマンドごとにworking_directoryを指定できるので、これで解決できる、ということです。

```yaml:.circleci/config.yml

  build:
    # この設定はcheckout先の指定であって、repository内のdirectoryは指定できない
    working_directory: ~/project
    docker:
      - image: circleci/python:2.7.14-stretch-browsers
    steps:
      - checkout # ここでworking_directoryにcheckooutされる
      - run:
         name: Build the Docker Image
         command: make package
         working_directory: docker/docker-images/image1 # 各ステップでそれぞれ指定できる
      - deploy:
         name: Publish a Docker Image
         command: make publish_branch
         working_directory: docker/docker-images/image1

```

一つのレポジトリ内の複数のモジュールのテストを行うことなどを考えると、この方が自然かなーと思ったりするので、便利さはどちらがいいかはわからないですね。
複数モジュールの場合は環境も違う可能性があるので、複数ワークフローとかにした方が良さそうですが。。

## cacheの指定など
若干面倒なのはcacheなどを保存するときに比較するfileのパスも指定しないといけないことでしょうか。

run/deployステップと同じようにrestore_cacheやsave_cacheステップにworking_directory指定をできたら書き方が統一できるんですが、残念ながら動きません。

### 動かない設定
以下のように書いても動かず、

```yaml:config.yml
      - restore_cache:
          working_directory: api # ここのブロックには有効にならない
          key: venv-{{ checksum "requirements.txt" }}
      - run:
          name: Create venv
          working_directory: api # ここは使える
          command: |
            virtualenv venv
            . venv/bin/activate
            pip install -r requirements.txt
      - save_cache:
          working_directory: api # ここのブロックには有効にならない
          key: venv-{{ checksum "requirements.txt" }}
          paths: venv
```


> Error computing cache key: template: cacheKey:1:8: executing "cacheKey" at <checksum "requirements.txt">: error calling checksum: open /home/circleci/project/requirements.txt: no such file or directory

と言われてしまいます。

### 正しい設定
正しく動かすには、以下のようにする必要があります。


```yaml:config.yml
      - restore_cache:
          key: venv-{{ checksum "api/requirements.txt" }} # checksum関数に渡すときに示す。
      - run:
          name: Create venv
          working_directory: api # ここは使える
          command: |
            virtualenv venv
            . venv/bin/activate
            pip install -r requirements.txt
      - save_cache:
          key: venv-{{ checksum "api/requirements.txt" }}
          paths: api/venv # 保存するパスもきちんと示す
```


なんか統一感がなくて、ちょっとしっくりきませんが、キャッシュを利用すると速度がだいぶ上がるので、どんどん利用したいですね。
(他にも変数展開が部分的にできたりできなかったりjobごとにrestore先のパスを指定できなかったりには不満がありますw)

開発に依存のない部分はbaseのdocker imageで適宜アップデートする方がいいと思いますが、それはそれでメンテコストが上がりそうですね。。