Danger のプラグインの構造

プルリクエストに関する定形作業を自動化するツール Danger のプラグインを書く機会があったので、プラグインの構造について簡単にメモ。v5.13.0 を参照している。

プラグインクラスの概要

プラグインDanger モジュールの直下に Danger::Plugin を継承して定義する。クラス名は慣習として DangerfileFooBar となる。

module Danger
  class DangerfileFooBar < Plugin
    def greet(msg) # used in Dangerfile
      ...

Plugin.inherited によって、このクラス自身がプラグインの1つとして登録される。

あとはプラグインが提供したい機能を public メソッドとして定義すればいい。

Dangerfile の実行環境

Dangerfile のコードは Danger::Dangerfile インスタンスinstance_eval として実行される。

プラグインインスタンスは初期化時に Dangerfile インスタンスの read only なインスタンス変数として登録される。この時、各プラグインクラスの特異メソッド instance_nameインスタンス変数名として使われる。(後述)

Plugin から継承する重要なメソッド

Plugin#initialize

上述の Danger::Dangerfile を受け取ってインスタンス変数 @dangerfile にセットする。

インスタンス作成は Danger 内部で行われるため、プラグイン作成者はこの挙動を変えてはいけない。オーバーライドする場合も引数は変えずに必ず super を呼び出すこと。

def initialize(dangerfile)
  super
  # Your code
end

Plugin.instance_name

Dangerfile 内でプラグインを参照するための名前を宣言するメソッド。当然だが毎回同じ値を返すこと。

デフォルトではクラス名から Dangerfile を取り除き、スネークケースにした文字列を返すようになっている。例えば DangerfileFooBar.instance_name"foo_bar" を返すので、Dangerfile 内で foo_bar.greet("hello") のように書ける。

Plugin#method_missing

method_missing では initialize で保存した @dangerfile にフォールバックする。

これはとても重要で、これのおかげであるプラグインから他のプラグイン(例: github)を参照することができる。


とりあえずここまで調べて気が済んだので一旦ここまで。また何かあったら書き足すかも。

Dangerfile 内の dangergithub も実態がプラグインなので、勉強しやすくていい。