ラベル groovy の投稿を表示しています。 すべての投稿を表示
ラベル groovy の投稿を表示しています。 すべての投稿を表示

2017年7月18日火曜日

[Jenkins] Pipeline Script からプラグイン機能を呼び出す

ブログズミ: [Jenkins] Groovy で IRC Plugin を使い倒す
以前、Groovy post build プラグインから IRC Plugin の機能を呼び出して、任意のメッセージを飛ばすことをやりましたが、これを Jenkinsfile に記述します。

やり方は単純
Jenkinsfile にそのまま書くだけです。

以前、Groovy Label Assignment plugin 向けに書いた groovy がこちら。
def jenkins = hudson.model.Hudson.instance
def irc_channel="#kiwiirc-iutest"
def p = jenkins.getPlugin("ircbot")
if( p == null ) {
  println("require IRC Plugin")
  return
}
def c = p.imPlugin.provider.currentConnection()
if( c == null ) {
  println("IRC connection not found. please set to IRC configuration")
  return
}
c.send(irc_channel, "label assignment")
return

これを、すこし汎用的にして Jenkins ファイルに追加します。

def send_irc(channel, message)
{
    def jenkins = hudson.model.Hudson.instance
    def p = jenkins.getPlugin("ircbot")
    if( p == null ) {
      println("require IRC Plugin")
      return
    }
    def c = p.imPlugin.provider.currentConnection()
    if( c == null ) {
      println("IRC connection not found. please set to IRC configuration")
      return
    }
    c.send(channel, message)
    return
}

で、あとはお好きなタイミングで呼び出すだけです。
stage('irc-send') {
        send_irc('#TEST', 'ビルドに成功したよ!')
    }


簡単ですね^^

2016年5月23日月曜日

[Jenkins] Groovy で IRC Plugin を使い倒す

IRC 使ってますか?
Slack とか Chatwork とか HipChat ですか?

IRC 使ってないし関係ないか~と思った「あなた」、ちょっと待ってください。

今回は「"Groovy" で IRC Plugin を使い倒す」というわけで、
Groovy 使ってプラグインにアクセスしてごにょごにょしようという話です。
なので、今回は IRC Plugin で説明をしますが、これに限った話ではなく、他のプラグインにも応用できます。

ちなみに、Groovy のことをよく知らなくても大丈夫です。見よう見まねでなんとかなります。(私がそうですから)

IRC Plugin でできること
まずは、IRC Plugin がどういったものか紹介をします。

IRC Plugin では以下のことができます。
  • コマンド
  • ビルド後の処理で通知(ビルド前も可)

コマンド機能は今回は話のメインではないので軽く説明。
jenkins-bot build job now
のようにするとビルドを開始するなど、IRC から Jenkins を操作する機能です。

もう1つが、ビルド後の処理で IRC に通知する機能です。

ビルド後の処理に追加しますが、「高度な設定...」 の 「Notify on build start」を有効にするとビルド開始時にも通知してくれます。

こんな感じに通知が来ます。

IRC Plugin でできないこと
  • 任意のメッセージ送信
  • ビルド後/ビルド前以外での通知

ビルド後/ビルド前の処理で送れる内容はある程度決まっており、任意のメッセージ・フォーマットで送れないのでちょっと不便です。(出力の順番を変えたいとか、定期的に任意のメッセージを通知をしたいとか)

Groovy で潜在能力を引き出す
プラグインで提供されている機能以上の力を引き出すことができるのが、Groovy です。
Groovy から Jenkins の機能にアクセスする方法はこれまでも紹介してきましたが、今回はプラグイン機能にアクセスします。そして、任意のメッセージを出力できるようにしたいと思います。

プラグインにアクセスするには、「getPlugin」を使います。今回は IRC Plugin なので
「hudson.model.Hudson.instance.getPlugin("ircbot")」のようにアクセスします。
getPlugin にはプラグイン ID を指定します。プラグイン ID はプラグインの Wiki に記載されています。

プラグインが get できたら、そこからさらにプラグインの機能にアクセスをしていきます。
IRC PluginSource Code(Github) を開くと実装が見れるので、これを参考に機能にアクセスしていきます。
(他のプラグインでもだいたいソースコード見れます。)

以下が、Jenkins のシステム設定で設定した IRC コネクションを使って、任意のメッセージを送るスクリプトです。
def jenkins = hudson.model.Hudson.instance
def irc_channel="#kiwiirc-iutest"
def p = jenkins.getPlugin("ircbot")
if( p == null ) {
  println("require IRC Plugin")
  return
}
def c = p.imPlugin.provider.currentConnection()
if( c == null ) {
  println("IRC connection not found. please set to IRC configuration")
  return
}
c.send(irc_channel, "label assignment")
return
細かい説明は省きます。
(何をしているか知りたい人は、プラグインのソースコードと照らし合わせて確認してください。)

最後にこのスクリプトを各種 Groovy の設定にコピーすれば設定完了です。
以下は Groovy Label Assignment plugin の設定をしているところです。


そして、実際に実行したところがこちら。


皆さんも、是非お試し下さい。

各種タイミングでの Groovy 利用を可能にするプラグイン
最後に Groovy が使えるようになるプラグインを少し紹介して終わりたいと思います。
ではでは。

プラグインタイミング設定
Groovy Pluginビルドジョブ
Groovy Postbuild Pluginビルド後ジョブ
Groovy Label Assignment plugin実行ノード決定ジョブ
Matrix Groovy Execution Strategy Pluginマトリックス生成ジョブ
Global Post Script Pluginビルド後グローバル
Scriptler Pluginビルドグローバル
Groovy Events Listener Plugin各種イベントグローバル
etc...

2016年3月28日月曜日

[Jenkins] 成果物(画像)を貼り付ける

今回は成果物に保存した画像ファイルをビルドページのトップに貼り付ける方法を紹介します。




なぜ、こんなことが必要かと言うと、
成果物ファイルを確認しようと思った時にリンクを一度クリックする必要があり、これが面倒くささに繋がります。
この一手間をなくすことで、より快適な環境になり、利用者の利点になります。

メリットの話はここまでにして、やり方を紹介します。

Groovy Postbuild Plugin
みんな大好き Groovy Postbuild Plugin !!
今回も Groovy を使用します。
ポイントは2つ、成果物パスの取得とサマリーへの img タグ挿入です。
実際のコードを見ていきましょう。

static createArtifactImageSummary(manager)
{
  def a = manager.build.getArtifacts()
  a.each {
    def path = it.relativePath
    if( path ==~ /.*\.(png|jpeg|jpg|bmp)/ ) {
      manager.listener.logger.println(path)
      manager.createSummary("clipboard.gif").appendText("<img src=\"artifact/$path\"><br />$path", false, false, false, "red")
    }
  }
}
Github

成果物のパスは、manager.build.getArtifacts() で取得した成果物リストを巡回して、relativePath から相対パスが取得できます。画像ファイルであれば manager.createSummary でサマリーを作成。さらに appendText で img タグを挿入しています。

これだけです。
これだけですが、このちょっとしたひと手間で閲覧者の面倒くささが取り除けます。
今回は画像ファイルでしたが、テキストなどの成果物でも応用ができると思います。
ぜひ試してみてください。

以上。


2016年3月23日水曜日

Jenkins でズンドコキヨシ

最近流行(ちょっと出遅れてますが…)のズンドコキヨシを Jenkins でやってみました。
ズンドコキヨシまとめ - Qiita

どうやってやったのか?ですが、ジョブでズンドコキヨシを表現してみました。
まずは結果をご覧ください。(小さいのでクリックしてみてください)

www.oyama-dansen.co.jp

構成
ジョブは以下の4つ。

最初の起点となる「きよしのズンドコ節」ジョブと、「ズン」、「ドコ」、「キヨシ」ジョブの4つのジョブが以下のようにつながっています。

ランダムに下流ジョブを実行
「ズン」と「ドコ」をランダムに実行させるために、
Groovy Postbuild PluginFlexible Publish Plugin を使用しました。



Groovy Postbuild でランダムにビルドステータスを「不安定」か「失敗」に変更しています。
(コードは後述。 Gist にも公開してます。)
Flexible Publish で「不安定」の場合は、「ズン」。「失敗」の場合は、「ドコ」を実行するように設定しています。


ズンドコキヨシ
メインのズンドコ関数ですが、まず判定は Groovy Postbuild で行っています。
判定コード:
import hudson.model.Cause.UpstreamCause
static setNext(manager)
{
  def r = Math.floor( Math.random() * 2 ) as int
  manager.listener.logger.println r
  if( r ) {
    manager.buildUnstable()
  } else {
    manager.buildFailure()
  }
}

static checkZUN(manager, cause, count)
{
  def causes = cause.getUpstreamCauses()
  def name = cause.getUpstreamProject()
  manager.listener.logger.println name
  if( name == "ZUN" ) {
      count += 1
      if( count == 4 ) {
        return true
      }
  } else {
    return false
  }
  cause = null
  causes.each {
    if( it instanceof UpstreamCause ) {
      cause = it
      return
    }
  }
  return checkZUN(manager, cause, count)
}

static check(manager)
{
  def name = manager.build.getProject().getName()
  manager.listener.logger.println name
  if( name == "DOKO" ) {
    def cause = manager.build.getCause(UpstreamCause.class)
    if( checkZUN(manager, cause, 0) ) {
      return true
    }
  }
  setNext(manager)
  return false
}

ズンドコの判定は「ドコ」ジョブで行います。

check(checkZUN) 関数では、UpstreamCause を辿って上流ジョブのジョブ名を取得していきます。
取得したジョブ名を使って、「ズン」、「ズン」「ズン」、「ズン」「ドコ」となったらビルドを「成功」にします。
ならなかった場合は、次のジョブにつなげるためにまたランダムでステータス変更をします。

ズンドコが成立すると「成功」ステータスになるので、あとは「成功」ステータスのときのトリガーを追加すれば完成です。


画像
最後にお遊びで付けた画像ですが、これは createSummary, appendText で img タグを挿入しています。
画像ファイルはワークスペースに配置すれば、ビルドページからワークスペースへの相対パスで参照できます。
具体的にはこんな感じに設定しています。

manager.createSummary("clipboard.gif").appendText("<img src=\"../ws/KIYOSHI.jpg\">
キ・ヨ・シ!!", false, false, false, "red")

来週はこれをもう少しカスタマイズして、成果物の画像ファイルを貼り付ける方法を紹介します。

最後に
今回は Pipeline Plugin (旧Workflow Plugin) を使いませんでした。(自分がほとんど使ってないので)
Jenkinsでビルドのパイプラインを作るぞー!(2016年2月版) - Mitsuyuki.Shiiba
あとはもう少し見た目をよくしたいなと思いましたが、時間がないのでここまでにしました。
誰かこの辺もチャレンジしてくれたらな~(私が大変喜びます)と言って締めたいと思います。では~

2016年3月7日月曜日

[Jenkins] NodeLabel Parameter Plugin + Groovy Label Assignment plugin でノードをパラメータにしつつ別ノードで実行する

NodeLabel Parameter Plugin は「ブログズミ: [Jenkins] ノードやラベルを指定して実行する」で紹介をしました。
Groovy Label Assignment plugin は「ブログズミ: [Jenkins] 同じノードで繰り返し実行されないようにする方法」で紹介をしました。

この2つを組み合わせることで、ノードをパラメータとしつつ、実行ノードは別にすることにできます。

どういうことかと言うと、
「NodeLabel Parameter Plugin」はノードをパラメータにできます。
右のようなに、ノードがリストで選べるので非常に便利です。

そして、このパラメータで選ばれたノードは、実行ノードとして利用されます。通常利用の範囲ではこの動作で問題ないと思うのですが、たまーに実行ノードを別にしたいことがあります。
(私の場合、メンテナンス系のジョブで必要になりました。)


そこで、「Groovy Label Assignment plugin」の出番です。
設定
ジョブの設定で「Groovy スクリプトで実行するノードを制限」を以下のようにします。
def label = currentJob.assignedLabel
return label
「実行するノードを制限」に設定を返すようにしているだけです。
これで「NodeLabel Parameter Plugin」に上書きされるラベル式を、「実行するノードを制限」の設定に戻すことができます。



実行
実際に実行するとこんな感じです。

slave3 をパラメータとして実行。


master ラベルが割当られて、master で実行されます。

まとめ
ノード選択でも Groovy の力を借りると幅が広がります。
Groovy Label Assignment plugin をぜひお試しください。

2015年10月19日月曜日

[Jenkins] 同じノードで繰り返し実行されないようにする方法

Workflow Plugin を使ったらこれについても制御できるかもしれないですが、
まだ Workflow Plugin 使えてないので、別の方法を紹介します。

Groovy Label Assignment plugin
Groovy Label Assignment plugin を使います。
このプラグインを使うと Groovy を使って、
動的に実行ラベルを設定することができます。

ジョブの設定ページを開くと、
「Groovy スクリプトで実行するノードを制限」があるので有効にし、スクリプトを入力します。
文字列を返すとそれが新しいラベル式になります。なにも返さなかった場合は、もとのラベル式が使われます。


前回実行ノードを除外するときは、こんな感じに書きます。
def label = currentJob.assignedLabel
def last = currentJob.getLastBuild()
if( last == null ) return
def node = last.getBuiltOnStr()
if( node == null || node == "" ) node = "master"
if( node )
  return "${label}&&!" + node 
実行しようとしているジョブは currentJob にバインドされているので、そこからラベルと前回実行時のノード名を取得して新しいラベルを生成します。


さまざまなスレーブでまんべんなく実行したい場合はマトリックスを組むのが良いですが、この方法も覚えておくと便利かもしれません。

2015年7月13日月曜日

[Jenkins] ビルドが失敗したときにスレーブをオフラインにする


Offline Node On Failure Plugin を使う
Offline Node On Failure Plugin
その名の通り、ビルドが失敗したらオフラインにするプラグインです。

インストールすると、ビルド後の処理に「Take node offline on failure」が追加されます。
細かい設定などは一切ありません。失敗したらオフラインにします。(master は除く)



失敗かつ特定のログがある/ない場合にオフラインにしたい
さて、Offline Node On Failure Plugin は単純に失敗したらオフラインにするプラグインでした。
ただ、同じ失敗でもオフラインにしたいときもあれば、したくないときもあるでしょう。
その場合は、オフラインにしたくないときはビルドステータスを不安定にすることで実現できます。
それも1つの手です。

しかし、それで終わってはつまらないので、別の方法を紹介します。

Groovy Postbuild Plugin でオフラインにする
Groovy Postbuild Plugin を使います。

オフラインの仕方は以下のようにします。
def com = manager.build.getBuiltOn().toComputer()
  if( com.isOnline() ) {
    com.setTemporarilyOffline(true, new OfflineCause.ByCLI("オフラインメッセージ"))
  }

さらに、特定のログが含まれているかどうかは、
manager.logContains で調べられるので、

if( manager.logContains("致命的な失敗") ) {
    def com = manager.build.getBuiltOn().toComputer()
    if( com.isOnline() ) {
      com.setTemporarilyOffline(true, new OfflineCause.ByCLI("オフラインメッセージ"))
    }
  }

のようにすれば、特定のログ出力に応じてオフラインにできます。


まとめ
プラグインを使えば簡単に実現可能ですが、Groovy を使った方法も覚えておくとより柔軟に制御ができるようになると思います。Groovy Postbuild Plugin で使える Groovy Script を github に上げてますので参考にしてください。(あんまり整理・メンテしてませんが…)
https://github.com/srz-zumix/jgpbc

2015年6月1日月曜日

[Jenkins] Groovy でマトリックス生成

追記: この記事には誤りがあります。詳細は記事末尾の追記をご覧ください。

Jenkins のマトリックス構成ジョブでマトリックスをもっと柔軟に作成したいことってありませんか?

例えば、特定のラベルが付いている すべてのスレーブ でテストを実行したい場合、該当するスレーブで軸を作ることになります。
ラベルで軸を作ると、1つのマトリックスしかできないので1回のビルドで実行されるスレーブも1つで、しかもどのスレーブが選ばれるかもわかりません。


欲しいのはこれじゃないです。
目的は、1回のビルドで該当するスレーブすべてで実行することです。
正攻法だと、該当するスレーブを自分で判断して登録していくことになると思います。

該当スレーブが少なければいいのですが、
たくさんあったり、スレーブの設定がよく変わったりする場合は、とてもメンドクサイです。
そこで、GroovyAxis plugin を使いましょう!

GroovyAxis
GroovyAxis plugin ではその名の通り、Groovy script でマトリックスの軸を設定できます。

まずは、プラグインマネージャーからインストールをしてください。
インストールするとマトリックス構成プロジェクトの設定の「軸の追加」に、「GroovyAxis」が追加されます。


これを選ぶと下のような設定が追加されるので、「Groovy Expression」に Groovy を記述します。


サンプル
基本
GroovyAxis のルールとして、配列を return する必要があります。そして、その配列要素が軸になります。
まずは、簡単なサンプルで動作を確認してみましょう。
def result = []
(1..3).each {
   result += "Axis"+it
}
return result
上記スクリプトを Groovy Expression に記入してください。
その下の「Test the Groovy script」ボタンで実行結果を確認できますので、保存する前に確認しておくとよいでしょう。

保存すると、以下のように Axis1,Axis2,Axis3 の3つのマトリックスができます。


すべてのスレーブ
冒頭の目的を達するには、スレーブの情報を知る必要があります。
まずは、スレーブを列挙し、それをマトリックス化します。
def result = []
def jenkins = hudson.model.Hudson.instance
def slaves = jenkins.slaves
slaves.each {
    result += it.getSelfLabel().getName()
}
return result

特定のラベルがあるスレーブ
次に、ラベルを参照し、目的のラベルがあったらマトリックス化します。
def result = []
def jenkins = hudson.model.Hudson.instance
def slaves = jenkins.slaves
slaves.each { slave ->
    slave.getAssignedLabels().find {
        if( it.getName() == "vs2015" ) {
            result += slave.getSelfLabel().getName()
            return true
        }
    }
}
return result

これで、冒頭の目的が達成出来ました。
Groovy script からは色んな情報を参照できるので、他にも面白い使い方ができると思います。
是非、試してみてください。

さらに便利に…
さてこのマトリックですが、スレーブのラベルを付け替えたり、スレーブを増減させた時に、自動で追従させたいと思いませんか?

できたらいいですねー・・・



・・・すみません。わかりません。
今のところ、「設定ページを開いて保存をする」というのを手作業でやる必要があります。
誰か方法を知っていたら教えてくださいm(__)m


追記
意図したスレーブで実行されてませんでした!!
大変申し訳ありませんでした

どうやら、スレーブの軸ではなく、ユーザー定義の軸と同じ挙動のようで、スレーブ軸の設定として Groovy Axis は使えませんでした。
こちらも、解決策がないかもう少し調べてみます。

追記2 - 回避策
根本的な解決とはいかないが、回避策を書いておきます。

組み合わせフィルターを使う


  1. スレーブ軸を追加し、可能性のあるスレーブをすべてチェックする
  2. 組み合わせフィルターを有効にする
  3. フィルターの式を「label==label2」のように、スレーブ軸名==GroovyAxis名とする
設定は以上です。


余分なマトリックスができてしまいますが、目的は達成できます。
(見た目がかなり悪いですが、対象外のスレーブは未実行になってます。)

Matrix Groovy Execution Strategy Plugin を使う
Matrix Groovy Execution Strategy Plugin は、GroovyAxis Plugin とは違い、組み合わせフィルターのところで Groovy script が使えます。


  1. スレーブ軸を追加し、可能性のあるスレーブをすべてチェックする
  2. 組み合わせフィルターを有効にする
  3. 実行方法を「Groovy Script Matrix Executor Storategy」に変更
  4. Groovy Script に以下のようなスクリプトを記述

def list = []
def slaves = jenkins.slaves
slaves.each { slave ->
    slave.getAssignedLabels().find {
        if( it.getName() == "vs2015" ) {
            list += slave.getSelfLabel().getName()
            return true
        }
    }
}

combinations.each {
    if( list.find { l -> it.label == l } ) {
         result[it.label] = result[it.label] ?: []
         result[it.label] << it
    }
}

execution.listener.logger.println result

return result


ビルド結果はこんな感じです。フィルターよりもすっきりしましたね。
また、この方法であればスレーブの設定が変わった場合にも追従が可能です。

とりあえず、今回は Matrix Groovy Execution Strategy Plugin を使った方法を採用したいと思います。

2014年8月11日月曜日

[Jenkins] Groovy Postbuild Plugin で使うスクリプトの共通化

Groovy postbuild plugin
とっても便利なので皆さん、ガシガシ使っていることと思います。

、いろんなジョブに同じようなスクリプトを書いていませんか?
スクリプトを変更したけど、別のジョブのスクリプトの変更を忘れていた、なんてことはないですか?

ということで、似たようなスクリプトは共通化してメンテナンスコストを下げましょう!

スクリプトを共通化
まずは、共通点を抜き出したスクリプトファイルを用意します。
今回は、単純に println するスクリプトを作成しました。
static test(manager)
{
  manager.listener.logger.println "test"
}
作成したファイルは「Hoge.groovy」として保存します。
ファイル分割については、こちらを参考にしました。
Groovyでのスクリプトの分割、共通化 - みちしるべ

Jenkins で使えるようにする
先ほど作成したファイルを、「${JENKINS_HOME}/userContent/groovy」に保存します。このパスは任意ですのでお好きなパスにしてください。

ジョブの設定ページを開き、「Groovy Postbuild」の「Additional groovy classpath」に先ほどのパスを記入します。

設定は以上です。

使う
使うときは、以下のように呼び出します。
Hoge.test(manager)

実行するとこのようにログ出力されます。


簡単ですね!

説明は以上です。これで、Groovy postbuild Plugin がもっと楽に使えるようになりますね^^

2014年8月4日月曜日

[Jenkins][スクリプトコンソール] 各スレーブのシステムプロパティを出力

各スレーブの任意のシステムプロパティを出力するスクリプトです。

def printSystemProperty(key)
{
  def jenkins = hudson.model.Hudson.instance
  def slaves = jenkins.slaves
  slaves.each {
    def com = it.toComputer()
    def properties = com.getSystemProperties()
    if( properties != null )
    {
        def ver = properties[key]
        if( ver != null )
        {
          println(it.getNodeName())
          println(ver)
        }
    }
  }
}

printSystemProperty("java.version")

2014年4月28日月曜日

[Jenkins][管理者向け] 起動時トリガージョブ

Jenkins の管理者向けに Jenkins が起動したらメール通知するジョブを作りました。
(マシンの不調で再起動することが稀にあるので、その検知をするために作った)

まず、Jenkins が起動した時に "何か" させるために、Startup Trigger Plugin をインストールします。
Startup Trigger Plugin はその名の通り、Jenkins の master もしくは slave が起動したことをビルドトリガーとして使えるようにするプラグインです。

あとは、適当なジョブを作成して Startup Trigger で master の起動をトリガーとして設定。

ビルド後の処理にメール通知を設定したら終わりです。
これで Jenkins が起動するとメールが送られてくるようになりました。


ついでなので、Jenkins のログをメールに含めるようにしてみました。
Groovy postbuild Plugin で以下のコードを実行してください。
def jenkins = hudson.model.Hudson.instance
def logs = jenkins.logRecords
if( logs != null )
{
    manager.listener.logger.println("log: ")
    logs.each {
        manager.listener.logger.println(new Date(it.getMillis()))
        manager.listener.logger.println(it.getMessage())
    }
}

logs の部分を以下のようにすれば、ユーザーが作成したログレコーダーからでもログを取得できます。
def logs = jenkins.getLog().getLogRecorder('HOGEHOGE').getLogRecords()

2014年4月21日月曜日

[Jenkins] Email-ext plugin の Pre-send Script を使う

Email-ext plugin の Pre-send Script を使う機会があったので、備忘録として書き残しておきます。
(Jenkins 1.556, Email-ext plugin 2.37.2.2)

Pre-send Script とは?
Pre-send Script はメール送信前にメッセージなどの編集ができる機能です。そのまんまですね。

Pre-send Script では以下のオブジェクトが扱えます。
msgMimeMessage オブジェクト
loggerログ書き込みオブジェクト
buildビルドオブジェクト
cancelboolean, 送信キャンセル

msg はメールの内容を扱う MimeMessage オブジェクトです。宛先の追加やメッセージの追加などができます。
logger はログ出力用のオブジェクトです。logger.println でビルドログに出力できます。
build はビルド情報を扱うオブジェクトです。結果や変更点などビルドに関わる情報をここから取得できます。
cancel に true をセットすると、その名の通りメールの通知がキャンセルされます。

設定方法
拡張e-mail通知の「Advanced Settings...」を開くと「Pre-send Script」の項目があるので、ここの groovy でスクリプトを書き込みます。


注意が必要なのは Pre-send の前に宛先が空だと Pre-send Script は実行されず "An attempt to send an e-mail to empty list of recipients, ignored." でメールが送信されませんので、宛先を編集する場合は気をつけてください。
Examples
上流ビルドのコミッタ-にメール通知する
上流ビルドのコミッタ-にメール通知する方法 - akira0622's blog

特定のログが含まれる場合にメール通知をキャンセル
def log = build.getLog()
pattern = /test/
if( log=~pattern )
{
  logger.println("キャンセルした")
  cancel |= true
}

ユーザーがビルドを実行した場合にメール通知をキャンセル
def cause = build.getCause(hudson.model.Cause.UserIdCause.class)
if( cause )
{
  logger.println("キャンセルした")
  cancel |= true
}

定期ビルドの場合に宛先を追加
import javax.mail.Message.RecipientType
def cause = build.getCause(hudson.triggers.TimerTrigger.TimerTriggerCause.class)
if( cause )
{
  msg.addRecipients(RecipientType.TO, "hogehoge@hoge.co.jp")
}

その他の使い方は公式の Recipe を参照してください。
https://wiki.jenkins-ci.org/display/JENKINS/Email-ext+Recipes

2014年4月14日月曜日

[Jenkins] アップグレードのスケジューリング

Jenkins の管理者の方々は Jenkins 自体のアップグレードやプラグインのアップグレードなど、メンテナンス業務があると思います。
それを少し楽にしたって話です。少しです、少し。

何をしたかというと、「Jenkins を SafeRestart させるジョブ」を作っただけです。
SafeRestart は実行(ビルド)中のジョブがなければ、Jenkins を再起動させる機能です。

どう楽になったか
アップグレードをする場合、Jenkins を止める必要があります。この作業はできるだけ開発メンバーが作業中でない方が良いです。そうなると、アップグレードは夜中とか休日とかなることが多いと思います。
また、大きいプロジェクトや1ビルドがなが~いテストを持つ Jenkins の場合、止めるのにも時間がかかったりします。(強制中断という手もありますが・・・)

それだと、管理者は大変ですよね?

今回、「Jenkins を SafeRestart させるジョブ」を作ったことで、「SafeRestart のスケジューリング」ができるようになり、Jenkins の再起動を予約できるようになりました。
つまり、金曜に Jenkins の更新をダウンロード&インストールしておき(再起動はしてないので、アップグレード自体は未完)、開発メンバーがいない土曜深夜に SafeRestart を仕掛けておけば、日曜日には再起動がかかって無事アップグレードが完了。
そして月曜日にはいつもどおり CI が回せるというわけです。

これで管理者である私は休日出勤しなくて済むようになりました。
SafeRestart させるジョブの作り方
いろいろ方法があると思います。
SafeRestart 自体は、Jenkins の URL + /safeRestart(http://~/safeRestart)を開くだけでもできますし、SafeRestart Plugin ってのもあります。

今回は、みんな大好き Groovy postbuild Plugin を使った方法を紹介します。

1. プロジェクトを作る
2. 「ビルド後の処理の追加」から「Groovy Postbuild」を追加
3. 以下のスクリプトを入力
def jenkins = hudson.model.Hudson.instance
jenkins.doSafeRestart()
4. ビルド・トリガに再起動させたい日時を設定する(ビルド中であることも考慮して早めに設定しておくといいかも)

設定は以上です。これで Jenkins の管理が楽になりますね。

※ Windows の場合、サービスで実行してないとダメなようです。(その他の OS は確認してません)

2013年4月16日火曜日

[Jenkins] スレーブマシンの再起動をするジョブ(その2)

ブログズミ - [Jenkins] スレーブマシンの再起動をするジョブ で紹介したスクリプトをパワーアップさせました。

前回は、再起動したいスレーブでジョブを実行してマシンを再起動させていました。
今回は、再起動したいスレーブとは別のスレーブでジョブを実行し、
ターゲットスレーブのビルドが終わるのを待ってから、再起動させるようにしました。

import hudson.slaves.OfflineCause.SimpleOfflineCause
import hudson.util.RemotingDiagnostics

def jenkins = hudson.model.Hudson.instance

class OfflineMessage extends org.jvnet.localizer.Localizable {
  def message
  OfflineMessage() {
    super(null, null, [])
    def timestr = new Date().format("HH:mm dd/MM/yy z", TimeZone.getTimeZone("UTC"))
    this.message = "automated reboot at end of test at " + timestr
  }
  String toString() {
    this.message
  }
  String toString(java.util.Locale l) {
    toString()
  }
}

def cause = SimpleOfflineCause.create(new OfflineMessage())
def target_name = manager.build.buildVariables.get("REBOOT_SLAVE")

if ( target_name == null ) {
    manager.listener.logger.println("ERROR!! REBOOT_SLAVE is null.")
}

// 同一 PC 上のスレーブをオフライン
def slaves = jenkins.slaves
slaves.each {
    def com = it.toComputer()
    def name = com.getEnvironment().get("COMPUTERNAME","")
    if( name.compareToIgnoreCase(target_name) == 0 ) {
        if( com.isOnline() ) {
            // スレーブをオフラインにしてアイドル待ち
            com.setTemporarilyOffline(true, SimpleOfflineCause.create(new OfflineMessage()))
            // 実際にアイドル待ちするのは、全部オフラインにしてから
        }
    }
}

slaves.each {
    def com = it.toComputer()
    def name = com.getEnvironment().get("COMPUTERNAME","")
    def node_name = it.getNodeName()
    if( name.compareToIgnoreCase(target_name) == 0 ) {
        if( !com.isIdle() ) {
            manager.listener.logger.println("Wait ${node_name} Slave Task...")
            while( !com.isIdle() ) {
                Thread.sleep(3000)
            }
        }
    }
}

// reboot
def script = """

    if (Functions.isWindows()) {
      'cmd /c "shutdown /f /r /t 10 -m \\\\\\\\${target_name} /c \"Restarting after Jenkins test completed\""'.execute()
    }

"""

def computer = manager.build.getBuiltOn().toComputer()
def channel = computer.getChannel()
manager.listener.logger.println(script)
RemotingDiagnostics.executeGroovy( script, channel )

// 再起動待ち
Thread.sleep(5*60*1000)

// 再接続
slaves.each {
    def com = it.toComputer()
    def name = com.getEnvironment().get("COMPUTERNAME","")
    if( name.compareToIgnoreCase(target_name) == 0 ) {
        com.setTemporarilyOffline(false, com.getOfflineCause())
    }
}

こちらのコードは github にもアップしています。

2013年3月12日火曜日

Jenkins + Softalk で容疑者を音声出力させてみた

Groovy post build plugin を使って Softalk から音声出力させてみました。
コードはこちら。
import hudson.util.RemotingDiagnostics

def res = manager.build.getResult();
if( res.isWorseThan(hudson.model.Result.SUCCESS) ) {
    def users = manager.build.getCulprits();
    if( users != null ) {
        def command = "softalkw.exe /W:";
        def find = false;
        users.each {
            command += "${it.getDisplayName()} ";
            find = true;
        }
        if( find ) {
            command += " アウトーーー!";
            manager.listener.logger.println(command);

            def computer = manager.build.getBuiltOn().toComputer();
            def channel = computer.getChannel();
            
            def script = """
                '${command}'.execute();
            """

            RemotingDiagnostics.executeGroovy( script, channel );
        }
    }
}



manager.build.getCulprits() で容疑者のリストが取得できます。
リストからアカウント名を取得し、softalk に読み上げさせたい文字列を作成しています。
アカウント名のままだとアルファベットを読み上げるだけになってしまうので、事前に
softalkw /P:ずみっくす,srz-zumix,True
のようにして単語を登録しておいてください。

メール通知だけの環境で満足してない方は試してみるのもありかも。

2013年3月5日火曜日

[Jenkins] ビルド番号の不整合を検出する

Jenkins がブルースクリーンなどで正常に終了しなかった場合、ビルド番号がリセットされてしまうことがあります。
(最新のバージョンではそんなことはないかもしれませんが)
その状態で古い履歴を削除する設定をしていると、
ビルド番号の大きい古いビルドが削除されず、ビルド番号の小さな新しいビルドが削除されてしまいます。

これが意外と気づきにくいんですよね。

というわけで自動化しましょう!
不整合の検出
@echo off

pushd "%~dp0"

if "x%~1" == "x" (
    call :target_jenkins_home
    if errorlevel 1 goto error
) else (
    call :target_command_line %*
    if errorlevel 1 goto error
)

SET TARGET_PATH
if errorlevel 1 goto error

SET ERRORCODE=0
for /D %%d in ( "%TARGET_PATH%\jobs\*" ) do (
    @echo %%~nd
    if exist "%%d\nextBuildNumber" (
        for /f %%i in ( %%d\nextBuildNumber ) do (
            call :checkbuildnumber %%d %%i
            if errorlevel 1 (
                SET ERRORCODE=1
            )
        )
    )
)

if "%ERRORCODE%" == "1" goto error
goto end

:checkbuildnumber
SET NEXT=%~2
rem @echo next build number %NEXT%

SET MAXNUM=0
setlocal enabledelayedexpansion
for /D %%d in ( "%~1\builds\*" ) do (
    call :getbuildlognumber %%d
    SET CURNUM=!errorlevel!
    if !CURNUM! gtr !MAXNUM! (
        SET MAXNUM=!CURNUM!
    )
)
rem @echo !MAXNUM!
if %NEXT% lss !MAXNUM! (
    @echo "Warning: next build number [%NEXT%] is smaller than the number of the log [!MAXNUM!]."
    exit /b 1
)
endlocal
exit /b 0

:getbuildlognumber
if not exist "%~1\build.xml" exit /b 0
for /f "tokens=1,2,3,4* delims=<>" %%a in ( %~1\build.xml ) do (
    if "%%b" == "number" (
        exit /b %%c
    )
)
exit /b 0

:target_command_line
if not exist "%~1" (
    @echo %~1 は存在しません。
    exit /b 1
)

SET TARGET_PATH=%~1
exit /b 0

:target_jenkins_home
SET JENKINS_HOME >NUL
if errorlevle 1 (
    @echo JENKINS_HOME が設定されていません。
    exit /b 1
)

SET TARGET_PATH=%JENKINS_HOME%
exit /b 0

:error
popd
@echo failed.
pause
exit /b 1

:end
popd
exit /b 0
bat ファイルでございます。
master ノードで実行する必要があります。
第一引数に ${JENKINS_HOME} のパスを指定します。省略した場合、環境変数のパスをそのまま使います。
こんなんでも定期的に実行するようにしたら、効果はきっとあるでしょう。

もう少しスマートに検出する
Groovy post build plugin を使って検出させてみました。
import hudson.model.AbstractProject

def jenkins = hudson.model.Hudson.instance

def projects = jenkins.getAllItems(AbstractProject.class)
projects.each { project ->
    def lastBuild = project.getLastBuild()
    if( lastBuild != null )
    {
        def lastNumber = lastBuild.getNumber()
        def nextNumber = project.getNextBuildNumber()
        if( nextNumber < lastNumber )
        {
            manager.listener.logger.println(project.getName())
            manager.listener.logger.println("Warning: next build number [${nextNumber}] is smaller than the number of the log [${lastNumber}].")
            manager.buildUnstable()
        }
    }
}
たったこれだけで出来ました~(^^
修復
ビルド番号の修正は Jenkins が"停止"しているときにする必要があります(たぶん)。 不整合の検出で使用したバッチファイルを少し変更して、不整合が見つかったら nextBuildNumber を修正します。
@echo off

pushd "%~dp0"

if "x%~1" == "x" (
    call :target_jenkins_home
    if errorlevel 1 goto error
) else (
    call :target_command_line %*
    if errorlevel 1 goto error
)

SET TARGET_PATH
if errorlevel 1 goto error

for /D %%d in ( "%TARGET_PATH%\jobs\*" ) do (
    @echo %%~nd
    if exist "%%d\nextBuildNumber" (
        for /f %%i in ( %%d\nextBuildNumber ) do (
            call :repairbuildnumber %%d %%i
        )
    )
)

goto end

:repairbuildnumber
SET NEXT=%~2
rem @echo next build number %NEXT%

SET MAXNUM=0
setlocal enabledelayedexpansion
for /D %%d in ( "%~1\builds\*" ) do (
    call :getbuildlognumber %%d
    SET CURNUM=!errorlevel!
    if !CURNUM! gtr !MAXNUM! (
        SET MAXNUM=!CURNUM!
    )
)
rem @echo !MAXNUM!
if %NEXT% lss !MAXNUM! (
    @echo "Warning: next build number [%NEXT%] is smaller than the number of the log [!MAXNUM!]."
    SET /a NEWNUM=!MAXNUM!+1
    @echo new next build number !NEWNUM!
    @echo !NEWNUM!| sed 's/\n//g'> "%~1\nextBuildNumber"
)
endlocal
exit /b 0

:getbuildlognumber
if not exist "%~1\build.xml" exit /b 0
for /f "tokens=1,2,3,4* delims=<>" %%a in ( %~1\build.xml ) do (
    if "%%b" == "number" (
        exit /b %%c
    )
)
exit /b 0

:target_command_line
if not exist "%~1" (
    @echo %~1 は存在しません。
    exit /b 1
)

SET TARGET_PATH=%~1
exit /b 0

:target_jenkins_home
SET JENKINS_HOME >NUL
if errorlevle 1 (
    @echo JENKINS_HOME が設定されていません。
    exit /b 1
)

SET TARGET_PATH=%JENKINS_HOME%
exit /b 0

:error
popd
@echo failed.
pause
exit /b 1


:end
popd
pause
exit /b 0
※上記バッチファイルの使用は自己責任でお願いします。

2012年10月18日木曜日

[Jenkins] スレーブマシンの再起動をするジョブ

Groovy postbuild plugin はとりあえずインストールしとけ
で、Groovy postbuild plugin を紹介しました。

今回は、Groovy postbuild plugin を使ってスレーブマシンの再起動する例を見つけたので紹介します。

ネタ元はこちら > https://bugreports.qt-project.org/browse/QTQAINFRA-558

以下に紹介されているコードを示します。
import hudson.slaves.OfflineCause.SimpleOfflineCause
import hudson.util.RemotingDiagnostics

/* FIXME: why cannot we import jenkins.util.NonLocalizable ? */
class OfflineMessage extends org.jvnet.localizer.Localizable {
  def message
  OfflineMessage() {
    super(null, null, [])
    def timestr = new Date().format("HH:mm dd/MM/yy z", TimeZone.getTimeZone("UTC"))
    this.message = "automated reboot at end of test at " + timestr
  }
  String toString() {
    this.message
  }
  String toString(java.util.Locale l) {
    toString()
  }
}

def computer = manager.build.getBuiltOn().toComputer()
def channel = computer.getChannel()
computer.setTemporarilyOffline(true, SimpleOfflineCause.create(new OfflineMessage()))
RemotingDiagnostics.executeGroovy( """

    if (Functions.isWindows()) {
      'shutdown /r /t 10 /c "Restarting after Jenkins test completed"'.execute()
    } else {
      "sudo reboot".execute()
    }

""", channel )

何が嬉しいか
クリーンな環境でテストをしたいと思った場合、
仮想マシンや Windows SteadyState(古い?) を使う方法があります。

そういった場合、クリーンな状態に戻すときに再起動する必要があるので、
このスクリプトを使って自動化できると助かるのではないでしょうか。
(Windows の場合 shutdown コマンドに /f オプションも付けたほうがいいかも)

本当に、Groovy postbuild plugin って便利ですね!

2012年10月12日金曜日

[Jenkins] Groovy postbuild plugin はとりあえずインストールしとけ

なぜ今まで使わなかったのか。もっと早く知っていれば、
チームメンバーからの要望に応えられてたというのに・・・
Groovy Postbuild Plugin

何が便利か
Jenkins が持っている情報の取得・変更がし放題なのです!
Jenkins をもうちょこーっとだけ便利に使いたいという場合に使えます。

例えば、このようなことに使えます。
使い方
「ビルド後の処理の追加」から Groovy postbuild を選択、
「Groovy script」に処理を書きます。

例:テストの説明にビルド時刻を設定
def tr = manager.build.getTestResultAction().getResult()
def st = tr.getSuites()
st.each { suite ->
  def cr = suite.getCases()
  cr.each { res ->
    res.description = "${manager.build.getTime()}"
  }
}

Jenkins のオブジェクトについては、
Jenkins Javadoc を参照するとわかると思います。

設定は以上です。試しに実行した結果がこちら。





wiki に説明と使用例が載ってるのでそちらも参考にしてください。

最後に
とても万能な plugin なので、今は不要でもとりあえずインストールしておくといいと思います。
Groovy postbuild plugin 便利!