この記事は川見てる Advent Calendar 2021およびMoney Forward Engineering Advent Calendar 2021 17日の記事です。
はじめに
マネーフォワードでことし10月から京都や鴨川🦆の良さを社内にひたすら宣伝しながらGoやYAMLなどを書いているwalkureです。
入社時の部署自己紹介で「趣味は鴨川🦆です」と言ったりSlackの分報へ鴨川🦆の写真をひたすら貼り続けていたところ、カモグルイ*1とか呼ばれるようになりました。
殆どの仲間は東京にいるので、あづまの地に鴨川🦆の良さを広めるべくこれからも尽力してまいります。
最近は天気がいいので朝起きたら鴨川🦆まで行ってラジオ体操してから就業するというドカタ時代のような生活。
現在*2は週一回出社しましょうということになっていて、勤務地が三条大橋西詰にあるので出社したときも気分転換に鴨川🦆しています。
人間的な生活はここにあった。
今日から始めるCircleCI
入社以来ひたすら鴨川🦆の宣伝GoやYAMLを書いています。東京ではひたすらC#を書いていたので、Goはまだまだ修行中。YAMLですがおもにCircleCIの設定やk8sのmanifestを書いています。
今日は、CircleCIを使ったことない*3わたしが「CircleCIの設定を書いて」って言われた際にいろいろ調べて戦ったメモを(ちょっとだけまともに書き直して)供養することにしました。CIの設定ってプロジェクト立ち上がるときには頑張るけど、走り出すと結構忘れてしまうので覚えているうちに書いておきましょう。
設定リファレンス
command → job → workflow
- Orb、ジョブ、ステップ、ワークフロー - CircleCI
- 処理の流れについて
command
make build
などの実行コマンドをまとめられる- 実行は
steps
内にrun
を書き連ねる
- 実行は
- 実行単位でない
job
- 実行単位
steps
内でcommandをたたいたり、run
をたたいたり- 実行するコンテナイメージ設定もできるぽい
- 実行環境はexecutor(後述)で指定する
workflow
- jobを並列実行する
- 依存関係も設定できるので実質直列実行もある
- 実行条件(特定のブランチは無視するとか)も指定
- ワークフローを使用したジョブのスケジュール - CircleCI
orb
CircleCI Orb とは、ジョブ、コマンド、Executor などの、パラメーター化および再利用が可能な構成要素をまとめた共有可能なオープン ソース パッケージです。
Orb の概要 - CircleCI
- 要はcommand(やjobなど)を外ファイルに切出して引っ張ってこれるようにしたもの
- 例えばgoだと環境インストールや
go mod
をキャッシュするなどの定番作業がorb化されている - 再利用可能な設定ファイル リファレンス ガイド - CircleCI
- command に引数設定できるよとかexecutorを名前付けできるよとか
- jobも引数取れる
- これらが外部に吐出されたものがorb
- orbのレポジトリはCircleCIがホストしてる
キャッシュ
- CIで立ち上がってくるVMの一部ディレクトリをキャッシュすることができる。
- パッケージマネージャで拾ってくる依存はちゃんとリビジョン指定していれば、毎回同じものを取ってくることになる。
- Caching Dependencies - CircleCI
- CircleCI 2.0 で Go 1.10 の build cache をいい感じに効かせる | Hori Blog
- 前出のorbでもgoとかだとgo modのキャッシュをシュッと効かせることができる
- クラウドでしか使えない(後述)ことに留意。
設定はYAML
- YAML の記述 - CircleCI
- YAMLで一行に収まらないものを複数行でやりたい
- CircleCIのcommandで改行を入れてみやすくする方法 - #人生戦略実行マニュアル
- syntax - How do I break a string in YAML over multiple lines? - Stack Overflow
>
で始めると\n
を消して連結してくれる。|
だと\n
はそのまま残して連結>
は長いワンライナーを複数行で書くとき、|
はcommand
にshell scriptを貼るときに便利そう。>
はインデントがそろってないと\n
を消してくれない。- これは
>
に特有みたいなので要注意。
- これは
>
や|
に-
をつけると、行末の\n
を消してくれる|-
は最後の\n
だけなくなるのであんまり意味を感じない。>-
は意味があるかも。
- YAMLで複数行テキストを書きたい時のあれこれ - Qiita
- 連結時に空白を勝手に挿入する。それを外すにはquoteして行末に
\
を入れるしかない。
- 連結時に空白を勝手に挿入する。それを外すにはquoteして行末に
- Transform YAML into JSON - Online YAML Toolsで実際に試して感覚を掴む。
シェル芸がときどき必要
- ex. How to check if a file exists in a shell script - Stack Overflow
- シェルスクリプトを書くとき覚えておくこと一選 - weblog of key_amb
- (Linux)コマンドを連結して行う「;」「&」「&&」「||」の違い : old_3流プログラマのメモ書き
- bash スクリプトの先頭によく書く記述のおさらい | Money Forward Engineers' Blog
set -euo pipefail
みたいなやつ
- CircleCIは
#!/bin/bash -eo pipefail
でコマンドを実行する
CircleCI は Bash を使用します
環境変数の使用>環境変数の使用オプション - CircleCI
run
でshell起動する際の設定が色々ある
すべてのコマンドライン プログラムの呼び出しに使用します。
CircleCI を設定する > jobs.steps.run - CircleCI
- job stepの失敗は何も設定しなければ
$? != 0
when
で失敗条件を変えたり、circleci-agent step halt
でジョブを終了したり
when
はrun
の中と外に存在できて、意味が変わる- 中にあるときは前出
- 外にあるとステップの実行条件になる
- 使ってるとconfig.ymlの複雑度が爆発しそう・・・
- パイプライン変数 > 条件付きワークフロー- CircleCI
パラメタとしての環境変数
- あちこちで設定できる
- 環境変数の使用 - CircleCI
- プロジェクト単位での設定→context(後述)→システム定義済み→job定義→runでの定義→run command内 の順番に設定されてゆく
context
- コンテキストの使用 - CircleCI
- 外(CircleCI組織全体の管理)から注入できる環境変数の集合
- 読み書き権限が設定できるので、APIキーとか設定するのに便利
- workflow単位で引用設定
- workflow内で呼ばれるjob/commandから見える
- CircleCI上のマシンで環境変数を扱う場合はContextsを使うと便利 - コード日進月歩
- 同一keyの環境変数もった複数のcontextを引用する(env keyを衝突させる)と何が起きるのか
- エラー吐いてくれるのかな?(まだ試せていない)
デバッグ
- ローカル実行と実際にクラウドを叩くのふたつ
YAMLのデバッグとjobs実行はローカル実行できる
- YAMLのチェックは
circleci config validate
でいける - ジョブの実行は
circleci build --job hoge
- CircleCI のローカル CLI の使用 - CircleCI
- CircleCI ローカルでCircleCIを使いたい
- まさかPushデバッグしてないよね? よく使うCircleCIのデバッグ方法 - VTRyo Blog
- CircleCIのジョブをローカルPC上で実行する | Hodalog
CIを動かす環境(executor)
- Executor タイプの選び方 - CircleCI
- Executor とイメージ - CircleCI
- docker→ machine/macos/windows の順に抽象度が下がり自由度が上がる
- Executor Migration from Docker to Machine - CircleCI
- Docker executorとMachine executorの違いについて書いてある
CIは基本的にコンテナ上で動く
- CircleCI のビルド済み Docker イメージ - CircleCI
circleci/
のイメージからcimg/
のイメージに移行するべきらしい
Docker executor
image
は複数指定できるが、最初に指定したimage
でCIは動くので書く順番は大事
複数のイメージを指定して設定されたジョブでは、最初にリストしたイメージによって作成されるコンテナで、すべてのステップが実行されます。 すべてのコンテナは共通ネットワーク内で動作します。 また、公開されるポートはすべて、プライマリ コンテナから localhost で利用できます。
Executor タイプの選び方 - CircleCI > 複数の Docker イメージを使用する
- 複数コンテナ間はtcpで会話できて
docker-compose
っぽいなにか(docker-compose
ではない) - circleci で複数イメージを指定したとき、それは docker としてどのような構成で実現される? - スタック・オーバーフロー
- netnsを使っているらしい。
2つ目以降のimage
で指定したコンテナが起動完了するのを待ってはくれない
- 前述したキャッシュ等でステップの実行速度が変わることによって並行タスクを追い抜いて事故
- キャッシュのせいで速度が変わる場合、ローカルでは起きずクラウドに上げて問題が顕在化するような辛い事態が起きる。
- プライマリコンテナでの作業がセカンダリコンテナの起動完了に依存する場合、完了を待つ
step
を入れるとか nc
やdockerize
で待つことができる- ちゃんと接続完了まで待ちたいなら、
mysql
コマンドなどでなんとかする必要がある - そもそも
run
で実行するコマンドにretry機能があればそれで十分説- 無限にretryされたらそれはそれで困るのでよしなに
wget
やcurl
だと--retry-connrefused
という引数があって、コンテナが立ち上がるまで頑張れる
docker
コマンドをstep
中でで使いたい場合はsetup_remote_docker
を呼ぶ
- Docker コマンドの実行手順 - CircleCI
docker-compose
を使いたい場合は、上記の手順でdockerコマンドが使えるようにした上でdocker-composeコマンドを入れる- Installing and Using docker-compose - CircleCI
- port forwardingとvolume mountに制限がある
Using docker combined with setup_remote_docker provides a remote engine similar to the one created with docker-machine, but volume mounting and port forwarding do not work the same way in this setup.
Installing and Using docker-compose >Using docker compose with docker executor - CircleCI
- これをなんとかするにはpureにdockerが走るMachine executorを使うしかない。
- remote dockerでつながる先のスペックは固定
Machine executorについて
- CircleCI を設定する>machine - CircleCI
- Ubuntuの VMがあがってくる。
- 追加費用発生の示唆がある。
Use of the machine key may require additional fees in a future pricing update.
Installing and Using docker-compose > Using docker compose with machine executor- CircleCI
MySQLコンテナについて
- cimg/mysql https://hub.docker.com/r/cimg/mysql/tags
- circleci/mysql https://hub.docker.com/r/circleci/mysql/tags
- DBストレージを
/dev/shm
に置く-ram
がcimg
では現状ない- いらんのでは?という話になっている模様
- cf. https://github.com/CircleCI-Public/cimg-mysql#ram
- 初期設定について
*1:実際晴れた週末は結構な頻度で鴨川🦆河川敷に行って一日ひなたぼっこしてるので反論の余地が一切ない。
*2:緊急事態宣言がないとき。
*3:今まで触ったことあるCIツールはCloud Buildぐらい。