Boxenを実行すると何が起こるのか

http://boxen.github.com/
https://github.com/boxen/boxen
https://github.com/boxen/our-boxen

スゴイスゴイと言われていて誰も使っていないBoxenだけど、昨日の朝コードを読んでみた。折角なので、boxenコマンドを実行すると何が起こるのかというのを、Rubyのメソッド単位のコールグラフという形で簡単に説明する。

処理の流れ

  1. レポジトリをgit-pullで更新
  2. 環境変数や前回実行時に保存しておいたJSONから設定を読み込み
  3. 前処理
  4. コマンドライン引数に応じて
    4-A. puppet-applyを実行 → 後処理
    4-B. その他便利コマンドを実行 → 終了

Puppetの扱い

librarian-puppetという仕組みが利用されていて、Puppetfile(=Puppet版Gemfile)にPuppetで入れたいものが定義されている。
Puppetfileで https://github.com/boxen/puppet-ruby 等を参照していて、puppet-applyするとこれらが入る。

コールグラフ

表記方法だけども、例えばCLI.runはBoxen::CLI.runを実行しているという意味で、CLI#runはCLIクラスのインスタンスに対しrunメソッドを呼んでいるという意味になる。インデントは、メソッドの内部で更にメソッドが呼ばれているということを表現している。

./our-boxen/script/boxen | レポジトリ(=boxen/our-boxenに該当)を更新 CLI.run | コマンドラインツールから呼ばれるエントリポイント Config.load | 保存しておいたJSONデータからconfigオブジェクトを作る Config#user | 自身のユーザ名を認識 Keychain.new | KeyChain.appにアクセスする Keychain#password | GitHubのパスワードをKeyChainから取得 Config#password= | configオブジェクトに保持 Keychain#token | GitHubのtokenをKeyChainから取得 Config#token= | configオブジェクトに保持 Flags.new | Flagsオブジェクトでコマンドラインオプションを管理 Flags#parse | コマンドライン引数をパース Flags#apply | configオブジェクトにコマンドラインから得た情報をセット Preflight.run | Puppet実行前に実行したいタスクを実行 Preflight.checks | \* Boxen::Preflight以下の名前空間に定義された奴が実行される Preflight::Creds#ok? | \* #ok?がfalseなら#runが呼ばれるという仕組み Preflight::Directories#ok? | \* 例えばHomebrewが入っているかとかを調べたり Preflight::Env#ok? | \* /etc/my.cnfが存在していたら警告を出したりする Preflight::EtcMyCnf#ok? | Preflight::Homebrew#ok? | Preflight::Identity#ok? | Preflight::Os#ok? | Preflight::Rvm#ok? | Config.save | ここで現在の設定をJSONに保存しておく(次回実行時に使う) CLI.new | 実行用オブジェクトの用意 Runner.new | \* Runnerはフック等含めた実行全体に責任を持っている Puppeteer.new | \* Puppeteerは操作に責任を持つ Checkout.new | \* Checkoutはmanifest集の入っているGitレポジトリに責任を持つ Hook.all | \* puppet-apply後に実行したいフックの定義を探す CLI#run | 実行開始 Runner#run | Runner#process | Runner#process\_flags | コマンドラインオプションを見て期待する処理を行う Flags#projects? | --projects : 全てのプロジェクトを一覧する Flags#disable\_services? | --disable-services : Service(=LaunchCtl)を止める Service.list | Boxenで定義されているServiceを探す Service.new | Service#disable | Serviceを止める Flags#enable\_services? | --enable-services : Serviceを動かす Service.list | Service.new | Runner#process\_args | コマンドライン引数を処理する Puppeteer.run | puppet-apply 実行 #Puppeteer#command | 実行用コマンドを用意して実行 #Puppeteer#flags | \* 実行用オプションを良い感じに用意 Puppeteer::Status.new | 終了ステータスのwrapper(puppet-applyは上手く行けば2を返すよ) Runner#report | 終了後のフック処理を行う Runner#hooks | 定義されたフックを探す Hook::GitHubIssue.new | 失敗ならGitHubIssueをopenし、成功すればcloseする Hook::GitHubIssue#run | Hook#perform? | perform?がtrueだった場合、callを実行するという仕組み Hook#call | Hook::Web.new | WebHookを実行する(GitHubのPostReceiveHookみたいな感じ) Hook::Web.run | 任意のURLに実行結果付きでPOSTリクエストしてくれる Hook#perform? | Hook#call | Puppeteer::Status#success? | puppet-applyが成功していれば、 Postflight.run | 実行後用に定義されたタスクを実行する Postflight.checks | Postflight::Active#ok? | Postflight::Env#ok? | (おしまい)