v2で自由自在に業務ワークフローのタスクを実行するごきげんよう、CI日和ですね。Botからトリガーして実行していた業務ワークフローの必要なタスクをえいやっとCircleCIに持っていったのでその話をします。長いので要約するとヘビーにJenkins使ってたのを全部CircleCIに持っていきました。2.1の機能をつかって設定を書きました。必見です自前運用のJenkinsさんお疲れ様でしたテストを継続的に動かす環境といえばJenkinsです。カヤックでも多くのプロジェクトでテストや、その他様々なタスクを実行する環境として利用されてきました。ぼくらの甲子園!ポケットもそういった例に漏れず、Jenkinsをヘビーに使っていました。自分で運用するJenkinsの面倒を見続けるのも以下のようなデメリットが生じる状況になってきました。勝手に機能が増えるみたいなことにはならない。プラグインを入れると強くなる。フルマネージドは勝手に機能が増えて強くなるまた、数あるCIサービスの中でもCircleCIを選択しました。Planも契約済みだったからです。導入するハードルがたまたま一番低かったからとも言えます。他の会社さんではCircleCIが最適だとは限りません。他の理由としては、フルマネージドのCI環境を提供するサービスの中では、並列でCPU時間を大量に使うような重いテストに比較的最適なサービスかと思います。いうわけで、移行を以下の手順で行いました。テストの実行をJenkinsからCircleCIへ移植Jenkinsで従来行っていた業務タスク実行をCircleCIへ移植ちゃんと全部CircleCIで動いているのを確認してJenkinsを撤収そんなわけで、現在の構成と、やっているタスクを挙げてみます。図にある通り、Jenkinsが2つあります。1つはテスト用のJenkinsで、EC2スポットインスタンスで強いインスタンスを用いたものです。1つは、プロジェクト内の開発サーバに立てたJenkinsです。botをトリガーにしてタスクを実行しています。このJenkinsでは、Googleスプレッドシートからマスタデータの取り込み開発環境へデプロイアセットデータの生成などなど、業務ワークフローに必要なタスクが行われています。CircleCIとJenkinsどちらも管理するのも面倒なので、こういったタスク類もCircleCIにお引越しします。CircleCIでテストを実行するテストを実行するのはCircleCIのもともとの用途なので、そこまで変なことはしていません。Jenkinsで実行されていたテストは以下の仕様でした。LinuxベースのDockerコンテナイメージ上で実行テスト対象はPerlアプリケーション。go-proveで並列実行コンテナ内にMySQLを並列数分立ててテストに利用64vCPUを利用できるインスタンス1台で80並列実行CircleCIもDockerを利用するほうが便利なのと、もともと並列数もべた書きではなく、コア数に応じてスケールするようになっていたため、変更せずにそのまま利用します。Planを使用しています。この移行では8vCPUのxlargeを使用します。splitを使った並列実行をします。CircleCIテストを実行するタスクを記述していきます。以下に登場するYAMLファイルはリポジトリの.circleci/config.ymlに書いていきます。設定に使うCircleCIのバージョンは、2.1を使っています。以下の例は一部を抜粋している形です。完全なYAMLの例が見たい方は、公式ドキュメントの例を参照するか、以下の記事を参考してください。させよう!executorテストの実行環境を設定します。2.1では実行環境をexecutorsという形で記述し、jobから設定を呼び出せるようになりました。ECRからDockerイメージをpullして使うようにしています。*test_reportersおよび、*working_directoryはCircleCIの機能ではなくYAMLのアンカー/エイリアスの機能で定義しています。YAMLの他の場所からでも、同じ値を呼び出すためにこうしています。Dockerイメージの置き先テスト用のコンテナイメージのpullの話題が出たので、イメージの置き場所のついての工夫も述べます。普段はap-northeast-1、つまり東京リージョンを使っているのですが、CircleCI上のイメージに関してはus-east-1を用いています。ap-northeast-1に置いていたところ、us-east-1への転送料金がAWS側に発生していたのを抑えたいのでus-east-1に引っ越ししました。副次的な効果として、初期化時のイメージのpullも早くなりました。以上のことから、ジョブは現在AWSのus-east-1で走っているようです。以下のポストにもあるように、リージョンは予告なく変更される可能性があります。2.1ではcommandsという形で、jobで使う処理のまとまりに名前を付けれるようになりました。違うjobで一部だけ同じ処理をするときに使えます。commandscommandsでは次の処理を定義しています。プロジェクトリポジトリをcloneしたものをキャッシュからリストアするCircleCIのキャッシュからリポジトリをリストアしています。歴史の長いプロジェクトで、毎回GitHubからcloneを行うには時間を要してしまうためキャッシュに保存しています。キャッシュは過去に保存したもの中にブランチ名やコミットハッシュが同じものがあればそれが、なければキーに前方一致したものが使われます。repo-v2-テスト対象のチェックアウトかなりデカイリポジトリを必要な分だけ高速にcloneやcheckoutするために、いろいろごちゃごちゃ書いているので詳細には書きません。具体的には以下のようなことをしています。先述した「リポジトリキャッシュのリストア」に使われるキャッシュを保存するものです。ここでも同じエイリアスを使って、定義を共通にしています。*working_directory依存ライブラリのキャッシュ作成とリストアCircleCIのキャッシュは本来こちらが想定されているようです。Perlのプロジェクトなので、cpanfileを読んだ依存ライブラリのインストールと、保存をしています。}}で依存ライブラリの構成が変わったときにキャッシュを再作成するような設定をしています。installテストの実行テストを実行するスクリプト自体は、もともとDockerでテストを動かすために使われたシェルスクリプトが存在していたため、それを流用しています。YAML上では以下の記述だけです。docker/circleci/app/docker_run.shこのdocker_run.shには、テスト実行時の前準備などが書かれています。Jenkinsで使われていたスクリプトを流用したものです。テストを実行する部分は以下のようになっています。splitで、テストジョブの分割を行っています。--split-by=timingsはテストの実行時間をもとにテストを分割します。現在はxlargeで10コンテナ並列でテストを実行しています。splitを使うと、コンテナごとにそれぞれ違うファイルが分配されて、分担してテストが実行されます。jobs以上に述べたexecutorsやcommandsをまとめてjobsに記述します。run_testこれで、だいたいJenkinsのときとテスト実行時間と同じ程度の速度でテストを実行することが出来ました。気になる点として、全体のジョブの実行時間のうち、テスト実行よりもコンテナイメージのpullとリポジトリのキャッシュからの復旧のほうが時間がかかっています。このあたりをチューニングすればさらに早くなると思われます。テスト以外を実行するさて、これでテストの移植はできました。今度はそれ以外のジョブの実行です。2.1を使っているので、上記のYAMLとは別にwokflowsも記述しています。/^fix\/.*/これで、onlyに挙げられているブランチがpushされれば、テストジョブが起動するわけですが、従来の「マスタデータの取り込み」といったタスクはpushとは無関係に起動する必要があります。botが発言をトリガーにJenkinsのbuildWithParametersというエンドポイントを叩いていたわけですが、CircleCIでも相当のことが出来ないか検討してみます。CircleCIでもAPIでジョブをトリガーする方法はあります。以下のドキュメントを参照してください。いきたいところですが注意点があります。上記のドキュメントから引用します。使用する場合には、単一のジョブをトリガーすることができません。思いっきり条件に当てはまっています。2.1.とも書かれています。このAPIは使用できません。このドキュメントにはworkflowsを使うケースではこちらも使えるよという記述もあります。(preview)ですがこのAPIにも難があります。supports.つまり特定のブランチがpushされたときにトリガーされるのと同じ挙動は実現できるものの、特別なジョブを実行したり、ジョブにパラメータをAPIから渡すことが出来ないと書かれています。これも要件に合いません。v2なるものを発見します。CircleCI-Public/api-preview-docsドキュメントには記載されておらず、まだプレビューリリース段階のAPIです。予告なしで破壊的な変更されることもありうるのですが、ドキュメントを注意深く見ていくと、これは使えそうだとなりました。parametersという概念が追加されています。2.1でも利用できたparametersですが、jobやcommands定義で使えるものの、workflowsでは使えませんでした。v2では、APIリクエスト時にパラメータを指定できるようになってます。workflowsでは、APIで渡されたパラメータを埋め込むことができるようになりました。parametersです。parametersの仕様は別のリポジトリで公開されています。parametersを使った例を挙げます。parametersです。parametersを埋め込んで、APIでトリガーさせてみます。>>がgreat_awesome_taskに置き換わって実行されます。ちなみにカヤックでは上記の例のmakeを使っている部分を、Daikuに置き換えて使用しています。リポジトリに置かれたDaikufileにPerlのコードでタスクを増やすと、CircleCIのconfigをいじらずにプロジェクト固有のタスクを実行できます。runでも同じことが出来るかと思います。走るworkflowを制御する上記のYAMLに加えてテストのジョブもworkflowに設定している場合に問題が起こります。pushしてテストが走ると同時に、任意のタスク実行のためにmakeが走ってしまうのです。業務ワークフローに必要なタスクをbotなどからトリガーする場合、タスク実行に使うブランチを限定する場合は容易に回避できます。workflowの設定に、filtersでブランチを列挙すれば、無駄にタスクが走るのを回避できます。/workflow.*/この例ではworkflowで始まるブランチが指定されたときのみ、ワークフロー用の業務タスクを実行します。私のプロジェクトでは特定のブランチの情報で実行してほしいケースがあるため、上記の方法ではなく別の方法で走るworkflowを制御しています。Workflowsです。parametersでworkflowを実行するかどうかを決定するというものです。実際に使ってみましょう。>>kick_taskをtrueにして設定するかどうかで、run_taskが実行されるか、testが実行されるかを区別できます。https://circleci.com/api/v2/project/gh/kayac/something-repository/pipelineとすれば通常のテストが起動します。parametersをつけることで、テストのときと処理を分けています。まとめ他にも、違うブランチ(コミットハッシュ)だが、テスト済みのブランチとコード部分の内容が一緒だからテストをスキップする、などなど様々なことをやっていますが、長くなってきたのでこのへんで。今後は、柔軟にプロジェクト依存のタスクが書けるのを生かして、本番環境への自動デプロイなどにチャレンジして見ようと思います。最後にもう一度注意です。v2はまだプレビューリリースの段階で、この記事を書いた時点(2019年10月)ではこの情報で使えていますが、予告なしの破壊的変更が入って、そのままでは使えなくなったりする可能性があります。CircleCI上でしか実行できない、環境が作れないようなタスクを実行するのに使うのは避けましょう。壊れたときに泣きを見ます。以上、CircleCIバリバリ使っているよ情報でした。v2で自由自在に業務ワークフローのタスクを実行するTweet関連記事2019-12-22NuxtJS製のWebサービスをECSに移行したはなしSREチームの長田です。CMS+CircleCIで作りました鎌倉は寒いです。みなさんはいかがですか。ソーシャルゲーム事...2019-12-04LobiのCIをJenkinsからCircleCIに移行したはなしSREチームの長田です。ことはじめこんにちは。(1)月別アーカイブ検索スターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。