Jenkinsfile で処理をエラーとせず中断する

スポンサーリンク

最近の Jenkins では Pipeline をつかって柔軟にビルドジョブを設定できます。その設定ファイルは Groovy の DSL で、jenkinsfile と呼ばれたりします。従来のスクリプトベタ書きに比べて柔軟な記述ができます。ある条件ときにはビルドジョブを中断したりもできます。その中断の方法を説明します。

スポンサーリンク

エラーとして中断する

Jenkins の Jenkinsfile にて途中で処理を終了するには通常 error を使います。引数には終了したときに表示する文字列を渡します。下記のようにすればOKです。これでビルドを中断できます。そのときビルドは失敗したことになります。

    error "something wrong"

公式の説明も貼っておきます。2行しか説明ないですが。

Pipeline: Basic Steps
Jenkins – an open source automation server which enables developers around the world to reliably build, test, and deploy their software
スポンサーリンク

ビルドしなかったとして中断する

エラーにして中断する場合は上記の通り error を使えばOKです。それ以外に成功にもエラーにもしたくない、ビルドしなかったという状態にしたい場合もあります。たとえばコミットがあったがそれがビルドには関係ないファイルの追加だった時などです。

今回は repo を使って説明をします。repo は多数のGitリポジトリからなるプロジェクトを扱うためのGitのフロントエンドです。 AOSPYocto などで利用されています。今回は前のバージョンのビルドから各リポジトリのハッシュ値が変更なければビルド不要として中断することを考えます。ついでの jenkinsfile の小技も説明します。

スポンサーリンク

jenkinsfile の例

最初に前回から更新がなかった場合に中断する Jenkinsfile を示します。下記の内容を実行しています。詳細は後述します。

  • src ディレクトリに移動する
  • repo diffmanifests を実行して出力を変数 diff_manifest に格納する
  • 出力が空だったらビルド不要ということでビルド無しとして終了する
  • 出力が空でなかったらビルドを継続する
stage ('前回から更新があったか確認') {
    steps {
        dir('src') {
            script {
                String diff_manifest
                diff_manifest = sh(returnStdout: true, returnStatus: false,
                                   script: """\
                                             |#!/bin/bash -e
                                             |repo diffmanifests --raw previous.xml default.xml 2>&1
                                             |""".stripMargin())
                if (!diff_manifest) {
                    println "No changes."
                    Jenkins.instance.getItemByFullName("$env.JOB_NAME").getBuildByNumber(currentBuild.number).doStop()
                } else {
                    println "Changes found."
                    println diff_manifest
                }
            }
        }
    }
}

dir

dir で囲まれた処理は dir の引数で指定したディレクトリで実行されます。dir ('src') { ...... }は src へ移動して処理を実行する、という意味です。

sh

sh は名前のまんまで、シェルを実行します。引数に returnStdout と returnStatus を指定できます。returnStdout が true だと標準出力を返します。returnStatus が true だと終了ステータス(0 とか 125 とか)を返します。有効にできるのはどちらかただけです。両方を有効にしてもエラーにはならないようですが意図通りには動きません。標準出力か終了ステータスかどちらかしか返せません。

stripMargin

これは別に使わなくてもいいのですがコードのみやすさのために使っています。行頭のスペースを削除できます。上記の例では行頭から「|」までを削除します。先頭のシェバンはからなず行頭から始める必要があるので、これがないとコードのインデントがくずれて見づらくなります。

ちなみにこの例だとシェバンはなくても動きますが安全のためつけておいたほうがいいでしょう。下記の投稿のようなエラーを踏んでしまう可能性があります。

Jenkinsfile から bash の機能を使う
Jenkins の設定ファイル(jenkinsfile)からコマンドを実行してその標準出力を受け取る時、sh() を使うと思います。下記のプラグインで提供されている機能ですね。 これは上記のサイトの説明に「Runs a Bou...

repo diffmanifests

repo はjenkinsfileとは直接は関係しないのでかるく読んでもらえればいいです。repo は各リポジトリとそのバージョンをマニフェストファイルと呼ばれる xml ファイルに記述します。また、repo diffmanifests 前のバージョン.xml 後のバージョン.xmlのように実行すると、前のバージョンから後のバージョンまでの差分を表示してくれます。差分がなければ何も表示しません。実行例は下記の投稿を参照してください。

コマンド出力を色付きのまま保存する | ansi2html と unbuffer
LinuxやWSLなどでコマンドを実行した時、出力がカラーで表示されることがあると思います。たとえば ls --color=auto とかですね。このような出力を普通にリダイレクションなどでファイルに書き込むと色情報が失われて普通の文字にな...

またこのコマンドは原則として終了ステータスは0を返します。なぜかエラーでも0を返してきます。

途中終了

ビルドジョブを途中で終了するためにdoStop()を呼び出しています。これで途中終了ができます。終了ステータスはABORTEDでになります。

Executor.currentExecutor().doStop() でも終了できそうな気がしたのですが、currentExecutor() が NULLを返してきてうまくいきませんでした……。ちなみにreturn はそのstageを抜けるだけでビルドジョブは終了しません。次のstageへ進んでしまいます。ではsystem.exitならどうかというと、これだとJVMごと終了してしまいJenkins自体がおちてしまいます。おちてしまった場合はsudo service jenkins restart として再起動させてください。

スポンサーリンク

まとめ

今回は Jenkinsfile にて途中で処理を中断する方法を説明しました。ついでに jenkinsfile の sh や dir 、stripMargin も説明しました。Jenkins Pipeline は柔軟性が高いのでこれを使えばさらに便利にCIを構築できると思います!

Jenkins
スポンサーリンク
しんやさんをフォローする
スポンサーリンク
ハングスタック

コメント