2020-12-26ログ:MacにVirtualBoxでCentos7を建てる
MacにVirtualBoxでCentos7を建てる
環境
- macOS:10.15.7
- VirtualBox:6.1.4
作業内容
VirtualBoxのインストール
既にインストール済みだった。
$ VBoxManage -v 6.1.4r136177
CentOS7のダウンロード
仮想マシンの作成
新規から作成。
作成後にマシンを選択して設定>ストレージから「コントローラ:IDE」にインストールしたCentOSのディスクイメージを設定。
仮想マシンの設定変更
設定>ディスプレイから「表示倍率」を250%に変更
以上
GitHubへのpushをトリガーにJenkinsでテストを実行しmasterにマージしてHerokuへデプロイする
タイトル通りです。「Jenkins+Python+unittest」の記事のまとめみたいな。
やりたいこと
- ローカルからGitHubのdevelopブランチへpush
- GitHubがWebhookでJenkinsに通知を行う
- push先の判断
- unittest実行
- masterにマージ
- Herokuへデプロイ
3~5がJenkinsで実行するジョブ単位です。ついでに各ジョブの実行をSlackで通知します。
3. push先の判断
これは補助的なジョブです。役割としてはGitHubへのpush先ブランチがdevelopかmasterかを判断するだけです。developであればビルド成功、masterであれば不安定ビルドで終了します。
本来であればGitHubとJenkinsの連携に「Git Plugin」または「GitHub Plugin」を使おうと思ったのですが、GitHub側がServeicesをWebhooksに統合してしまったようです。これらのPluginであればGitHub側でブランチを指定できたようなのですが。
Webhooksでは多様なイベントをトリガーにできますがブランチの指定ができません。Jenkins側でパラメータを見てブランチを判断することになりますが、masterでもdevelopでもビルドは行わなくてもジョブが走ってしまうのです。「5. masterにマージ」のジョブが実行される度に失敗記録が積み上がるのも嫌なので今回は全体制御用にこのジョブを作成しています。
他にいい方法があれば教えて下さい。
Jenkinsの設定
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
上が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で置き換えしてみたい。
Jenkins+Python+unittest最後
(2020/05/06:追記)こっちを見たほうが良いです。
続きです。
GitHubのdevelopへのpushをトリガーにJenkinsのジョブを実行します。
1. unittet実行
Jenkins
- Jenkinsの管理>プラグインの管理より「Conditional BuildStep」をインストール。
- Jenkinsの管理>ユーザーの管理>(ユーザー)>設定>より「Add new Token」を選択してJenkinsにアクセスするためのAPIトークンを取得する。
- ジョブ>設定>ビルド・トリガの「リモートからビルドにチェック」してURLをメモする。
- ビルド手順の追加より「Conditional step(Single)」を選択して下記の通り設定。
項目 | 値 |
---|---|
Run? | Regular Expression Match |
Expression | ."ref":"refs\/heads\/develop". |
Label | ${ENV,var="payload"} |
On evaluation failure | Don't run |
Builder | Virtualenv Builder |
shellは前と同じ内容です。
pip install -r requirements.txt coverage run --source='dokipro1' -m xmlrunner -o test-reports coverage xml -o coverage/result.xml
GitHub
ジョブの実行
以上で設定は完了です。試しにdevelopにpushしてみます。空コミットが便利です。
$ git commit --allow-empty -m '[Dev] Jenkins連携テスト' $ git push origin develop
Jenkinsから確認したとこと無事にジョブが実行されていました。
さて、本当はこの後developをmasterにマージするジョブを作りたかったのですが問題が発生しました。masterにマージしてpushするとこの記事で作っている単体テストジョブが実行されてしまいます。ちょっとJenkinsの実行トリガーから考え直さなければいけなくなりましたのでここまで。
Jenkins+Python+unittest番外編
(2020/05/06:追記)こっちを見たほうが良いです。
coverageの集計が間違っていたました。
明らかに対象のファイル数が多いと思ったらライブラリも集計対象になってた。
coverage run --source='dokipro1' -m xmlrunner -o test-reports
対象のパスをちゃんと指定しなきゃですね。これでOKでした。
Jenkins+Python+unittest続き
(2020/05/06:追記)こっちを見たほうが良いです。
続きです。 oyasuminase.hatenablog.com unittestの結果とCoverageをxml形式で出力しJenkins上で結果をいい感じに確認します。
unittest-xml-reportingのインストール
テスト結果をxml形式で出力できるライブラリをインストールします。
$ pip install unittest-xml-reporting
コードの修正。
if __name__ == '__main__': unittest.main(testRunner=xmlrunner.XMLTestRunner(output="./test-reports"))
ついでにテストケースを一箇所失敗するようにしておきました。
coveragreのインストール
coverageの方もいれていきます。
$ pip install coverage
ジョブの設定
- Jenkinsの管理>プラグインの管理より「Cobertura Plugin」を検索してインストール。
- ジョブ>設定>ビルド後の処理に「JUnitテスト結果の集計」を追加。
- ジョブ>設定>ビルド後の処理に「Cobertura カバレッジ・レポートの集計」を追加。
- ジョブ>設定>ビルドスクリプトの修正。
pip install -r requirements.txt coverage run -m xmlrunner -o test-reports coverage xml -o coverage/result.xml
ジョブを実行すると
こんな感じ。