LoginSignup
9
7

More than 5 years have passed since last update.

Jenkinsで一定サイクルに終わらなかったジョブを検出する

Last updated at Posted at 2012-07-04

一定サイクルで実行するジョブを作成したとき、
ジョブの実行がサイクルの時間内に収まらなかった場合は、
次の実行がビルドキューに追加される。(※)

(※) ジョブの設定で「可能であれば並行してビルド」を「OFF」にしている場合。
「ON」にしていると、Jenkins全体のジョブ並行実行数の制限に達していない限り、
キューには追加されず、即座に実行されてしまう。)

これは、ジョブの実行時間に対して、
指定されたサイクルが短すぎるということなので、
サイクルを長くするなり、ジョブの実行時間をチューニングするなりすべきで、
一般的には良くない状態である。はず。

ではどうすれば、サイクルに収まらず、
次の実行がビルドキューに追加されてしまったジョブを、
プログラマティックに検出できるかという話。

Jenkinsには「リモートアクセスAPI」という便利なものが用意されていて、

https://wiki.jenkins-ci.org/display/JA/Remote+access+API)

以下のURLを呼び出すことで、ビルドキューの状態がjsonで取得できる。
http://[host]:[port]/queue/api/json

json
{
  items: [
    {
      actions: [
        {
          causes: [
            {
              shortDescription: "ユーザーkei2100が実行",
              userId: "kei2100",
              userName: "kei2100"
            }
          ]
        }
      ],
      blocked: true,
      buildable: false,
      id: 564,
      params: "",
      stuck: false,
      task: {
        name: "test_job",
        url: "http://[host]:[port]/job/test_job/",
        color: "blue_anime"
      },
      why: "ビルド #20 は既に実行中です。 (予定時間:21 秒)",
      buildableStartMilliseconds: 1340090312065
    }
  ]
}

このjsonで、「blocked: true」になっているものが「次の実行がビルドキューに追加されている」状態にあたるので、

参考 : http://javadoc.jenkins-ci.org/hudson/model/Queue.Item.html

これを検出してあげれば良い。

例えば以下のような感じ。

#!/usr/bin/env ruby

require 'json'
require 'net/http'
require 'optparse'

def get_job_infos_with_json(host, port) 
  uri = '/queue/api/json'

  http = Net::HTTP.new(host, port) 
  http.open_timeout = 30
  http.read_timeout = 30

  begin
    http.start do 
      response = http.get(uri)
      if response.instance_of? Net::HTTPOK 
        return response.body
      else
        raise "http://#{host}:#{port}#{uri} returns #{response.code}"
      end
    end
  rescue => e
    raise "http://#{host}:#{port}#{uri} throws exception.\n caused by #{e.message}"
  end
end

def duplicate_job_start?(job_info)
  if job_info['blocked'] 
    return true
  else
    return false
  end
end

host = nil
port = nil 

# コマンドラインパラメータの取得
opt = OptionParser.new do | opt |
  opt.on('-h HOST') {| val | host = val} 
  opt.on('-p PORT') {| val | port = val} 

  opt.parse(ARGV)
end

if (!host || !port)
  puts opt.help
  exit 1
end

# Jenkisのジョブキュー情報を取得
job_infos_json = get_job_infos_with_json(host, port)  
job_infos = JSON.parse(job_infos_json)

# 前回の実行が終わっていないジョブを検出
duplicate_jobs = []

job_infos['items'].each do | job_info |
  if duplicate_job_start?(job_info) 
    duplicate_jobs << job_info
  end
end

if duplicate_jobs.size > 0
  puts "Previous job has not finished yet..."
  duplicate_jobs.each do | job_info |
    puts "job name : #{job_info['task']['name']}"
  end
  exit 1
else
  exit 0
end
9
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7