はじめに
こんにちはSREエンジニアのMakiです。
この記事ではJenkins Pipelineジョブの使い方応用編として、パラレル処理のやり方や、対話形式での入力などのやり方を紹介していきます。
少し高度なパイプラインを書こうかなと考えている人の参考になれば幸いです。
【Jenkins】Pipelineジョブを使ってみよう ~ 応用編 ~
シナリオ
- 【Jenkins】フリースタイルジョブを使いこなそう!~ かわいい子猫の画像を取得してみる ~
https://tielec.blog/index.php/sre/ci-cd/jenkins/free_style_job/ - 【Jenkins】Pipelineジョブを使ってみよう ~ 基本編 ~
https://tielec.blog/index.php/sre/ci-cd/jenkins/pipeline-basic/
上記で作成した猫の画像をダウンロードするジョブ(フリースタイルジョブとパイプラインジョブ)をパラレルで実行します。このときに対話式で実行するかの確認を求めるようにする。
Pipelineジョブを作成する
前回と同様ジョブを作成します。
ジョブの名前は parallel_download_kitten_image_pipeline
とします。
設定の入力
設定は省略します。
必要に応じて 古いビルドの破棄
など設定しましょう。
スクリプト作成
型を作る
pipelineの型を埋めていきます。
- nodeはslave1
- stageは "Confirm download kitten image"と"Parallel download kitten image"の二つを用意しておきます。
- postブロックは
cleanWs
のみ設定しておきます。
pipeline{
agent{
label "slave1"
}
stages{
stage("Confirm download kitten image"){
steps{
echo "========executing A========"
}
}
stage("Parallel download kitten image"){
steps{
echo "========executing A========"
}
}
}
post{
always{
cleanWs()
}
}
}
Confirm download kitten image
stage Confirm download kitten image
の中身を実装していきます。
やりたいことの確認
- 次のステージに進む前に対話式で実行の確認をできるようにしたい。
- 承認ステージをスキップしたい場合に対応できるようにしたい。
この二つを実現していきます。
1. 次のステージに進む前に対話式で実行の確認をできるようにしたい。
まず一つ目の対話式での確認ですが、input
というステップを使います。
また、input
を使うときは入力がされないままジョブが滞留するということを防ぐためにtimeoute
というステップと併用します。
- 1時間何もなかったらタイムアウトする設定を作ります。
timeout(time: 1, unit: 'HOURS') {
// some block
}
- 対話のメッセージを設定します。
input 'download kitten image?'
- inputはtimeout の内側のブロックに記載します。
timeout(time: 1, unit: 'HOURS') {
input 'download kitten image?'
}
- これをstepsの中に書きます。
pipeline{
agent{
label "slave1"
}
stages{
stage("Confirm download kitten image"){
steps{
timeout(time: 1, unit: 'HOURS') {
input 'download kitten image?'
}
}
}
stage("Parallel download kitten image"){
steps{
echo "========executing A========"
}
}
}
post{
always{
cleanWs()
}
}
}
2. 承認ステージをスキップしたい場合に対応できるようにしたい。
続いて二つ目の承認ステージをスキップしたい場合に対応できるようにしていきます。
パラメータにスキップするオプションを定義し、条件に当てはまるときはスキップするという方針で実装します。
使うのは parameters
と when
を使います。
前回まではジョブの設定でparameterを組みましたが、実はpipelineの中で定義することも可能です。
今回は真偽値のパラメータをSKIP_CONFIRM_DOWNLOAD
という名前で定義してそれをフラグとして利用することにします。
parameters {
booleanParam defaultValue: false, description: 'チェックを入れた場合ダウンロードの確認をスキップします。', name: 'SKIP_CONFIRM_DOWNLOAD'
}
parameter
はagent
と同じ階層に記載します。
pipeline{
agent{
label "slave1"
}
parameters {
booleanParam defaultValue: false, description: 'チェックを入れた場合ダウンロードの確認をスキップします。', name: 'SKIP_CONFIRM_DOWNLOAD'
}
stages{
stage("Confirm download kitten image"){
steps{
timeout(time: 1, unit: 'HOURS') {
input 'download kitten image?'
}
}
}
stage("Parallel download kitten image"){
steps{
echo "========executing A========"
}
}
}
post{
always{
cleanWs()
}
}
}
- 次に
when
ブロックを使ってstage
の実行制御していきます。
SKIP_CONFIRM_DOWNLOADがtrueではない
ときに実行するという条件で設定します。
when {
not {
environment name: 'SKIP_CONFIRM_DOWNLOAD', value: 'true'
}
}
when
ブロックはstage
ブロック内の最初に記載します。
pipeline{
agent{
label "slave1"
}
parameters {
booleanParam defaultValue: false, description: 'チェックを入れた場合ダウンロードの確認をスキップします。', name: 'SKIP_CONFIRM_DOWNLOAD'
}
stages{
stage("Confirm download kitten image"){
when {
not {
environment name: 'SKIP_CONFIRM_DOWNLOAD', value: 'true'
}
}
steps{
timeout(time: 1, unit: 'HOURS') {
input 'download kitten image?'
}
}
}
stage("Parallel download kitten image"){
steps{
echo "========executing A========"
}
}
}
post{
always{
cleanWs()
}
}
}
このあたりでVSCodeの Pipeline Linter
でシンタックスエラーがないか確認してみます。
※ Pipeline Linter について わからない方は前回の記事を御覧ください↓
https://tielec.blog/index.php/sre/ci-cd/jenkins/pipeline-basic/#toc6
linterの使い方
Ctrl
+ Shift
+ P
> Validate Jenkinsfile
を実行
Jenkinsfile successfully validated.
が表示されればOKです。
これでConfirm download kitten image
のステージの実装が完了しました。
Parallel download kitten image
続いてParallel download kitten image
のステージを実装します。
ただ、ジョブを二つパラレルで実行しても面白くないのでScripted Pipeline
の書き方を使ってみます。
やりたいこと
- 日付をjson形式で取得できるAPIを利用し、今日の日付を返す関数を作る。
- 取得した日付を用いてダウンロードする画像のファイル名を準備する。
- 日付が入ったファイル名をジョブのパラメータとし
kitten_image_generator
とkitten_image_generator_pipeline
の二つを並列実行する。
1. 日付をjson形式で取得できるAPIを利用し、今日の日付を返す関数を作る。
関数の定義はpipelineブロックの外側で定義することができます。
getTodayFromJsonApi
という名前で関数を作ります。def getTodayFromJsonApi(){ sh 'curl -f -o date.json "http://date.jsontest.com"' json = readJSON file: 'date.json' echo "TODAY is ${json.date}" return json.date }
関数はこのように定義することができます。
やっていること
sh
ステップの中で日付をjson形式表示するAPIをキックしdate.json
というファイルに吐き出す。readJson
というステップを用いてファイルを読み込みjson
という変数に値を格納する。- return で日付を返す。
変数の中身は以下のようなデータが格納されています。
{
date: "11-26-2019",
milliseconds_since_epoch: 1574773459376,
time: "01:04:19 PM"
}
- これをパイプラインに記載します。
pipeline{
agent{
label "slave1"
}
parameters {
booleanParam defaultValue: false, description: 'チェックを入れた場合ダウンロードの確認をスキップします。', name: 'SKIP_CONFIRM_DOWNLOAD'
}
stages{
stage("Confirm download kitten image"){
when {
not {
environment name: 'SKIP_CONFIRM_DOWNLOAD', value: 'true'
}
}
steps{
timeout(time: 1, unit: 'HOURS') {
input 'download kitten image?'
}
}
}
stage("Parallel download kitten image"){
steps{
echo "========executing A========"
}
}
}
post{
always{
cleanWs()
}
}
}
def getTodayFromJsonApi(){
sh 'curl -f -o date.json "http://date.jsontest.com"'
json = readJSON file: 'date.json'
echo "TODAY is ${json.date}"
return json.date
}
2. 取得した日付を用いてダウンロードする画像のファイル名を準備する。
Decralative pipeline
の中でScripted Pipeline
のような書き方をする場合はscript
ブロックを使います。script
ブロックの中では関数の呼び出しや、変数の変更など柔軟な書き方ができます。Groovy
の知識が必要となるのは主に、このscript
ブロックを使いたいときになります。
script{
def today = getTodayFromJsonApi()
def image = "kitten-image-${today}.jpg"
}
このようにscript
ブロックの中で関数の呼び出しや変数の定義を行うことができます。
3. 日付が入ったファイル名をジョブのパラメータとし "kitten_image_generator" と "kitten_image_generator_pipeline"の二つを並列実行する。
まずはパラレル実行はparallel
ステップを使います。
書き方がちょっと特殊なのでいかにテンプレートを用意します。
parallel(
"A":{
echo '========executing A========'
},
"B":{
echo '========executing B========'
}
)
A、Bにはそれぞれわかりやすい名前を入れてください。
次に kitten_image_generator
を呼び出す処理を書きます。
ジョブの呼び出しはPipelineSyntax
から作るとパラメータなどのサジェストがされるので便利です。
- KITTEN_IMAGE_FILE_NAMEのパラメータには先ほど定義した
image
という変数を渡します
build job: 'kitten_image_generator', parameters: [string(name: 'KITTEN_IMAGE_FILE_NAME', value: image)]
-
同様に
kitten_image_generator_pipeline
の呼び出し部分も作ります. -
これらを
script
ブロックに書いていく次のようなものが出来上がります。
script{
def today = getTodayFromJsonApi()
def image = "kitten-image-${today}.jpg"
parallel(
"kick freestyle job": {
build job: 'kitten_image_generator', parameters: [string(name: 'KITTEN_IMAGE_FILE_NAME', value: image)]
},
"kick pipeline job": {
build job: 'kitten_image_generator_pipeline', parameters: [string(name: 'KITTEN_IMAGE_FILE_NAME', value: image)]
}
)
}
これを Parallel download kitten image
の中に記載したら完成です。
Linterでシンタックスエラーを確認するのもお忘れなく。
完成!!
こちらはすべて書き終わったあとのJenkinsFile
です。
pipeline {
agent {
label "slave1"
}
parameters {
booleanParam defaultValue: false, description: 'チェックを入れた場合ダウンロードの確認をスキップします。', name: 'SKIP_CONFIRM_DOWNLOAD'
}
stages {
stage("Confirm download kitten image") {
when {
not {
environment name: 'SKIP_CONFIRM_DOWNLOAD', value: 'true'
}
}
steps {
timeout(time: 1, unit: 'HOURS') {
input 'Download kitten image?'
}
}
}
stage("Parallel download kitten image") {
steps {
script{
def today = getTodayFromJsonApi()
def image = "kitten-image-${today}.jpg"
parallel(
"kick freestyle job": {
build job: 'kitten_image_generator', parameters: [string(name: 'KITTEN_IMAGE_FILE_NAME', value: image)]
},
"kick pipeline job": {
build job: 'kitten_image_generator_pipeline', parameters: [string(name: 'KITTEN_IMAGE_FILE_NAME', value: image)]
}
)
}
}
}
}
post {
always {
cleanWs()
}
}
}
def getTodayFromJsonApi(){
sh 'curl -f -o date.json "http://date.jsontest.com"'
json = readJSON file: 'date.json'
echo "TODAY is ${json.date}"
return json.date
}
Pipelineジョブを実行する
-
ビルド実行
をおしてジョブを実行します。
※ 初回実行時はパラメータが読み込まれていないのでパラメータ付きビルド
ではなくビルド実行
になります。 -
Stage Viewにcursorを合わせるとメッセージがサジェストされます。
-
Proceed
を押すと処理が進みジョブが実行されます。
- Blue Oceanでパイプラインの様子を見てみます。
-
画面左
Open Blue Ocean
を開く -
最新のビルド番号を開く
このようなパイプラインになりました。
-
今度は確認をスキップして実行してみます。
-
確認が行われずに画像をダウンロードするステージへと進みました。
-
再度Blue Oceanで確認してみます。
Blue Oceanでもスキップされていることが確認できます。
Jenkins Pipelineジョブを使ってみよう ~ 応用編 ~の内容は以上です。お疲れ様でした。
まとめ
いかがでしたでしょうか。今回の記事ではJenkinsPipeline の応用編としてパラレル処理と対話式で入力処理のやり方について記載しました。質問やコメントとうございましたらぜひフィードバックお願いします。
関連ページ
-
Jenkins Pipelineを学ぶ前に知っておいて欲しいこと
https://tielec.blog/index.php/sre/ci-cd/jenkins/pipeline-concept/ -
【Jenkins】Pipelineジョブを使ってみよう ~ 基本編 ~
https://tielec.blog/index.php/sre/ci-cd/jenkins/pipeline-basic/
おすすめ書籍
[改訂第3版]Jenkins実践入門 ――ビルド・テスト・デプロイを自動化する技術 (WEB+DB PRESS plus)
初めてJenkinsを学ぶ方におすすめです。
Jenkins
Jenkinsでできることについてもう少し詳しく学びたい方におすすめです。
コメント