くりにっき

フルスタックキュアエンジニアです

CircleCI orb Perfect Testing

sue445.hatenablog.com

で書いてた

今回作ったorbのインテグレーションテストも頑張ってるのですが、長くなるので別の機会に書こうと思います

の件です。

https://github.com/sue445/circleci-ruby-orbs/blob/1.2.0/.circleci/config.yml の解説をします

注)タイトルは半分釣りです

tl;dr;

  • 何をテストしたいかによって難易度が変わる

orbのテストについて

https://github.com/CircleCI-Public/config-preview-sdk/blob/master/docs/orbs-testing.md より抜粋

You can think of orb testing at 4 levels, in increasing levels of complexity and scope.

  1. Schema Validation - this can be done with a single CLI command and checks if the orb is well-formed YAML and conforms to the orb schema.
  2. Expansion Testing - this can be done by scripting the CircleCI CLI and tests whether the elements of the orb generate the configuration you intended when processing configuration containing those elements.
  3. Runtime Testing - this requires setting up separate tests and running them inside a CircleCI build.
  4. Integration Testing - this is likely only needed for fairly advanced orbs or orbs designed specifically as public, stable interfaces to 3rd-party services. Doing orb integration tests requires a custom build and your own external testing environments for whatever systems you are integration with.

英語は苦手なので 今回は和訳することが目的ではないので具体的にどんなテスト手法があるのかを紹介します

YAMLシンタックスチェック

実際のソース

https://github.com/sue445/circleci-ruby-orbs/blob/1.2.0/.circleci/config.yml#L7-L14

一番お手軽ですが、ymlファイルの検証だけで実際にジョブを動かさないためテストとしては不十分です

ローカルテスト

CircleCI Orbs 入門 | tsub's blog の「Orb のテスト実行」が詳しいです

実際のソース

だいたいの場合はこれでいいのですが、orb実行のために他にファイルが必要な場合( ruby-orbs/bundle-install の場合Gemfile)には不向きです

理由

インテグレーションテスト

https://github.com/CircleCI-Public/artifactory-orb ではスモークテストのためのリポジトリhttps://github.com/eddiewebb/artifactory-orb-test )を作っていました。

それを参考にruby-orbsでも https://github.com/sue445/circleci-ruby-orbs-test のようなリポジトリとCircleCIのプロジェクトを作っています

circleci-ruby-orbs(メインのリポジトリ)とcircleci-ruby-orbs-test(スモークテスト用のリポジトリ)を連携させて下図のようなインテグレーションテストを実現しています。(文字が小さくなってすいません。。。)

f:id:sue445:20181116014650p:plain

仕組み

  1. 【ローカル】トピックブランチをpush
  2. 【circleci-ruby-orbs】sue445/ruby-orbs@dev:${CIRCLE_SHA1} (CIRCLE_SHA1はビルド実行時のgitのリビジョン)でorbをリリース
  3. 【circleci-ruby-orbs】smoke_testジョブでcircleci-ruby-orbs-testのリポジトリをcloneする
  4. 【circleci-ruby-orbs】cloneしたcircleci-ruby-orbs-testで smoke_test/{CIRCLE_SHA1} のようなブランチを作る
  5. 【circleci-ruby-orbs】circleci-ruby-orbs-testが sue445/ruby-orbs@dev:${CIRCLE_SHA1} を使ってビルドするようなコミットを作る
  6. 【circleci-ruby-orbs】circleci-ruby-orbs-testにpush
  7. 【circleci-ruby-orbs-test】circleci-ruby-orbsのCircleCIから下記画像のようなコミットがpushされてくるので、circleci-ruby-ops-test側のCircleCIがビルドを実行する
    • f:id:sue445:20181112013800p:plain
  8. 【circleci-ruby-orbs】circleci-ruby-orbs-testのビルドをポーリングして、ビルドが終了するまで待つ

【おまけ】スモークテスト用のブランチを自動で削除する

circleci-ruby-orbs-testには smoke_test/xxxxx のようなブランチが大量に作られるので、それを定期的に削除するCircleCIのジョブを作ってます

今の設定だと12時間に1回、12時間以上前に作られたブランチを自動で削除するようにしています

【おまけ】orbリリース時に自動でgitのtagをpushしたい

orb-tools/increment を使えばorbの自動リリースは簡単にできるのですが、リポジトリ的にはリリースごとにtagが打たれていた方が後からバージョン間の差分が取りやすいので嬉しいことが多いです。

increment後に自動でgitのtagをpushする方法がないかissueで聞いたところ、

github.com

You could run circleci orb info to get the latest in an additional step in your flow

というレスをもらったのでそれをCIで実装したのが下記です

circleci orb info をたたいてLatestで返ってきたバージョンのtagを作ってpushしています

*1

*1:余談ですがここだけrubyを使っているのはシェルで標準出力を正規表現のparseするのが難しかったためです