CIツール第2弾です。
CIってなにとか、第1弾のGithub Actions編は、こちらをご覧下さい。
Kotlin, LiveData, coroutine なんかを使って初めてのAndroidアプリを作る(10)
今回の目標
JenkinsとCircleCIについて、簡単に動かしてみます。
今回は、リリースビルドについては割愛します。
debugビルドとテストまでとします。
※署名はやろうとすると結構大変みたいで
JenkinsはAndroid Signingというプラグインがあるのですが、AndroidStudioで作ったjksファイルはPKCS12じゃないため、今回は使えません。
試してみたい方は、keytool
で作り直してやってみると良いかと思います。
Jenkins
昔なじみのクCIツールです。クラウド型ではありません。
自分で用意した環境で動かす必要があります。でも導入はそんなに難しくないので、やってみましょう。
個人プロジェクトなら、余ってるPCなんかをJenkinsマシンにしちゃうのでもいいかも知れません。お金かからないですからね。ただ、古いPCにすると、スペックが足りなくて、ビルドやテストに時間がかかってしまうかも知れませんが。
今回は、ローカルで動かすJenkinsです。
サーバーを立ててやる方は、まずそちらを用意して環境を作って下さい。
(1) Jenkinsインストール
インストールと言っても難しいことはありません。
1. 自分でインストール
公式サイトからwar
をダウンロードして好きな場所に置いておくパターンです。
これのメリットは、よく分からない設定が後に残らず試せることですね。
サーバーを立ててJenkinsマシンとして常に稼働させたいような場合には、2の手順をやりましょう。
ダウンロードページで、一番下の方にある、**Generic Java package (.war)**と書いてあるところをクリックします。
最新版か、LTS(Long-term Support)のどちらにするかはご自由にどうぞ。私はLTS版を落としました。
ファイルがダウンロードできたら、好きな場所にjenkins.war
を移動します。
ターミナルなどでそのフォルダに移動し、次のコマンドで起動します。
$ java -jar jenkins.war
起動ログが流れて、こんな表示が出ると思います。
*************************************************************
*************************************************************
*************************************************************
Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:
【パスワード文字列】
This may also be found at: /Users/<ユーザー名>/.jenkins/secrets/initialAdminPassword
*************************************************************
*************************************************************
*************************************************************
あとでこのパスワードを使うので、コピーしておきます。
起動したターミナルを閉じてしまうとJenkinsも落ちるので、気をつけましょう。
しばらく待つと、ログが止まるので、そうしたらブラウザでhttp://localhost:8080
にアクセスします。
以下のようなページが表示されるので、先ほどコピーしたパスワード文字列を貼り付け、[Continue]をクリックします。
![]() |
---|
次のページでは、[Install suggested plugins]を選びましょう。Androidのビルドに欠かせないGradleやGitのプラグインなんかはこれでインストールされます。
![]() |
---|
Adminユーザーを任意の情報で作ります。
パスワード忘れるとややこしいので、これだけは忘れないようにしましょう。
![]() |
---|
次のページでは、Jenkins URLを設定しますが、今はローカルで動かすだけなのでそのままにしておきます。
パブリックドメインを持っていてサーバーを立てる人は、ここにそれを入れるのかな?(やってみたことない)
![]() |
---|
[Save and Finish]をクリックし、次のページで、[Start using Jenkins]をクリックすると、下のような感じで起動するはずです。
![]() |
---|
Jenkinsおじさんこんにちは!
2. インストーラーからインストール
公式サイトのダウンロードページで、自分のOSに合ったファイルをダウンロードしてクリックして、あとはインストーラーに任せることも出来ます。
マシンが起動すると自動的に起動してくれる設定をしてくれるので、常時稼働させたいような場合にはこちらが便利です。
ただ、どのユーザー権限で動いているかが分かりづらく、ジョブによってはそのために動かなかったりすることがあります。
なので私は、自分で.war
を好きな場所に置いた上で、launchctl
の登録も自分でやるのが好きです。あるいは 登録しないで必要なときだけ起動コマンド叩いています。
(2) プラグインのインストール
Androidをビルド、テストできるようにプラグインをインストールする必要があります。
- ダッシュボード((起動時に表示されている画面)で、[Jenknsの管理]をクリック
![]() |
---|
- [プラグインの管理]をクリック
![]() |
---|
- [利用可能]タブをクリック
![]() |
---|
- フィルターに[Android]と入力し、表示された中から、以下の2つをチェック
- Android Emulator
- Android Lint
![]() |
---|
- ページ下部にある[ダウンロードして再起動後にインストール]をクリック
![]() |
---|
- ダウンロードが始まったら、[インストール完了後、ジョブがなければJenkinsを再起動する
]をクリック
![]() |
---|
- 再起動するのを待つ
- もし長時間待っても変わらないようならブラウザを再読込してみて下さい。
これで準備が出来ました。
なお、AndroidSDKやJDK、Gitなどもインストールしてパスを通しておくことが必要です。
それらについては、個別に調べて下さい。
※インストールしたプラグインは、削除出来ません。
(3) ジョブを作成する
さっそくジョブを作っていきましょう。
1. ジョブを作成
- ダッシュボードで、[新規ジョブ作成]をクリック
![]() |
---|
- 任意の名称を入力する(必須)
- [フリースタイル・プロジェクトのビルド]を選ぶ
- [OK]をクリック
2. [General]タブの設定
- 説明欄に任意の説明を記入
- [Github project]にチェック
- [Project url]には、GithubプロジェクトのルートページのUrlを貼り付ける
3. [ソースコード管理]タブの設定
- [Git]をチェック
- チェックアウトしてビルドしたいリポジトリのUrlを貼り付ける
- 認証情報を追加する
- [認証情報]のドロップダウンリストから今作成したものを選択
- [ビルドするブランチ]に任意のブランチを指定
4. [ビルド・トリガ]タブの設定
- [SCMをポーリング]をチェック(※任意)
※ サーバーを立てている場合は、[Github hook trigger for GITScm polling]が使えます- [スケジュール]には、クーロン風の時間指定を記入
- 例) 15分おきにチェック
H/15 * * * *
- 例) 15分おきにチェック
- [スケジュール]には、クーロン風の時間指定を記入
5. [ビルド環境]タブ
- [ビルド開始前にワークスペースを削除する]にチェック
- [Run an Android emulator during build]にチェックを入れる
- [Run existing emulator]を選択
-
[AVD name]に、作成済みのエミュレーターの名前を入力
- エミュレーターの名前は、ターミナルなどで以下のように打つと確認できます。
$ android list avd
※作成済みのエミュレーターを使った方が安定します
-
- [Reset emulator state at start-up]にチェック(テスト中にクラッシュしたときなど、次の実行が不安定になるので入れておいた方が良い感覚です)
- [Show emulator window]をチェック
※チェックしないとテストが不安定です
- [Run existing emulator]を選択
6. [ビルド]タブの設定
- [ビルド手順の追加]をクリック
- [シェルの実行]をクリック
- [シェルスクリプト]に、以下の内容を記入
./gradlew assemble
./gradlew lint testDebugUnitTest
./gradlew connectedCheck
7. [ビルド後の処理]タブの設定
-
[ビルド後の処理を追加]をクリック
-
[Publish Android Lint results]を選択
- 設定は特に不要
-
[ビルド後の処理を追加]をクリック
-
[JUnitテスト結果の集計]を選択
- [テスト結果XML]に以下を入力
**/test-results/testDebugUnitTest/*.xml
**/androidTest-results/connected/*.xml
- [テスト結果XML]に以下を入力
-
[ビルド後の処理を追加]をクリック
-
[成果物の保存]をクリック
- [保存するファイル]に以下の内容を入力
**/*.apk
- [保存するファイル]に以下の内容を入力
以上で設定は終わりです。
実行してみましょう。
ビルド実行をクリックすると、ビルドが手動で起こせます。
![]() |
---|
ビルド結果ページです。
![]() |
---|
何度かビルドした後のダッシュボードの表示サンプルです。
![]() |
---|
Github Actionsと違い、テスト結果はページ上で見られます。
なお、エミュレーターは、作成済みのものを指定した方が良いと書きましたが、更に、閉じるときに確認ダイアログが表示されたままになり、エミュレーターが終了しないままになってしまうので、以下の設定もしておいた方が良いです。
- エミュレーターの設定ボタンを押す
クイックブートしなくなりますが、テストの時は初期状態の方が都合が良いので、常にOS再起動からやってもらいます。
(4) Slack通知
プラグインでは上手くいかなかったので(いろいろ仕様が変わったため情報が古い)、Curlコマンドでやります(汗)
1. Incoming Webhookの作成
まずは前回と同じ方法で、Incoming Webhookを作成します。
Webhook URLを秘密テキストとして使うため、コピーしておいて下さい。
2. 秘密テキストの作成
ダッシュボードから、
[認証情報]-[System]-[グローバルドメイン]
とメニューを進み、左側のメニューに表示される[認証情報の追加]から、先ほどコピーした文字列を登録します。
![]() |
---|
3. 秘密テキストのバインド
- ジョブの設定画面で、[ビルド環境]タブを表示
- [秘密テキストや秘密ファイルを使用する]にチェックを入れる
- [追加]をクリック
- 先ほど作成した秘密テキストを選ぶ
- 変数名は任意ですがビルドのシェルスクリプトで使う際に間違えないように
4. curl実行
[ビルド]のシェルスクリプトに直接Curlコマンドを書いていきます。
基本的には以下のような形式でCurlコマンドを実行すればOKです。
POST_DATA=`cat << EOF
payload={
"text": "I am a test message",
"attachments": [
{
"text": "And here’s an attachment!"
}
]
}
EOF`
curl --data-urlencode "${POST_DATA}" ${WEBHOOK_URL}
メッセージ文の設定は、https://api.slack.com/docs/messages/builder などで適宜カスタマイズして下さい。
以上で設定は終わりです。
保存をクリックして、ジョブを実行してみて下さい。
完了したら、通知が来ます。
私にはこれが精一杯のデザイン(苦笑)
出来れば、branch名とかコミットメッセージとか拾いたいですね。
それらは、[ビルドから利用可能な環境変数の一覧]というリンクから探して使えます。
CircleCI
GithubActionsと同様のSaas型で、日本語サポートもあるらしいCircleCIも試してみました。Githubに特化したCIツールのようですね。
でも、Github特化なら、Github Actionsが出来たし、今から使うメリットは・・・なんだろう?(笑)
あ、テスト結果がブラウザから見られる、かなあ。でも失敗したメソッドを見つけるのが大変だったので、どっちもどっちかなあ・・・
とりあえず、見ていきましょう。
(1) 登録
- トップページで、[無料でビルドを開始する]をクリック
- GithubかBitbucketのアカウントでログインをクリック
- 認証を許可する
(2) プロジェクトの設定
- Select an organizationが表示されたら、任意の組織を選んでクリック
- リポジトリを選択
- [Hello World]の部分をクリックして、Androidを選択
![]() |
---|
- [Start Building]をクリック
![]() |
---|
- [Add Manualy]をクリック
![]() |
---|
- [Download config.yml]をクリック
![]() |
---|
- [Start Building]をクリック
これで、いったんプロジェクトが保存されます。
(3) config.yml
を編集する
- プロジェクトルートに
.circleci
というフォルダを作成する - ダウンロードした
config.yml
をそこに置いて開く - ビルドステップを記述する
ビルドステップには、デバッグビルドとUnitTestのみにしました。デバッグapkと、テスト結果をArtifactにアップします。
全部でこうなりました。
version: 2.1
orbs:
android: circleci/android@0.2.0
jobs:
build:
executor: android/android
steps:
- checkout
- run:
command: ./gradlew assembleDebug
- run:
command: ./gradlew testDebugUnitTest
- store_artifacts:
path: app/build/reports
destination: reports
- store_test_results:
path: app/build/test-results
- store_artifacts:
path: app/build/outputs/apk/debug/app-debug.apk
destination: app-debug.apk
とりあえず、GithubActionsと同様、master
ブランチに、ブランチ設定をした設定ファイルがないと意図取りに動かないため、master
ブランチに上げてしまいます。
今回は、特定のブランチのみに絞って行いたいので、このような設定になります。
workflows:
version: 2
build-deploy:
jobs:
- build:
filters:
branches:
only: feature/qiita_10_sub/circleci
上記の設定を、config.yml
の一番下に追加して下さい。
- masterブランチにコミット、push
- 対象ブランチにマージしてpush
これで対象ブランチでワークフローが走るはずです。
(4)パイプライン実行
動き始めた時のPiplineページの表示。
![]() |
---|
完了時の表示。
![]() |
---|
Jobsをクリック。
STEPSタブ
![]() |
---|
TESTSタブ
![]() |
---|
ARTIFACTSタブ
![]() |
---|
ええっ
アーカイブはしてくれないの??
でも一応、index.html
をクリックすればテスト結果が見られるので、ダウンロードする手間が不要な分、マシですかね。
失敗したときのTESTSタブ
![]() |
---|
たくさんエラーがあるとちょっと見づらそうですが、Artifactから確認するしか無いですね。
(5) エミュレーターテストについて
CircleCIでは、エミュレーターでのテストが出来ないため、Firebase TestLab等と連携させないとダメみたいです。
なのでここではやりません。興味ある方はこちらなどを参考に実行してみて下さい。
CircleCI 2.0 での Android エミュレーターのテスト
https://support.circleci.com/hc/ja/articles/360000028928-CircleCI-2-0-%E3%81%A7%E3%81%AE-Android-%E3%82%A8%E3%83%9F%E3%83%A5%E3%83%AC%E3%83%BC%E3%82%BF%E3%83%BC%E3%81%AE%E3%83%86%E3%82%B9%E3%83%88
Test Labについては、いずれ触れてみるつもりです。
(6)その他の設定
1. スキップコメント
[ci skip]
でコミットメッセージを始めると、そのコミットのみを含むpushは、パイプラインが実行されません。
2. Slack通知
やっぱりやりたいですよね、Slack通知。
Incoming WebhookでURLを発行するのは同じです。
- Piplinesのトップページで、[Project Settings]をクリック
![]() |
---|
- [Environment Variables]の[Add Environment Variable]をクリック
![]() |
---|
- 変数名を入力し、 Incoming Webhook Urlを貼る
- [Add Environment Variable]をクリック
-
config.yml
にorbを追加
orbs:
android: circleci/android@0.2.0
slack: circleci/slack@3.4.2
-
config.yml
にstepを追加
- store_artifacts:
path: app/build/outputs/apk/debug/app-debug.apk
destination: app-debug.apk
- slack/status:
success_message: ':circleci-pass: $CIRCLE_BRANCH のビルドが完了しました\n:github_octocat: User:$CIRCLE_USERNAME'
failure_message: ':circleci-fail: $CIRCLE_BRANCH のビルドが失敗しました\n:github_octocat: User:$CIRCLE_USERNAME'
webhook: '${SLACK_WEBHOOK}'
こんな表示です。
成功時
![]() |
---|
失敗時
![]() |
---|
※:circleci-pass:
や:github_octocat:
はSlack側に登録している絵文字です。
3. バッジ
やっぱりやりたいですよね、バッジ表示。
古い情報ばかりでなかなか大変でしたが、結局は公式の英語のページに書いてありました。
# Example for specific branch:
[](https://circleci.com/gh/circleci/circleci-docs/tree/teesloane-patch-5)
これをコピーしてくるのが良いかと思います。
ブランチを自分のパスに直します。私だと、こうなります。
style=svg
だと分かりづらいのでshieldにしました。
[](https://circleci.com/gh/le-kamba/qiita_pedometer/tree/feature%2Fqiita_10_sub%2Fcircleci)
これをREADME.mdに貼った結果です。
まとめ
CIツールでAndroidのアプリのビルド、テスト、結果レポートやapkをアーカイブ出来るようになりました。
個人的には、Github Actionsが使いやすかったですね。Jenkinsも、ビルドマシンとして別マシンが用意できる環境なら大変強力です。
自分が業務で使ったことがあるので慣れているだけかも知れませんが、設定もほとんどGUIで出来るのでやりやすいのではと思います。
CircleCIは、先ほども書いたとおり、GithubActionsが登場した以上、ちょっと今から使うメリットがないような気がします。エミュレーターテストも出来ないし。
テスト結果の見やすさなら、Jenkinsなんですが、これも慣れの問題かも知れません。
今回紹介しなかったBitriseがモバイルアプリ開発に特化しているようなので、CDまで含めて考えるなら、試してみてもいいかも知れないとは思っています。
ここまでのソースは以下のブランチにアップしてあります。
https://github.com/le-kamba/qiita_pedometer/tree/feature/qiita_10_sub/circleci
https://github.com/le-kamba/qiita_pedometer/tree/feature/qiita_10_sub/jenkins
また、masterブランチにymlファイルが入っていないと、masterブランチを無視する設定がきかないので、各ymlファイルだけmasterにもアップしたります。
予告
以前予告した、データをサーバーに保存するのをやります。そのためにはユーザーを一意に特定する必要があるので、ログイン機能が必要になってきます。
ということで、以下のFirebaseの機能を入れていきます。
- 認証(Authentication)
- Databse(Cloud Firestore)
これで、アプリをアンインストールしたり機種変更したりしても、過去データを戻すことが出来ます。
ただ、これはやり方を間違えると、Firebaseにとんでもなく課金されてしまうので、注意が必要です。
参考ページなど
- MACへJenkinsをインストール(インストールの仕方編)
https://qiita.com/t_n/items/22e6c5fd9f2ced3d5fc4 - Jenkins 上で Android アプリのテストを実行する方法 (Gradle 使用)
https://vividcode.hatenablog.com/entry/android-app/jenkins-test - Injecting Secrets into Jenkins Build Jobs
https://support.cloudbees.com/hc/en-us/articles/203802500-Injecting-Secrets-into-Jenkins-Build-Jobs - SlackのIncoming Webhooksを使い倒す
https://qiita.com/ik-fib/items/b4a502d173a22b3947a0 - CircleCIのバッジを追加する
https://circleci.com/docs/ja/2.0/status-badges/ - CircleCI Orbsで、jobの結果をslackに通知する
https://qiita.com/k_bobchin/items/11f0d778de09502de1f3