Bitbucket Pipelines でテストを走らせる

### 承前

職場ではCI動いてるし設定ファイルをいじることもあるけど、自分でイチから構築したことがあるわけではない。理解してるかというとたぶん理解してない。
知らんぷりで生きていけるかもだけど、多分こういうとこが足腰になるんだよねということで一念発起。
まじめに取り組んでみると一念発起するほどの大変なものでもなかったが、そもそもの理解が薄いためにちょいちょ躓いた。
忘却力に定評がある自分のためにメモを残す。

### 構成

こんな感じの作りだとします。
test_index.pyはindex.pyを読み込んで動作。
index.pyはcredentials.jsonを読み込んで動作。

```
(project)/webapp/test/test_index.py
(project)/webapp/app/index.py
(project)/webapp/config/credentials.json
```

### 勘違いをしていた

以下のyamlは意図した動作をしない。
pytestが見つからず、落ちてしまう。

```yaml
image: python:3.7.0
pipelines:
  default:
    - step:
        name: セットアップ
        script: # なんとなく一区切りじゃん？という薄い理解
          - pip install -U pip
          - pip install -r webapp/app/requirements.txt
    - step:
        name: テスト実行
        script: 
          - python -m pytest webapp/test/test_index.py -v
```

しばし悩み、あちこちの見本を眺めて得心。
step毎にまったく新しい環境でウゴウゴしているみたい。Dockerのレイヤーみたいなイメージでいたけど、どっちかというと全く別のコンテナが順に上がって落ちるということのよう。
そういえばCircleCIだかでそんなハマり方したことあった気がする。
そして次のステップにあれこれ持ち越しするやり方もあった気がする。
今回はとにかく最低限動かすとこまでたどり着きたいのでハードルを下げ、愚直にやる。

### 動くようになった

もうこれでダメなら帰るよというサンプル。
こいつ自体はこれで問題ないけど、中で設定ファイルを読み込んでいる箇所でしぬ。
ファイルが見つからない云々。

```yaml
image: python:3.7.0
pipelines:
  default:
    - step:
        name: テスト実行
        script:
          - pip install -U pip
          - pip install -r webapp/app/requirements.txt
          - python -m pytest webapp/test/test_index.py -v
```

### 環境変数の扱い

Firebaseを使っているので、クレデンシャルのファイルを渡してあげないとアプリが動かない。
GOOGLE_APPLICATION_CREDENTIALSみたいな名前で環境変数を定義したい。
リポジトリのページ→設定→PIPELINESの下にある「Repository variables」

> GOOGLE_APPLICATION_CREDENTIALS=webapp/config/credentials.json

最初はこのように入れてたけど、ファイルが見つからなくてしぬ。
（手元やデプロイ先の環境はDocker使っていて、絶対パスで指定できてるからこういう悩みがなかった）

そいえば、このCIってどこで実行されてんの？root？
とりあえず以下のようなしょうもないやつを実行。

```yaml
image: python:3.7.0
pipelines:
  default:
    - step:
        name: いまどこ？
        script:
          - pwd
```

どうもディレクトリは
> /opt/atlassian/pipelines/agent/build/

ここであるというのを得る。
上のディレクトリ名にこっちの設定ファイルのパスをくっつけて、
> /opt/atlassian/pipelines/agent/build/webapp/config/fb_credential.json

こんな具合で環境変数にセット。
無事に動いた。よかった。

### よくない

そんな間抜けな構築がまかり通るわけがない。
ちょろっと調べると以下のページをみつけたので、

[環境変数 - アトラシアン製品ドキュメント](https://ja.confluence.atlassian.com/bitbucket/environment-variables-794502608.html)

なるほど。そりゃそうだ。
Pipelinesが動き始めて気分が良いので、一応確認をしてみる。

```yaml
image: python:3.7.0
pipelines:
  default:
    - step:
        name: env kakunin
        script:
          - echo $BITBUCKET_CLONE_DIR
```

> echo $BITBUCKET_CLONE_DIR
/opt/atlassian/pipelines/agent/build

重畳。というわけで、再びPipelinesの設定ページで GOOGLE_APPLICATION_CREDENTIALS を ${BITBUCKET_CLONE_DIR/webapp/app/fb_credential.json に設定し直してみる。
これはうまくいかなかった。
以下のように、script内で指定することにする。yamlに書くならちゃんと展開されるであろう。

```yaml
image: python:3.7.0
pipelines:
  default:
    - step:
        name: テスト実行
        script:
          - pip install -U pip
          - pip install -r webapp/app/requirements.txt
          - export GOOGLE_APPLICATION_CREDENTIALS=${BITBUCKET_CLONE_DIR}/webapp/app/fb_credential.json
          - python -m pytest webapp/test/test_index.py -v
```

これは動いた。よしよし。
しかしなんというか、どっちがいいものかよくわからなくなってきた。
他の環境変数（TZとか）はBitbucket上の環境変数に設定しているので、散らかっちゃったのがちょっとイヤだなあ。
ともあれ動けば勝ちなので、どっちでもいいということにする。

### 次にやりたいこと

#### ほんとはDockerビルドしたい
Dockerで開発してるしDockerでデプロイしてるので、CI上もビルドしてテストを通したい。
じつはDockerでの構築も試したがうまく行かなかったために今回の形で再構築をしたという経緯がある。
stepに対する勘違いが原因でダメだっただけかもしれない。

#### cacheなるものがあってステキそうだが意味がわからない

これも調べて着手。pipとかあるので、あのだるいpipインストールをキャッシュして置けるのなら、ぜひしたい。

### 追記：Dockerでテストを走らせた

上の勘違いが解消された時点で問題が解決していたみたい。

```yaml
image: python:3.7.0

pipelines:
  default:
    - step:
        script:
          - docker build -f webapp/Dockerfile -t webapp:latest webapp
          - docker run --rm --name webapp -p 5000:80 -i webapp:latest python -m pytest  /test/ -v

```

ここでも小さな失敗があって、Docker起動のときの手癖で「-it」つけてコケてた。

> the input device is not a TTY

こんなエラーが出るのでわかりやすいけど、とりあえずtをつけたらいかんよということで。
Bitbucket Pipelinesの今月分の無料枠を使い切ったので、今回はここまで。

参考
https://qiita.com/acro5piano/items/a9ec64f78e7da304a661