Log

いろいろ

GitHubへのpushをトリガーにJenkinsでテストを実行しmasterにマージしてHerokuへデプロイする

タイトル通りです。

やりたいこと

  1. ローカルからGitHubのdevelopブランチへpush
  2. GitHubがWebhookでJenkinsに通知を行う
  3. push先の判断
  4. unittest実行
  5. masterにマージ
  6. Herokuへデプロイ

3~5がJenkinsで実行するジョブ単位です。ついでに各ジョブの実行をSlackで通知します。

3. push先の判断

これは補助的なジョブです。

役割としてはGitHubへのpush先ブランチがdevelopかmasterかを判断するだけです。developであればビルド成功、masterであれば不安定ビルドで終了します。

本来であればGitHubとJenkinsの連携に「Git Plugin」または「GitHub Plugin」を使おうと思ったのですが、GitHub側がServeicesをWebhooksに統合してしまったようです。これらのPluginであればGitHub側でブランチを指定できたようなのですが。残念。

developer.github.com

Webhooksでは多様なイベントをトリガーにできますが、ブランチの指定ができません。Jenkins側でパラメータを見てブランチを判断することになりますが、masterにしろdevelopにしろ、ビルドは行わなずともジョブが走ってしまうのです。「5. masterにマージ」のジョブが実行される度に失敗記録が積み上がるのも嫌なので、今回は全体制御用にこのジョブを作成しています。

他にいい方法があれば教えて下さい。

Jenkinsの設定

  • 「Conditional BuildStep」をインストール。
  • ユーザーの管理より「Add new Token」を選択してAPIトークンを取得。

GitHubの設定

  • Settings>Webhooksより「Add webhook」を選択してURLを以下の形式で入力します。 TOKEN_NAMEはジョブの設定で指定する認証トークンです。
http://[USER_ID]:[API_TOKEN]@[JENKINS_HOST]/job/[JOB_NAME]/buildWithParameters?token=[TOKEN_NAME]

ジョブの設定

今回作成するジョブは全てフリースタイルプロジェクトです。

  • General
    「ビルドのパラメータ化」にチェックを入れてテキスト形式で名称はpayloadとしておきます。
  • ビルド・トリガ
    「リモートからビルド」にチェックを入れて認証トークンに適当な値を入力します。この認証トークンがGitHubの設定で使うTOKEN_NAMEです。
  • ビルド
    「シェルの実行」を選択し下記の通りシェルを書いて「Exit code to set build unstabl」には「1」を設定します。これによりdevelop以外にpushされた場合にはexit code=1でシェルが終了しジョブの実行結果が不安定ビルドになります。
if [[ ${payload} =~ .*\"ref\":\"refs/heads/develop\".* ]]; then
  exit 0
fi
  exit 1

f:id:mtzml:20210313154452p:plain

上がdevelopで下がmasterからのpushです。masterがunstableになっているのでOK。

このジョブではSlack通知を行わないため、以上で設定は終了です。

4. unittest実行

事前準備

  • EC2にPython3系を入れておきます。
$ sudo yum update
$ sudo yum install python3
  • Jenkinsに「ShiningPandas Plugin」をインストール。Jenkinsの管理>Global Tool ConfigurationよりPython3を追加します。

以上で、EC2上のJenkinsでPython3を使えるようになります。

ジョブの設定

  • ソースコード管理
    Gitを選択しリポジトリURLには先程と同じURLを入れます。ビルドするブランチはdevelopです。
  • ビルド・トリガ
    「他のプロジェクトの後にビルド」を選択し、対象プロジェクトには「3. push先の判断」のジョブを指定し「安定している場合のみ起動」とします。これでdevelopにpushされた時のみこのジョブが実行されるようになります。
  • ビルド
    「Virtualenv Builder」を追加します。Python3を選択して以下のシェルを入力。
pip install -r requirements.txt
coverage run --source='dokipro1' -m xmlrunner -o test-reports
coverage xml -o coverage/result.xml
  • ビルド後の処理
    JUnitテスト結果の集計」「Coberturaカバレッジ・レポートの集計」を追加します。これらの設定はリソースパスを指定するだけです。そして「Slack Notification」も追加します。これでSlackにビルド通知が飛びます。

5. masterにマージ

排他とかどうするんだろうと思ったけど、このプロジェクトの開発者は私一人なので考えないことにします。

ジョブの設定

  • ソースコード管理
    先程のジョブと同じようにURLを設定。今回は認証情報としてGitHubのアカウントを追加します。cloneだけなら問題ないですがpush時に必要となるためです。追加処理から「Meger before build」を選択し、masterにmergeするようにしておきます。
  • ビルド後の処理
    「Git Publisher」を追加します。「ビルド成功時のみプッシュ」「結果をマージ」を選択し「ブランチ」でoriginのmasterを指定します。「Slack Notifications」も追加。Slack通知もにぎやかになってきました。

6. Herokuへデプロイ

最後のジョブです。Herokuの便利機能を使います。

Herkokuのダッシュボード>Deployから「Automatic deploys」を有効にするだけです。これで指定したブランチにコミットがあった場合に、自動でデプロイをしてくれます。今回はmasterを設定。

Slackへの通知も行おうとしましたが失敗しました。また今度挑戦します。

おわりに

躓きながらで結構時間がかかってしまった。

「3. push先の判断」を「4. unittest実行」から切り出したことは、Webhookトリガーへの依存性が排除され、部品としての独立性がたかまったので良かったと思う。

「5. masterにマージ」と「6. Herokuへデプロイ」は一緒でもいいんじゃない?て思うけど、ここまでで疲れていたのでHerokuのCLI周りが面倒だった。

今度はPipelineで置き換えしてみたい。