Jenkins、GitHub Actions、Azure DevOpsによるモバイルCI/CD
モバイルアプリケーション向けのCI/CDパイプラインを構築する際の主な課題を取り上げます。また、よく使われるモバイルCI/CDツールで、AndroidとiOSのアプリケーション向けのCI/CDパイプラインをどう構築できるかの例も紹介します。
セキュリティスキャンをCI/CDパイプラインに組み込んだチームの85%は、パッチのSLOを守り、脆弱性をより速く修正し、より頻繁にコードを変更し、自社のコードベースへの理解が深まったと述べています。
本記事では、モバイルアプリケーション向けのCI/CDパイプラインを構築する際の主な課題を取り上げます。また、よく使われるモバイルCI/CDツールで、AndroidとiOSのアプリケーション向けの継続的インテグレーションのパイプラインをどう構築できるかの例も紹介します。
セキュリティチェックをCI/CDパイプラインに組み込む前に、パイプラインが正しく構築され安定していること、そして何かが壊れた場合に修正できる適切な可観測性を備えていることを確認しなければなりません。
モバイルアプリケーションにCI/CDを導入する際によく見られる課題をいくつか紹介します。
-
CI/CDの専門知識の不足:
ほとんどのDevOpsソリューションでは、自動化されたワークフローやプロセスを適切にセットアップ・カスタマイズ・維持するために、高度なCI/CDの専門知識が必要です。多くのアプリケーション開発者は、このスキルセットを身につけるのに時間と経験を要します。 -
所有権の不明確さ:
CI/CDの構築は一度きりの作業ではありません。人間が書くあらゆるコードと同様に、それは失敗したり、壊れたり、予期しない挙動をしたりします。そのため、CI/CDパイプラインの管理や実装が不十分だと、失敗の原因をすぐに特定するのが面倒な作業になりがちです。その結果、コードの誤りを修正すべき担当チームへ引き継ぐのも難しくなります。
-
Dev・QA環境のみに限定し、Prod環境と比較しないこと:
モバイルアプリケーションは通常、端末にインストールされるクライアントバイナリと、API経由で通信するバックエンドで構成されます。 CI/CDパイプラインには、テストを実行するための異なる設定や環境がある場合があります。よくある誤りの一つは、Dev環境とQA環境を使ってテストし、Prod環境との違いを軽視してしまうことです。 その結果、本番環境のコードはテストされないままとなり、誤り、セキュリティ上の問題、予期しないエラーを抱えることがあります。
-
動的解析の軽視:
多くの企業が、静的解析のみでCIパイプラインを構築しています。これは主に、アプリケーションの動的解析を自動化する際に直面する困難のためです。 静的解析は、バイナリやソースコードを解析して、既知の脆弱性のパターンを見つけることを目的とします。しかし、静的解析は、軽微なソフトウェアの不具合や悪用されない欠陥について、あまりに多くのアラートを生成することで知られています。 だからこそ、OWASPの標準は、静的解析と動的解析の両方を実装することを推奨しています。動的解析は、アプリケーションを実行しながらセキュリティ脆弱性を検出するよう設計されています。アプリケーションで使われる範囲のみをカバーし、特定された問題について高い確度を提供します。
-
UI自動化の実行の難しさ:
CI/CDパイプラインにおいて、UIの操作を自動化することは、テストカバレッジを高め、テストのスケーラビリティと品質を確保するための重要なステップです。よくある課題は、すべてのUIの操作を自動化し、それらが異なるアプリケーションのバージョン、OSのバージョン、複数の端末を通じて安定していることを確保することです。
-
CI/CDベンダーの隠れた制約:
モバイルアプリケーション向けに完全に自動化されたCI/CDパイプラインを持つには、モバイルアプリケーションの厳格なオペレーティングシステムの要件、厳密なコード署名、頻繁に更新されるSDKやツール、端末でのテスト、アプリストアへの申請に適合する必要があります。 そのため、自社のニーズをカバーし、実装と保守を容易にするには、CI/CDベンダーの選択が不可欠です。
では、モバイルアプリケーション(AndroidとiOS)のビルドを、よく使われるCI/CDプラットフォームのいくつかにどう追加できるかを見ていきましょう。
Jenkinsを使ったAndroidアプリケーションの継続的インテグレーション
JenkinsでソースコードからAndroidのAPKを生成する方法を学びます。すでにJenkinsをインストール済みであることを前提とします。
-
ステップ1:Java JDKのインストール:
ターミナルで次を実行します。
sudo apt install default-jdk
-
ステップ2:Android SDKのインストール:
Androidのダウンロードページにアクセスし、Command line tools only>Linuxの表に記載されているリンクを取得します。何もダウンロードしないでください。リンクをコピーするだけです。
# here you paste the link you grabbed in the developer.android.com site
sudo -iu jenkins wget https://dl.google.com/android/repository/commandlinetools-linux-8512546_latest.zip
sudo -iu jenkins mkdir android-sdk
sudo -iu jenkins unzip commandlinetools-linux-8512546_latest.zip -d android-sdk
# this step is important to accept the Android SDK license
yes |sudo -iu jenkins android-sdk/tools/bin/sdkmanager --licenses
-
ステップ3:Gradleプラグインのインストール:

.1 Jenkinsを開きます:Manage Jenkins >> Manage Plugins >> Available
.2 Gradleを検索します

.3 Installをクリックします

-
ステップ4 Jenkinsの設定:
.1 Jenkinsを開きます:Manage Jenkins >> Configure System >> Global properties >> Environment variables

.2 変数を追加します:
# depending on your local paths
ANDROID_HOME : /var/lib/jenkins/android-sdk
JAVA_HOME : /usr/lib/jvm/java-11-openjdk-amd64

-
ステップ5:Androidのビルドジョブの作成:
.1 Jenkinsを開きます:New Item
.2 ジョブ名を入力します
.3 Freestyle projectを選び、OKを押します
.4 Source Code Managementに移動し、Gitをチェックして、次を入力します:
-
Repository URL:自分のリポジトリへのGit URL。このURLはGitHubから取得します。git@github.com:{username}/{repo}.gitの形式になるはずです
-
Credentials:自分の認証情報を選択するか、credentialsメニューで新しいものを作成します。
-
Branches to build:branch_name
.5 Buildセクションで、Invoke Gradle scriptを選択します

.8 タスクの名前を入力します
.9 Post-build Actionsで、Archive artifactsに**/*.apkを入力します
.10 Saveを押します
-
ステップ6:ビルドの開始:
ジョブのダッシュボードからBuild Nowをクリックすると、ジョブが実行されます。 ビルドに成功すると、プロジェクト情報に生成されたAndroidアプリが表示されます。

Jenkinsを使ったiOSアプリケーションの継続的インテグレーション
-
ステップ1:XCodeプラグイン付きのJenkinsのインストール(MacOSが必要):
.1 Jenkinsを開きます:Manage Jenkins >> Manage Plugins >> Available
.2 Xcode integrationを検索します

.3 Installをクリックします
-
ステップ2:JenkinsのGlobal configurationからDevelopment teamを作成:
.1 Jenkinsを開きます:Manage Jenkins >> Configure System
.2 Xcode builderセクションに移動します
.3 Apple Development Teamsセクションに移動し、Addボタンをクリックします
.4 Team NameとDevelopment Team IDの2つのフィールドを入力します

.5 Keychainセクションを追加します
.6 Keychain NameとKeychain passwordの値を入力します(キーチェーンのパスはすでに入力されているはずです)

.7 ApplyしてSaveします
-
ステップ3:リポジトリをクローンするようJenkinsジョブを設定:
.1 Jenkinsワークスペース内のプロジェクトパスに移動します(/Users/Shared/Jenkins/Home/workspace)
.2 Xcodeを使ってプロジェクトを開きます
.3 XcodeのGeneralタブで、Provisioning profileとすべての情報が正しいことを確認します
.4 すべての情報が正しいことを確かめるため、Xcodeを使ってプロジェクトをビルドしてみてもかまいません
.5 Automatically manage signingのチェックボックスはオフにしておくべきです
.6 Jenkinsの設定で使用するため、Team NameとBundle Identifierを控えておきます
-
ステップ5:Jenkinsでのビルドの設定:
.1 Jenkinsを開き、自分のプロジェクトに移動して、configureをクリックします
.2 Buildセクションで、buildステップのボタンをクリックし、Xcodeオプションを選択します。Xcode関連のフィールドが追加されます。
.3 General build settingsで、Settingsボタンをクリックします
.4 先ほどJenkinsのGlobal Configurationに追加したDevelopment Teamを選択します
.5 XcodeのSchema Fileを入力します:
.6 Pack application, build and sign .ipa?オプションを選択します。

.7 .ipaファイルを生成するための.appのエクスポート方法。‘development’、‘ad-hoc’、‘enterprise’、‘app-store'のいずれかにすべきです。
.8 .ipa filename pattern:IPAファイル名のパターン。この文字列には${VERSION}と${BUILD_DATE}(yyyy.MM.dd)を使えます。
.9 Code signing & OS X keychainオプションに移動します
.10 Manual signingを選択します
.11 Bundle IDとProvisioning profile UUIDを入力します(これはprovisioning profileの.mobileprovisionファイルから見つけられます)
.12 Unlock Keychainを選択します
.13 ドロップダウンメニューから、先ほど作成したKeychainの値を選択します
.14 Advanced Xcode buildオプションのセクションに移動します
.15 Xcode Workspace Fileのフィールドを入力します:Xcode Project Directory:$WORKSPACE
.16 ApplyとSaveを押します
-
ステップ6:ビルドの開始:
ジョブのダッシュボードからBuild Nowをクリックして、ジョブの実行を確認します。
ビルドに成功すると、プロジェクト情報に生成されたIpaアプリが表示されます。
GitHub Actionsを使ったAndroidアプリケーションの継続的インテグレーション
GitHub Actionsが提供するランナーを使うと、Linux、Mac、Windowsでビルドを実行できます。
すべてのランナーにはJavaとAndroidがすでにインストール・設定されています(プリインストールされているソフトウェアの一覧はかなり長いです)。 ワーカーは、追加のセットアップなしに、ほとんどのAndroidプロジェクトをそのままビルドできます。
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout the code
uses: actions/checkout@v2
- name: Build the app
run: ./gradlew build
GitHub Actionsを使ったiOSアプリケーションの継続的インテグレーション
IPAのビルドには、yukiarrr/ios-build-actionタスクを使います。このアクションはiOSプロジェクトをビルドし、IPAファイルにエクスポートできます。
完全なドキュメントはGitHubリポジトリで確認できます。
name: Build and sign Ipa file
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- name: Build and export iOS
uses: yukiarrr/ios-build-action@v1.5.0
with:
project-path:
workspace-path: ".xcworkspace path"
scheme: "project name"
export-method: "Choose app-store, ad-hoc, package, enterprise, development"
configuration: "Choose Debug or Release"
output-path: artifacts/output.ipa
p12-base64: ${{ secrets.P12_BASE64 }}
certificate-password: ${{ secrets.P12_PASSWORD }}
mobileprovision-base64: ${{ secrets.ADHOC_MOBILEPROVISION_BASE64 }}
code-signing-identity: ${{ secrets.CODE_SIGNING_IDENTITY }}
team-id: ${{ secrets.TEAM_ID }}
Azure DevOpsを使ったAndroidアプリケーションの継続的インテグレーション
-
ステップ1:パイプラインの準備:

.1 自分のプロジェクトを開き、左パネルのPipelinesセクションに移動します
.2 Create Pipelineをクリックします
.3 自分のGitリポジトリを選択します
空のYamlパイプラインが生成されます。次に、Gradleを使ってバイナリファイルをビルドする必要があります。
-
ステップ2:Gradleタスクを使ったApkファイルのビルド:
.1 show assistantをクリックします

.2 Gradleを検索します

.3 JUnit Test Resultsセクションの下にあるPublish to Azure Pipelineをオフにできます
.4 ファイルをビルドするタスク名を設定します
.5 Addボタンをクリックします
.6 Saveをクリックして、CIパイプラインを保存します
ファイルに対してほかのジョブを実行したい場合は、‘Copy files’と‘Publish build artifacts’のタスクを追加して、生成されたファイルをパイプラインに取り込むこともできます。
Azure DevOpsを使ったiOSアプリケーションの継続的インテグレーション
-
ステップ1:パイプラインの準備:
.1 自分のプロジェクトを開き、左パネルのPipelinesセクションに移動します
.2 Create Pipelineをクリックします
.3 自分のGitリポジトリを選択します
空のYamlパイプラインが生成されます。次に、Gradleを使ってバイナリファイルをビルドする必要があります。
-
ステップ2:Gradleタスクを使ったApkファイルのビルド:
Ipaファイルに署名するには、provisioning profileとiOSの証明書が必要です。
これらをパイプラインにアップロードするために、Secure filesセクションを使います。
.1 pipelines -> Library -> Secure filesに移動します

.2 provisionファイルをアップロードします。ここでは、これをmy_provision_profile_ostorlabと呼ぶことにします
.3 certificate public key(.p12)をエクスポートしてアップロードします。これをmy_certificate.p12と呼ぶことにします
.4 自分のパイプラインに戻り、3つの変数を追加します:
p12FileName = my_certificate.p12
p12Password = my_certificate_password
provisioningProfile = my_provision_profile_ostorlab

.5 show assistantをクリックします
.6 install apple provisioningを検索します

.7 provProfileSecureFileに変数$(provisioningProfile)を入力します
.8 Addをクリックします
.9 show assistantをクリックします
.10 install apple certificateを検索します

.11 ファイル名とパスワードに変数の内容を入力します
.12 Addをクリックします
-
ステップ3:Ipaファイルのビルドと署名:
.ipaファイルをビルドするには、vmImageとしてmacOSを使う必要があります。
.1 build configurationを変数として追加する必要があります。値はDebugまたはReleaseに設定できます。
.2 SDK変数を追加する必要があります。macOSのTerminalアプリケーションからxcodebuild -showsdksを実行して、有効なSDKの一覧を表示します。
.3 show assistantをクリックします
.4 Xcodeを検索します

.5 Signing styleで、Manual signingを選択します
.6 Signing identityに値$(APPLE_CERTIFICATE_SIGNING_IDENTITY)を入力します。この変数は、先ほど追加した‘Install Apple Certificate’に対応します
.7 Provisioning profile UUIDに、Install Apple Provisioning Profileタスクで定義された値$(APPLE_PROV_PROFILE_UUID)を入力します。
.8 Addをクリックします
.9 saveをクリックして、CIパイプラインを保存します。
初めてビルドを実行すると失敗し、変数とsecure filesへのアクセス許可を求められます。Authorize resourcesをクリックして、ビルドを再実行してください。
本記事では、CI/CDパイプラインを構築する際のいくつかの課題を見てきました。また、よく使われるCIプラットフォームでのAPKとIPAのモバイルアプリケーションのビルドについても論じました。 CIの実装は、レビュープロセスの後にデプロイを自動化するCDパイプラインで仕上げるべきです。 モバイルアプリケーションの領域には、アプリケーションを開発・ビルドするための複数のフレームワークがあるため、CIの実装はフレームワークのツールによって異なり得ます。
次の記事では、flutterフレームワークと、それらのCI/CDプラットフォームでビルドをどう自動化できるかを取り上げます。