2017年10月23日月曜日

Jenkins の API を Ruby から操作してみた

概要

前回 Jenkins の API を curl で試してみました
今回は Ruby から実行してみました
専用の SDK があるようなのでそれを使ってみます

環境

  • macOS X 10.12.6
  • Jenkins 2.60.3
  • Ruby 2.4.1p111

ライブラリインストール

  • bundle init
  • vim Gemfile
gem "jenkins_api_client"
  • bundle install

サンプルコード集

いろいろと試してみます

ジョブの一覧の取得

require 'jenkins_api_client'

client = JenkinsApi::Client.new(
  :server_ip => 'localhost',
  :username => 'root',
  :password => 'ab4eda0916f1a599e8132bc2bf8a3cec'
)
jobs = client.job.list_all
puts jobs.class # -> Array
jobs.each { |job|
  puts job
}

jobs = client.job.list("^hoge")
jobs.each { |job|
  puts job
}

list メソッドを使うことで正規表現でジョブを絞込することができます

ジョブをビルド

require 'jenkins_api_client'

client = JenkinsApi::Client.new(
  :server_ip => 'localhost',
  :username => 'root',
  :password => 'ab4eda0916f1a599e8132bc2bf8a3cec'
)
jobs = client.job.list_all
jobs.each { |job|
  code = client.job.build(job)
  # build_id = client.job.build(job, params = {}, opts = {"build_start_timeout" => 100})
}

client.job.build でジョブ名を文字列で指定するだけです
上記サンプルは全ジョブを実行しているので必要なジョブだけ絞り込んで実行したほうが良いでしょう

また build_start_timeout を指定してビルドを実行するとレスコンスコードではなくビルドの番号が返ってきます
なのでビルド番号がほしい場合は下の方法で呼ぶ必要があります

コンソール情報を取得する

ビルド番号からコンソールの情報を取得します
text or html が選択できます

require 'jenkins_api_client'

client = JenkinsApi::Client.new(
  :server_ip => 'localhost',
  :username => 'root',
  :password => 'ab4eda0916f1a599e8132bc2bf8a3cec'
)

job = 'hoge'
build_id = client.job.build(job, params = {}, opts = {"build_start_timeout" => 100})
ret = client.job.get_console_output(job, build_num = build_id, start = 0, mode = 'text')
puts ret['output']
puts ret['size']
puts ret['more']

client.job.get_console_output を使います
ビルド番号が必須なので、ジョブを実行した際にビルド番号を取得するようにします
(ビルド番号がない場合は最新のビルドから取得しても良いような気がしますが)

ジョブを連結する

いわゆる「他のプロジェクトのビルド」を設定することができます

require 'jenkins_api_client'

client = JenkinsApi::Client.new(
  :server_ip => 'localhost',
  :username => 'root',
  :password => 'ab4eda0916f1a599e8132bc2bf8a3cec'
)
jobs = client.job.list_all
target_jobs = client.job.chain(jobs, 'success', ["all"]) # 安定している場合のみ起動にチェックが入る
# target_jobs = client.job.chain(jobs, 'failure', ["all"]) # 失敗した場合でも起動にチェックが入る
# target_jobs = client.job.chain(jobs, 'unstable', ["all"]) # 不安定でも起動にチェックが入る

client.job.build(target_jobs[0])

第二引数を変更することで次のビルドに進む条件を変更できます
第三引数は chain する対象のジョブを絞り込むことができます
例えば failure を指定すると失敗したジョブだけを chain することができます
これを使えば失敗したジョブだけをつないでビルドすることができるようになります
ちなみに chain コール後はジョブが連結されているので each で回してビルドするのではなく先頭だけ実行すればすべてのジョブが実行されます

ジョブを作成する

XMl の生成が必要です
Helper クラスが合ったのそれを使います

require 'jenkins_api_client'

client = JenkinsApi::Client.new(
  :server_ip => 'localhost',
  :username => 'root',
  :password => 'ab4eda0916f1a599e8132bc2bf8a3cec'
)

def create_job_xml
  builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') { |xml|
    xml.project {
      xml.actions
      xml.description
      xml.keepDependencies "false"
      xml.properties
      xml.scm(:class => "hudson.scm.NullSCM")
      xml.canRoam "true"
      xml.disabled "false"
      xml.blockBuildWhenDownstreamBuilding "false"
      xml.blockBuildWhenUpstreamBuilding "false"
      xml.triggers.vector
      xml.concurrentBuild "false"
      xml.builders {
        xml.send("hudson.tasks.Shell") {
          xml.command "\necho 'going to take a nice nap'\nsleep 15\necho 'took a nice nap'"
        }
      }
      xml.publishers
      xml.buildWrappers
    }
  }
  builder.to_xml
end

puts client.job.create('job_name', create_job_xml)

create_job_xml の内容を変更すればジョブの内容を変更することができます
curl でファイルを操作してジョブを作成するよりかはプログラム内で XML を扱ったほうが若干ジョブの作成しやすさは上かなと思います

最後に

Ruby から Jenkins の API をコールしてみました

ビルドの実行からジョブの作成まで基本的なことはすべてできると思います
また、今回は触れませんでしたがプラグイン関連の処理もできるので Jenkins 自体の設定もコードから操作することができるかもしれません (未確認)

あとは Sinatra や Rails などの Web フレームワークと組み合わせれば独自 UI なども簡単にできると思います

参考サイト

1 件のコメント:

  1. ビルドの詳細結果を取得する方法は以下の通りです

    require 'jenkins_api_client'

    client = JenkinsApi::Client.new(
    :server_ip => 'localhost',
    :username => 'root',
    :password => 'pass'
    )

    ret = client.job.get_build_details('job_name', 3)
    pus ret['result']

    返信削除