次のようなことがやりたかった。
- テストを実行するジョブと、テストが通った特定(master)のブランチをデプロイするジョブを作る
- さらにデプロイが完了したブランチを Redmine に同期するジョブも作るけどそれは省略
- 機能ブランチをテスト → master にマージしてテスト → デプロイ → Redmine に同期
- デプロイ対象のサーバ自体を Jenkins スレーブにする
- デプロイは Jenkins がソースをチェックアウトしてローカルコピーするだけ
- テストとデプロイは別のスレーブで実行されることがある
Pipeline
- 環境変数
BRANCH_NAME
が設定されない- シェルで同じ情報を得られなくもないけど
properties
ビルド世代を指定するとジョブの実行時に一部の設定が消える?- 後述の
Multibranch Pipeline
のように設定してるとSCMをポーリング
の設定が消える - 上書きされてしまうため?
- 後述の
checkout scm
にコミットのIDが渡されないっぽい- 連続でばばばっとプッシュされると同じコミットが2回ビルドされることがある
- ジョブが実行されたときの最新コミットでビルドされるため
- 普通は Git のポーリングで検出されたコミットになるはずなのに
- ので Pipeline の後段で
checkout scm
していると前段とは異なるコミットになることがある - ので前段と後段で同じコミットをチェックアウトするためにはIDを指定する必要がある
- ので
checkout scm
は使えない(使いにくい)
次のように test のステージでチェックアウトされたコミットを取得して deploy のステージで使う。
def git_url = 'http://gitlab.example.com/goto/testing.git' def git_branch def git_commit node('test'){ stage 'test' git url: git_url, branch: "**" echo "this is test" git_branch = sh(script: 'git rev-parse --abbrev-ref HEAD', returnStdout: true).trim() git_commit = sh(script: 'git rev-parse HEAD', returnStdout: true).trim() if (git_branch == 'master') { node('dev'){ stage 'deploy' checkout([$class: 'GitSCM', branches: [[name: git_commit]], userRemoteConfigs: [[url: git_url]]]) echo "this is deploy" } } }
あるいは test のステージのツリーを stash して deploy のステージで unstash でも良いかもしれないけどツリーが巨大だと辛そう。
node('test'){ stage 'test' checkout scm echo "this is test" def git_branch = sh(script: 'git describe --all', returnStdout: true).trim().replaceFirst(/^\w+\/\w+\//, '') if (git_branch == 'master') { stash "ok" node('dev'){ stage 'deploy' unstash "ok" echo "this is deploy" } } }
Multibranch Pipeline
- ブランチごとにジョブが自動的に作成される
Jenkinsfile
が含まれるブランチだけ対象
Branch Sources
にGit
とSingle repository
ってのがあるけど何が違うの?Single repository
だとジョブは指定した名前で1つだけできる?- なぜか設定を保存してもう一度開くと設定がクリアされている?
- よくわからない
Discard old items
で保持数に 1 以上を指定するとブランチが消えてもジョブが消えないっぽい?0
を指定すれば大丈夫だけどそういうものなの?
- ブランチが消えてジョブが削除されてもワークスペースが削除されない
- master には下記のディレクトリができる
workspace/${multi}/${branch}@script/
- node で指定した slave には下記のディレクトリができる
workspace/${multi}/${branch}/
workspace/${multi}/${branch}@tmp/
- ブランチ作成→削除を繰り返すとものすごいゴミがたまる
- master には下記のディレクトリができる
- ブランチジョブのビルド履歴は
properties
で指定しないとダメ- 親の
Discard old items
が継承されるわけではない
- 親の
下記のような Jenkinsfile でそこそこ良い感じにできるけど、ブランチ作成→削除でゴミがたまる。
properties properties: [ [$class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', numToKeepStr: '10']] ] node('test'){ stage name: 'test', concurrency: 1 checkout scm echo "this is test" } if (env.BRANCH_NAME == 'master') { node('dev'){ stage name: 'deploy', concurrency: 1 checkout scm echo "this is deploy" } }
例えばジョブの実行時にカレントディレクトリの兄弟のディレクトリが古かったら削除するとか。
properties properties: [ [$class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', numToKeepStr: '10']] ] node('test'){ stage name: 'test', concurrency: 1 checkout scm echo "this is test" } if (env.BRANCH_NAME == 'master') { node('dev'){ stage name: 'deploy', concurrency: 1 checkout scm echo "this is deploy" } } stage 'purge' node('test'){ sh "find ../ -mindepth 1 -maxdepth 1 -mmin +60 -print0 | xargs -0 rm -vfr" } node('master'){ sh "find ../ -mindepth 1 -maxdepth 1 -mmin +60 -print0 | xargs -0 rm -vfr" }
ブランチの有無、あるいはジョブの有無を確認して削除するかどうかを判断できると理想。
まとめ
そんなに多段にしているわけでもないし、Jenkins DSL でいまのところ満足しているので、当面はそのままでいいや。