非プロダクト エンジニアだけど CircleCI でプロダクト エンジニアみたいなことをしている話

この記事は [CircleCI Advent Calendar 2020](https://qiita.com/advent-calendar/2020/circleci) 22 日目の記事です.
本日は makotom こと CircleCI の DevOps Customer Engineer 水上がお届けします.

本当はこの記事で私がここ 2 か月ほど取り組んでいる新しい Windows ビルドの話をしようと思っていたのですが (なのでタイトルも伏せていたのですが), あいにく諸々が間に合わず, マージ・リリースの前に共同作業者であるレビュアーがクリスマス休暇に入ってしまったので, 急遽突貫工事で別の内容をお届けします. いかついサンプル コードとかファンシーな画像とかが全くなく, ただただエモだけで語っているのにはそういう背景があります. :bow:

# はじめに

さて, 私は現在 CircleCI で DevOps Customer Engineer として活動しています. このロールは, 主にすでに CircleCI をお使いのお客様を技術的な観点からご支援するのが主な役目です. つまり, CircleCI の製品開発には基本的にはコミットしません. 組織的にも, Customer Engineering (以下 CE) というお客様との対話に重きを置いた別組織になっており, 製品開発に注力を置く Engineering の組織とは別組織になっています.

しかし, 実際に私は CircleCI のコード ベースにコミットする機会が少なからずあります. 上述にもあった Windows ビルドの関連の開発・修正のほか, CircleCI server における parallelism の機能のバグ修正を書いたこともありましたし, Docker Hub の API 制限が話題になっていたころには Docker の認証情報のエンコーディングに生じていた問題の修正を書いた, なんてこともありました.

**CircleCI のどのような環境が, 非プロダクト エンジニアでもプロダクト コードにコミットできる状況を可能にしているのか?** CE が必要なソースコードへの read 権限を持っているという状況もあるにはあるのですが, それ以外にもいくつか大事な要素があると私は思っています.

# CircleCI のコードは CircleCI で CI/CD をしている

ある意味当たり前ですが, CircleCI の Git リポジトリはほぼすべて CircleCI で CI/CD をしています. エンジニア向けのメモ置き場も CircleCI で CI/CD をしています. 私が今まで見た CircleCI のリポジトリで CircleCI を使っていないリポジトリはひとつも思い当たりません.

これは, 実は**コード コミットの障壁が極めて低い**ことを意味しています. よいアイディアを持っているあなたは, 元のコードを読んで理解できて, それを書き換えるだけのコーディング能力を持っていて, あとはリポジトリへの write 権限さえあれば, すぐにコミットできる. 開発環境とかビルドとかテストとかリリース・デプロイのこととかはいったんは CI/CD に任せてしまえばよくて, とにかくメインのコード ベースに加える変更のことだけを考えればよい. 実際, 私の開発環境の WSL には, 基本的には, Git と, 多少のカスタマイズが施された VSCode と, ほぼ空の `.vimrc` で動いている Vim しか入っていなくて, 時々検証用に Docker がフルに使える環境を用意するくらいです. そんな質素な環境でも, ほとんどのコード コミットを困ることなくすることができます. 正直な話, デプロイやリリースのためのオペレーションのことなんてほとんど考えたことがなくて, **push したらあとは勝手に CI/CD がよしなにやってくれる前提でコードを書きます**. よっぽど, `push` する瞬間に write 権限を持っていないことに気づくほうが深刻な問題です (しかも CircleCI の場合アクセス制御管理者は US にいるので日本・アジア地域にいると結構悲しい思いをしますw 余談ですが).

CircleCI のビジョンでもある "世界中のだれもが, 思い浮かんだアイデアをすぐにソフトウェアとして配信できるように支援する" (Make it as easy as possible to go from idea to delivery) ことを考えるとき, 一般には単にメインの開発者が携わる DevOps のサイクルを高速化することを考えがちですが, 真に, 世界中のだれもが簡単にコミッターになれるようにし, 思い浮かんだアイディアをエンド ユーザーに届けられるようにすることもまた, CI/CD の大事な要素といえそうです. 複雑化する現代社会において, あまねくアイディアを汲み上げられる仕組みは, チームのサステナビリティにも影響します. 既存のエンジニアのための CI/CD だけでなく, **今後新たに入ってくるであろうエンジニアや, コアなエンジニアではないけど熱意はあるコミッターのことも考えて実践する CI/CD** という視点を持つと, CI/CD の見方がすごく変わると思います.

# ラッパーが開発を加速する

CircleCI の多くのコードには便利なラッパーが用意されています. しかも多段構成になっていて, たとえばサービスのデプロイ用には, 各リポジトリが共通で使えるデプロイ ツールがあって, さらにその上で動く各リポジトリごとのビルドやテスト, デプロイのためのラッパーが用意されています. ラッパーがあることで, 手元でのテストやビルドが極めて手軽に行えます. 先ほど述べたように, 私の開発環境は至ってシンプルな構成になっていますが, **ラッパーがあることでほとんど苦労することなく手元でのビルドやテストが行える**ようになっています.

"そんなんドキュメントに書けばええやないか" という声が聞こえてきそうですが, **手順をドキュメントに書くというのではダメなんです**. ドキュメントに書かれている各リポジトリ固有のお作法を読み込んでいる時間は思った以上に非生産的で, そこにかけている時間をアイディアの結晶化に費やせるようになると大きな差になってきます. そしてこれは, CI/CD の実装にも直結してきます. つまり, **ラッパーの整備にきちんと時間投資し, CircleCI の config.yml をシンプルにし, CI/CD の実装や検証, ジョブ実行時のトラブルにより持っていかれる時間を圧縮する**ことで, 本来のアイディアの実装にかけられる時間に大きな差が出てきます.

これは私がよくセミナー等でいうことなのですが, 一足でそのような贅沢でお手軽な環境を作り上げることは不可能です. 一個ずつ, カイゼンしていくのが近道だと思います. そして, おそらく**そのツールの恩恵をうけるひとすべてがツールのカイゼンに携われるようにすることが大事**なんだと思います. 必要は発明の母, ですから. (実際, 先ほどの CircleCI のデプロイ ツールは, コアである SRE に限らず複数のチームのエンジニアがコミットしています.)

# とにかくテストを書くことが称賛される

これもあたりまえといえばあたりまえなのですが, すごくテストを書くことが推奨されます. しかも, 私のようなコアではないゆるふわコミッターからするとびっくりするくらい要求が高かったりします. 幸いにしてエンジニアリング チームのみなさんが優しく, ペアプロでテストの作成に協力してくれたりしますが, それがなかったら心が折れてしまうかもしれないくらい要求が高いこともあります. 単にコード カバレッジを広げるだけでなく, どれくらいの粒度でテストをするかもよく議論になります.

これだけ聞くと非情なようにも聞こえますが, 実は裏には合理的な理由があるといえます.

そもそもコード変更をレビューするとき, レビュアーは以下のようなことを考えるわけです:

1. そのコードが成し遂げようとすることは何か? コードの背景にある事情やコードが解こうとする問題の定義.
2. そのコードは何をすることで定義された問題を解決しようとするのか? コードの目的の定義.
3. そのコードは具体的にどのような解法やアルゴリズムで目的を達成するのか?
4. 作者の考えた解法やアルゴリズムは目的に対して適切か? 穴はないか? 代替案はないのか? なぜ代替案を採用しなかったのか?
5. そのコードは作者が考えた解法やアルゴリズムを正しく適切に表現しているか? なぜそのような表現にしたのか? 代替案はないのか?
6. そのコードは既存のアセットに加えるのにふさわしいか? 新しいコードの目的は既存のコードの目的と相反しないか? 新しいコードは既存のアセットと親和性の高い記述になっているか?

これらを検討するためには, **レビュアーはそのコードを書いた作者の意図を非常に正確に理解する必要があります**. ここで国語の試験よろしく読み手が筆者の考えを最大限慮ることを期待していると, レビュアーの負担が一方的に大きくなっていき, 結果的にレビュアーが適切な判断を下せない状況に陥り, 作者のせっかくのアイディアを取り込めなくなる原因にもなります. ところが, テスト コードがあれば, 作者の意図をよりよく表現してくれます. 特に, テスト コードは, コードの目的を具体例でもって表現し, 解法およびアルゴリズムの記述の正確さを保証してくれます. しかも, テスト コードが削除されてしまわない限り, ずっとそれを主張しつづけてくれます.

つまり, **あなたのすてきなアイディアをいまそして未来にわたって正確に表現しつづけるために, 質の高いテスト コードが必要**なのです. そして, そのテストコードを **CI/CD で継続的に繰り返し実行し, あなたのアイディアが毀損されていないのを検証し続けることが大事**なのです. CircleCI の社内でこんな頭でっかちなことを常に考えているひとはさすがにいないと思いますが, テストコードの存在が, レビューを円滑なものにし, より多くのアイディアを持続的に取り込めるようにしていることは多くのエンジニアの共通の実感としてあるように思います.

余談ですが, 作者の意図を正確に表現するのに有効な箇所はあと 2 箇所あります. ひとつはレビュー リクエストの説明文で, もうひとつはコード中のコメントです. とくにコメントは, そのコードの目的や解法をより高い視点でコードのすぐそばで表現するのにすごく役立ちます. 実は私, 10 年くらい前はコメントを一切書かない派だったのですが, 自身のコードの意図の表現の重要性に気づき, 積極的にコメントを書く派に転身した経緯があったりします.

# Open & Transparent

最後はここにつきるでしょう - 節度を持ってオープンで透明性のある組織が, ひろくアイディアを汲み上げる習慣を作ります. 前述しましたが, 多様なアイディアを可能な限り汲み上げる姿勢は, 複雑さの増す現代社会において組織の存続にかかわります.

たとえば, そもそもコードを見られないひとには, 今何が起きていて何が可能で何が不可能かの判断もつかないでしょう. コードの read が許可されている状況でも, コア メンバー以外からの PR を一切受け付けない文化にあれば, 外からアイディアをコミットしようとする発想も出てきません. アイディアの安全な実装と投入に対して周囲が協力的でなければ, アイディア メーカーの心はどんどん折れていきます.

"そんなのもはや CircleCI 関係ないんちゃう?" と言われそうですが, あながちそうでもありません. 確かに, CircleCI 社内でも, アイディアを Google Docs にペラを書いて投下する, といったことも結構しますし, このレベルの話には CI/CD と直接関係ないこともたくさんあります. しかし, コーディングという実際のアイディアの実装には Google Docs 以外のツールをたくさん使いますし, なにしろ**適切なツールがないことには理想のシステム・文化・習慣は構築できません**. 言い換えれば, **CircleCI のような, 持ち込まれたアイディアがどのようなもので, どのように作用するのかを, 誰でも簡単に試して検証できるツールを使うことで, ようやくアイディアを広く汲み上げる文化が発展していく**といえるのではないでしょうか.

# おわりに

以上, 私が考える, "CircleCI のどのような環境が, 非プロダクト エンジニアでもプロダクト コードにコミットできる状況を可能にしているのか?" を書いてみました. 予想以上にエモだけの文章になってしまった...... お見苦しくてスミマセン.

そして, ここまで読んで CircleCI という会社に興味をもった皆さん, [弊社は絶賛採用中](https://boards.greenhouse.io/circleci)ですので "Qiita のこの記事を読んだ" って一言添えて応募していただけると私が喜びます. (ぉぃ

明日は @sho7650 さんの担当です. お楽しみに!