GitLab Womenで喋ってきた話と、gitlab-ci only:variables

[GitLab Advent Calendar 2018](https://qiita.com/advent-calendar/2018/gitlab) 8日目の記事です。

### もくじ 
- [GitLab Women (GitLab Meetup Tokyo #11)](https://gitlab-jp.connpass.com/event/105178/) で gitlab ci の tips と要望について話したら、秒速で「この機能を使えばやりたいことができるよ!!」と教えてもらえて嬉しかった
- 早速自分のプロジェクトでも使ってみたので、やり方をまとめて教えてくれた方にお礼を言いたい
- Gitlab-jp コミュニティに参加しよう

### Meetup での発表と驚き
[GitLab Women (GitLab Meetup Tokyo #11)](https://gitlab-jp.connpass.com/event/105178/) で [gitlab ci pipeline 活用TIPSと要望](https://speakerdeck.com/mikit/20181107-gitlab-women-mikit) というLTをしてきました。
内容については下にまとめているものと同様ですが、`.gitlab-ciをcrontab的に使う` というトピックで、pipeline の表示で困っている話をしたところ、それは [only:variables](https://docs.gitlab.com/ee/ci/yaml/#onlyvariables) を使えばいいよ! と教えてもらい、目から鱗がポロリと落ちました。今回、要望としてお話をさせていただきましたが、その後、実装方法などの議論があり、コードに反映されていくまでにはそれなりの時間がかかるだろうと考えていました。実際に業務で困っていたというのもあり、その場で解決できたことで大変大変ありがたかったです。そのようなインタラクションがあったのは大きな驚きでした。対応いただいた Gitlab-jp の皆さんに感謝します。

また、ちょうど昨日の Advent Calendar を書いた @gingi99 はチームメイトで、うちのチームについては彼が [書いて](https://qiita.com/gingi99/items/a10d1a868a2bf6fe8a7c#はじめに) くれていたので、うちのチームでの gitlab の使い方や背景についてご興味のある方は、こちらもどうぞご覧ください。

### .gitlab-ciをcrontab的に使う
うちのチームでは gitlab-ci をデプロイだけでなく、任意の時間に job を走らせる使い方をしています。それぞれの job の実行開始時間は以下の通りに設定されていました。

* a: 毎時 5,15,25,35,45,55
* b: 毎日 4:00
* c: 毎日 0,6,9,12,15,18,21時の 7分
* d: 毎日 3:07

通常、gitlab-ci のスケジュール実行では、一つのプロジェクトに登録されたすべてのスケジュールが実行される時間になると、一つの pipeline として、すべての job が実行されます。

上の例でいうと、pipeline が実行されるタイミングは↓となります。

```
0:05 0:07 0:15 0:25 0:35 0:45 0:55 
1:05 1:15 1:25 1:35 1:45 1:55 
2:05 2:15 2:25 2:35 2:45 2:55 
3:05 3:07 3:15 3:25 3:35 3:45 3:55 
4:00 4:05 4:15 4:25 4:35 4:45 4:55 
      :            :
```

0:05 と 0:07 に実行される job を特定したかったため、job のスケジュール設定で任意の環境変数を設定し、.gitlab-ci.yml でその環境変数が設定されている場合にのみ必要な作業を行うように設定していました。下記の例では `ingestTotflowToHive` 環境変数が設定されている場合のみ処理を行うようになっています。

```yaml
ingestTotflowToHive:
  stage: ingestTotflowToHive
  only:
    - schedules
  script:
    - if [ ! -n "${ingestTotflowToHive}" ]; then exit; fi
    - date
    - bash -x flow/tot_ingest_10min.sh
```

他の job についても同様に、それぞれ個別の環境変数を設定・参照して処理を行うかどうかを判断するようにしていました。

これで個別の job を任意の時間に動かす、という命題は実現できていたのですが、その時間に実行すべきでない job も `Job succeeded` で終了するため、gitlab ci の pipeline 表示では処理を行わなかった job についても表示されてしまいます。目的の job を確認するときは一つ一つ内容を確認する必要があり、大変煩雑でした。

これをなんとかならない!? と話したところ、[only:variables](https://docs.gitlab.com/ee/ci/yaml/#onlyvariables) を使ってみてはと示唆を受けました。.gitlab-ci.yml にて、任意の環境変数により、それぞれの job を実行するかどうかを判断することができる命令です。

上の例を only:variables を使って書き換えると、このようになります。

```yaml
ingestTotflowToHive:
  stage: ingestTotflowToHive
  only:
    variables:
    - $ingestTotflowToHive == "true"
  script:
    - date
    - bash -x flow/tot_ingest_10min.sh
```

`ingestTotflowToHive` に `true` が設定されている時のみ `script:` セクションが実行されます。環境変数が設定されていないときにはスクリプトは実行されず、pipeline 表示にも現れず、大変スッキリしました。やったね！

[.gitlab-ci.ymlの設定ドキュメント](https://docs.gitlab.com/ee/ci/yaml/) を改めて読んでみたところ、[only:changes](https://docs.gitlab.com/ee/ci/yaml/#onlychanges) や [when](https://docs.gitlab.com/ee/ci/yaml/#when) もなかなか使えるやつでした。簡単に紹介します。

`only:changes` は指定したファイルが更新されていた時のみ、その job を実行します。Dockerfile を変更したら image を build して test を行い、大丈夫そうならコンテナのデプロイを行う、といった処理を行うのに便利です。

`when` は後処理をするのに便利です。`only:variables` と併用可能なので、先ほどの例に挙げた job が fail した時のみ、そのあとに実行するような設定ができます。

```yaml
cleanup_ingestTotflowToHive:
  stage: cleanup_ingestTotflowToHive
  only:
    variables:
    - ${ingestTotflowToHive} == "true"
  script:
    - set -x
    - rm -f flow/tmpfile
  when: on_failure
```

当初 gitlab-ci を使い始めた頃にはこんな機能なかったのに、知らないうちに色んな命令が追加されていて、どんどん使いやすくなってるんだな〜と実感しました。

### コミュニティ
Gitlab は日本にコミュニティがあり、日本語での Meetup や slack で発表や質問、コントリビュートの相談をすることができます。
join して、使っていて困ったこと、やりたいことの実現方法など、聞いてみてはいかがでしょうか。何か道が開けるかも。

- compass https://gitlab-jp.connpass.com
- slack join URL https://gitlab-jp.herokuapp.com