Kanazawa.rbでCIハンズオンをやったよ
または Kanazawa.rb meetup #45 で無双してきたよ!の話。
今回はタイトルを「はじめてのC☆I」にした。要するにテーマは Continuous Integration である。
最初の段階ではそんなに深い意味は考えてなくて、単に meetup #45 はもくもくじゃない回をやるタイミングだったのでどうしようかなと考えた時に、手持ちのネタとして比較的ライトに開催でき、かつハンズオンで時間稼ぎできるんじゃないかという気持ちで考えていた。(実は)
今回はそんな meetup #45 にいたる準備と開催中に感じていたことをつらつらと書いてみる。
CIを体験するだけに集中できる内容に
ハンズオンについてはとにかく「テーマ以外のことを気にしなくて済むように」に集中して考えた。これは以前 Heroku ハンズオンをやって、Windows で Rails の環境を用意するのが大変、Windows で Git + SSH の環境を作るのが大変、PostgreSQL の環境を用意してなかった、など「HerokuというよりはRailsに手こずった」印象が残っていたためである。
ということで
- GitHub アカウントだけ事前に用意してもらう
- こちらで用意したリポジトリを各自が fork
- GitHub アカウントで CircleCI にログインしてリポジトリと紐付ける作業
- CircleCI 側で自動でテストが走るように元のリポジトリで細工しておく
- リポジトリの中身はだいたいみんなが分かるだろう HTML, JS, CSS だけのもの
という設計にした。
※ 当初 45 分程度を予想していたのだが、余裕を見て 1時間に設定したところ見事に 45 分で終わってしまい、最後に急遽自動テストの環境をその場で用意することになるとはまったく予想していなかったが…。
これで「言語の環境がどうとか」「テストコードがどうとか」「テストの書き方がどうとか」全部すっ飛ばせるでしょ、という読み。
用意したのは以下のリポジトリ。
wtnabe/todomvc-vanillajs: forked TodoMVC (VanillaJS version)
内容はなんでもよかったんだけど、あとで中身に興味を持っても意味のあるものにしておきたかったので、いっとき流行った TodoMVC の中の VanillaJS バージョンを用意した。
(実は最初に自分を盛り上げるためにやったのはこのリポジトリを本家の TodoMVC のリポジトリから分離する処理を自動化することだった笑)
あっ、そもそもCIってなんだっけ
しかし、じゃあいざ人前で CI で喋るとぞとなった時に、自分の中にちゃんとした CI 像がないことが分かってきた。なんとなく自動で何かが処理されて、結果の通知が Slack で受け取れて…いやいや待て待て、通知の話は CI の必須要件じゃないよな。そもそも CI を入れて本当に嬉しいことって何?みたいな疑問が次から次へと出てきて、タイムテーブルは埋まるけどほんとにこんなんでいいのか?と不安になってあれこれ調べていた。
そんな時見つけたのが ThoughtWorks の CI に関するページだった。
Continuous Integration | ThoughtWorks
とてもよい内容だったのでこれを使ってイントロを喋った。曰く
チェックインごとに自動化されたビルドによって検証され、チームは問題を早く検出することができるようになる。
これですよ、と。問題は早く発見できた方がその解決も早くなる。とてもシンプルだけど大きなメリットだと自分は感じたので何はともあれ最初にこれを話した。
あとは戦場のリアルな話も、GitHub Flow や Continuous Deployment の話も役者が揃っている。ぼくは安心してピエロになってみんなが手を動かしやすい準備と雰囲気を作るだけ。
GitHub Flowの話からworkflow話が盛り上がった
当日いちばん盛り上がったのは、CI ハンズオンでも CI 話でもなく、実は workflow の話だった。(もちろん CircleCI ハンズオンもそれなりにウケたんですよ!)
GitHub Flow は pull-req を中心において branching をシンプルに、ガンガンリリースしていこうという workflow だ。
- Understanding the GitHub Flow · GitHub Guides
- GitHub Flow (Japanese translation)
- GitHub FlowとCIでモダンWeb開発 // Speaker Deck
これを紹介し、pull-req の画面上で CI の様子が確認でき、master へ merge することで CI サービスから deploy できることを示してからが、がぜん盛り上がった。
- そうは言ってもいきなりリリースは怖い
- staging を用意して自動でそっちにリリースすることもできますよ
- いやいや、やっぱ develop ブランチはあった方がよいのでは
- 開発期間やチームの大きさにもよるかもしれないですね
- 話ずれますけど、レビューのキューが詰まってコンフリクトが頻発しています
- branch の寿命が長すぎる、変更の影響範囲が広すぎる、チーム内のレベル差が大きすぎるなどあるかもしれませんね
- そこだけ別 branch を用意した方がいいかもね
自分が GitHub Flow を採用しようと思った理由
当日は整理できていなかったのでうまく話せなかったが、あとで思い出したので改めて書き起こしてみる。
自分が(ほとんどのコードで)GitHub Flow を採用しているのは何より
制約が単純でツールがよくできているから
である。
それ以前は
に紹介されている、いわゆる Git Flow と呼ばれるものを採用していた。まずは develop ブランチを用意しましょう、ってやつ。
Subversion 時代の感覚(branch の寿命が長い開発)にはマッチしていて個人的には割とよいなと思っていたんだけど、バージョン管理初心者にはいきなり local だ remote だ用語がバンバン増えていく中で branch の意味とか細かく覚えてられないのが正直なところだったらしく、すぐにはリリースできない、あるいは明日リリース予定のものが remote の develop に突っ込まれて hotfix がリリースできなくなるなど、変な混乱が収まるまでしばらく時間を要してしまった。すぐにリリースしない branch が他の branch を block してしまう、ということが直感的に理解できないようだった。
結局、master と develop が一致していないといろいろ面倒になってしまうのであれば、そもそも develop は要らないのでは?と思っていたところ、GitHub Flow を知り、これがぴったりマッチしたのでそれに飛びついた、というのが実情である。決して GitHub Flow はレビューしやすい、とかそこまで積極的によりよいプラクティスを求めていたわけでもない。とにかくシンプルなので変なことが起きにくいのが最大の利点だ。
(これはバグがリリースされにくいという意味ではなく、メンバーの理解度が高くなくても変なことが起きにくいという意味。残念ながら。バグは最悪 rollback すればなんとかなるので。重大さにもよるけど。)
改めてCIとworkflowについて思ったこと
自分の場合は CI と CD ( Continuous Deployment ) は少なくともうちの(比較的小規模な)Web 開発においてはリリース担当者などの blocker 要素を減らしつつある程度の品質を確保するために不可欠な要素になっている。
以前は全員が capistrano を叩けるように教育もしたけど、今はそれも不要になった。こうして極力軽量なプロセスにしないと回らない現実と戦うのが至上命題だからこそ CI と GitHub Flow がマッチしているのだけれど、ここにこだわってやってる現場は(少なくとも近辺には)あまりないかもしれない。参加者の中ではやはりもっと branch の寿命も長いとか、そもそもコードをクラウドに乗せられないので SaaS な CI に頼るのは難しいという人が比較的多かったように思う。
そういう現場はもちろんそれなりに多いだろうし、そこで GitHub Flow を入れないなんてクソですよという気は毛頭ない。ただちょっとこの地域の Web 界隈の、特にフロントエンド方面の人を煽るつもりはあったけどね。
CI と GitHub Flow でリリースサイクルを小さく速く回すためには、当然だけどフロントエンドの人も Git を使ってコミットし、レビューする人が GitHub 上で pull-req を merge するのが最も合理的だ。特に若い人にはそれくらい当たり前にこなせるようになってもらいたいという願いは込めていた。
ヘビーウェイトなプロセスはそれに見合う重さを持つプロダクトに適用してしかるべきであって、ライトに回せるはずの開発をヘビーに回す必然性はないと自分は考えている。それは単なる不勉強だろう。そういう気持ちは込めてある。採用するかしないかは現場次第だし、現場現場でプロセス、ワークフローはカスタマイズが必要だとは思うが、伝統的な人力ベースの重たいワークフローは昨今の多くの現場で割りに合わないのではないか、というのが自分の意見だ。まして制作よりの小さな Web 開発であればなおさらである。
あなたの現場には変な待ちとか無意味なブリッジとか妙に属人化したタスクとか謎の○○職人とか、ありませんか? それって本当に必然性あるの?
コードをクラウドに乗せられない問題と本当のコストと最初の一歩
最後はややポエミーに。
当日の timeline でよく流れていたのはソースコードを GitHub に置けないというものだった。(紹介した SaaS が GitHub にしか対応していないとか、結構多かったからだろう。)GitHub は CI の必須要件じゃないので、紹介したツールにこだわらずに目的を達成することができれば別に GitHub にコードを置く必要はないと思う。とは言え、時間短縮をするためにはよくできたツールに乗っかった方がいいよ、というのは長いこと自分の価値観の中心にあるものだ。
例えば実際に CI を導入しようと思ったら誰がその準備をすることになるだろう。だいたいはエース級の「様々な仕組みをよく理解して適切なコミットを作れる人」がやると思う。その時、エースがどれだけ時間を使えますか? いやいや、そんなところに時間使うなんて無理だし他のやつじゃ CI なんて分かってないし無理だよ、ってことになっちゃわない? それって要は最初から無理って決まってるってことだよね。
最近、変えるための準備に時間が必要なのではなく、変えることに時間が掛かるから変えられないのではないか?ということを時々考えている。そのルールは本当に合っているの? ルールが目的化していない? 大事なことはなんなの? 流行りのツールを取り入れることは目的じゃないけど、だからといってこれまでのルールが本当に理に適っているとは限らないよね。現時点では仕方ない、って判断は普通によくある。過去においてもこの「現時点」はいくつもあったはずだ。だったら見直さなきゃ。
すぐにいっぺんに全部変えるのはそりゃ無理だと思う。でもこの問題に取り組もうとしている人は、問題を適切に分解して解いていくことを、それをソフトウェアで実現する人たちなんだよね? ちょっとでいい、すぐにできることでいい、変えられることから変えていけばいいじゃん。
さーて、次は何をかましてやっかね。