Jenkins Pluginに頼らずシェルだけでJobを構築する(ios単体テスト編)


概要

Jenkins Pluginを使うとJenkinsのバージョンを上げた時に動作しなくなったり、そもそもGUI設定が面倒だったりで、実はシェルで書いた方が楽じゃん。と思っているのでそうします。
(全く使わないわけではなく、Jenkins2でのお勧めPluginをそのまま入れとくぐらいはやります)
いまどきはfastlaneでビルドしたり、Webサービス使ったりと思います。が、Jenkins + シェルでやります。

シェルで書いておくメリットは、コマンドレベルで何をしているのかが理解できることでしょう。

インストール

jenkins

homebrewで入れてます。

$ brew update
$ brew cask install java
$ brew install jenkins

設定はネットで探せばすぐ出てくるので割愛。

xctool or xcpretty

xcodebuild test に機能を追加したツールです。
homebrewでインストールしておきます。

$ brew install xctool

xctoolを使わない場合は、xcprettyを入れる(logを整形してくれる)

$ brew install xcpretty

想定運用

gitにpushされたらこのJobが動作する想定です。こちらの記事を参照
テストが始まった場合とテストの成否をgithub apiでステータスを更新することでgithub上で状況がわかるようにします。
また、チャット(今回の場合はchatwork)にも配信します。

Job

JenkinsのGUI設定

  • ビルドのパラメーター化でbranchを設定できるようにします。
  • ソースコード管理でgit設定をします。branchはパラメーター名の$branchにします。
  • ビルド環境で、滞留した場合にビルドを中止します。
    タイムアウトの判定 -> 一定の経過時間で6分 -> 失敗扱いにする
  • シェルの実行で以下を書きます。
#!/bin/bash -l

set -eux

BUILD_URL=${BUILD_URL:-"http://<userid>:<password>@<ホスト名>:8080/job/<Job名>"}

githubToken=XXXXXXXXXXXXXXXXXXXX
chatworkToken=XXXXXXXXXXXXXXXXXXXXXXXX

export WORKSPACE
export BUILD_URL
sh ${WORKSPACE}/jenkins/unitTest.sh $githubToken $chatworkToken $branch

BUILD_URL はテストが失敗した場合にgithub上の失敗リンクの遷移先です。入らない場合があったのでデフォルト値を入れています。
また今回はchatworkで結果を通知するのでchatworkのtokenを渡します。

Jenkins外のシェル

#!/bin/bash -l

set -ux
: usage
: $1=githubToken $2=chatworkToken $3=branch

: $1 $2

githubToken=$1
chatworkToken=$2
branch=$3

shellFilePath="${WORKSPACE}/jenkins"

curl -X POST -H "Authorization: token ${githubToken}" https://api.github.com/repos/<ユーザ名>/<レポジトリ名>/statuses/$(git rev-parse HEAD) -d \
"{ \
  \"state\": \"pending\", \
  \"target_url\": \"${BUILD_URL}\", \
  \"description\": \"テスト中です\", \
  \"context\": \"Jenkins\" \
}"

rm -rf Library/Developer/CoreSimulator/Devices


# クリーン処理 
. ${shellFilePath}/clean.sh
clean
install

# 一時的に落ちたことを検知させるため
set +e

xctool -workspace ${WORKSPACE}/<プロジェクト名>.xcworkspace \
-scheme <プロダクト名> \
-configuration Debug-Mock \
-sdk iphonesimulator9.3 \
test  -only <プロダクト名>Tests

# xctoolを使わない場合
# set -o pipefail && xcodebuild -scheme "<プロダクト名>" -workspace "<ワークスペース>.xcworkspace" -configuration "Debug-Mock" -destination "name=iPhone 6s Plus,OS=9.3" -destination-timeout "240" build test | xcpretty --color --test

if [ $? -ne 0 ]; then

    curl -X POST -H "Authorization: token ${githubToken}" https://api.github.com/repos/<ユーザ名>/<レポジトリ名>/statuses/$(git rev-parse HEAD) -d \
"{ \
  \"state\": \"failure\", \
  \"target_url\": \"${BUILD_URL}\", \
  \"description\": \"テスト失敗してます\", \
  \"context\": \"Jenkins\" \
}"

    curl -X POST -H "X-ChatWorkToken: ${chatworkToken}" \
    -d "body=${branch}にPushしてテストが落ちてます" "https://api.chatwork.com/v1/rooms/<ルームID>/messages"

    exit 1

else 

    curl -X POST -H "Authorization: token ${githubToken}" https://api.github.com/repos/<ユーザ名>/<レポジトリ名>/statuses/$(git rev-parse HEAD) -d \
"{ \
  \"state\": \"success\", \
  \"target_url\": \"${BUILD_URL}\", \
  \"description\": \"テスト成功!!\", \
  \"context\": \"Jenkins\" \
}"

fi