kotas.tech

こたすの技術的なチラ裏 ( Twitter: @ksaito )

Git ブランチから自動的に Jenkins ジョブを作る

Jenkins の Git プラグインは標準で複数ブランチのビルドに対応してるんですが、1つのジョブで全部のブランチをビルドするので

[成功 (master)] → [失敗 (branchA)] → [成功 (master)] → [失敗 (branchA)]

みたいな感じでブランチごとの成功/失敗がわかりづらく、IRC に通知出してると

FAILED! → Yippie! → FAILED! → Yippie! …

とうるさい感じで残念です。

というわけで軽くググったところ、引っかかった↓を導入します。

Jenkins "Build Per Branch" by entagen

インストール

まずはドキュメントに書かれている通り、Jenkins にプラグインをいくつかインストール。

あと、Jenkins のユーザーから Git リポジトリにアクセスできるように設定しておきました。

テンプレートジョブ作成

次に、自動生成されるジョブのテンプレートとなるジョブを作っておきます。通常は master に対してテストを実行するジョブになると思います。

  • プロジェクト名: myproj
  • テンプレートジョブの対象ブランチ: master

の場合、テンプレートジョブ名は以下のようにする必要があります。

myproj-<好きな名前>-master

僕の場合はテスト実行したいだけなので "myproj-test-master" みたいな感じにしました。

なお、<好きな名前> 部分を変えて複数のジョブを作れば、各ブランチに対して同じように複数のジョブが作られます。

テンプレートジョブは、コピーしてもすぐに動かせるように、ビルドを完全に自動化しておく必要があります。

また、ジョブの設定で [ソースコード管理システム] → [Git] → [Branches to build] を master にしておきます。

ブランチを同期させるジョブを作る

適当な名前(例: sync-myproj-branches)で「フリースタイル・プロジェクトのビルド」のジョブを作ります。*1

ジョブの設定は以下のようにしていきます。

ソースコード管理システム

  • [Git] を選択
  • [Repositories] の [Repository URL] に下記を入力
https://github.com/entagen/jenkins-build-per-branch.git
  • [Branches to build] の [Branch Specified] に下記を入力
origin/master

ビルド・トリガ

[定期的に実行] を使ってもいいですが、僕の場合はフックで動かすようにしたので何もチェックを入れてません。

ビルド

[ビルド手順の追加] を押して [Invoke Gradle script] を選択します。

  • [Use Gradle Wrapper] にチェックを入れます。
  • [Switches] には、以下のオプションを指定する必要があります。
オプション名 説明
-DjenkinsUrl Jenkins の URL http://localhost:8080/jenkins
-DgitUrl Git リポジトリの URL git@github.com:example/repos.git
-DtemplateJobPrefix 先ほど作ったテンプレートジョブのプロジェクト名部分
(上記の例なら myproj)
myproj
-DtemplateBranchName テンプレートジョブの対象ブランチ名
(上記の例なら master)
master
-DnestedView Jenkins トップのジョブ一覧でのグループ名(不要なら省略) myproj-branches
-DdryRun true を指定すると、実際には何も行わずに操作内容を見られる true
  • 例として、[Switches] 入力欄の右側の [▼] を押して複数行入力にしてから、以下のように入力します。
-DjenkinsUrl=http://localhost:8080/jenkins
-DgitUrl=git@github.com:example/repos.git
-DtemplateJobPrefix=myproj
-DtemplateBranchName=master
-DnestedView=myproj-branches
-DdryRun=true
  • [Tasks] に下記を入力します。
syncWithRepo

実行

-DdryRun=true の状態で、先ほど作ったブランチを同期させるジョブ (sync-myproj-branches) をビルド実行します。

初回実行時は Gradle による依存ライブラリのインストールが走るので多少時間がかかります。

ビルド結果のコンソール出力から、どのような操作が行われるか確認できます。

問題なければ、ジョブ設定の [Switches] から "-DdryRun=true" の行を削除すれば、実際にジョブが作成されます。

これで、Git ブランチとジョブの同期ができるようになりました。

フックで実行

次に、Git リポジトリに何かがプッシュされたら、自動的にブランチとジョブを同期してから、変更されたブランチのジョブをビルド実行するようにしたいです。

まず、Git のサーバーサイドフックや、Git フロントエンドの WebHook 機能などで、プッシュがあったタイミングで下記の URL に POST するようにします。(sync-myproj-branches は自分のジョブ名に書き換えて下さい)

http://<JenkinsのURL>/job/sync-myproj-branches/build

僕の場合は、GitLab を使ってたので、プロジェクトの Hooks から上記の URL を追加しておくだけで OK でした。

ジョブとブランチの同期後にビルド実行

これで、Git に何かがプッシュされる度に自動的にブランチとジョブが同期されるようになりましたが、これだけでは同期で作られたジョブのビルドが実行されませんので、ブランチ同期ジョブ (sync-myproj-branches) のビルド手順に以下を追加しました。

curl -s "http://<JenkinsのURL>/git/notifyCommit?url=<GitリポジトリのURL>"

これで、同期が終わったタイミングで Git プラグインに通知され、更新されたブランチに関連するジョブでビルドが実行されるようになりました。

やったー\(^o^)/

*1:ドキュメントでは「SyncYOURPROJECTGitBranchesWithJenkins」という名前で作れと書いてありますが、好きな名前で動かせます