tmytのらくがき

個人の日記レベルです

Azure DevOpsとAppCenterでCI/CDといわれるやつをやった

Azure DevOpsとAppCenterを使ってCIできるようにした

やったこと

  • Azure DevOps(旧VSTS)でソース管理とビルドパイプラインの面倒を見る。AppCenterでテスターにバイナリを配布する。
  • AndroidiOS両方やる
  • ビルドマシンは自宅にmacOSな物理マシンを設置する

セットアップ

セットアップ自体は簡単。どれもすぐできるので省略します。

  • Android Studioをセットアップする
  • XCodeをセットアップする
  • Azure DevOpsのビルドエージェントをセットアップする

困ったこと

  • iOSのビルドがうまくいかなくて泣いた

iOSはProvisioning Profileとp12を設定しているのに署名がうまくいかなくて泣いた。 結局、VSTSのビルドタスクの実装を読んで、ビルド前にMagicを施すことでなぜかビルドできるようになった。

逆にAndroidはデフォルトでなにも困っていないので特に触れません。

泣いた結果のビルドパイプライン

Pipelineのところ。Schemeをちゃんと書く。

f:id:tmyt:20181126004828p:plain

なんかよくわからない文字列をpbxprojに書き込む

echo "/* tweaks
ProvisioningStyle = Manual;
*/"  >> ”プロジェクト名”.xcodeproj/project.pbxproj

DerivedDataのせいでビルドにこけることがあるので毎回消す

echo Cleaning DerivedData...
rm -rf /Users/<ユーザー名>/Library/Developer/Xcode/DerivedData/<プロジェクト名>-*

XCode Buildはこれでいいらしい。最初Manual署名とかいろいろやってみたけど、結局署名がうまくいかなかったりでよくわからない。 最初の謎の文字列をpbxprojに書き込むとビルドタスクがいい感じに動く。もうさっぱりわからない。

f:id:tmyt:20181126005134p:plain

ついでにGitのChangeLogをBuild artifactに入れておく。

echo "$(Build.SourceVersionMessage)" > $(build.artifactstagingdirectory)/CHANGELOG

結局ビルドタスクの実装に依存した謎の文字列を無理やり押し込んで解決したけど、こんなことしなくても通るはず…謎。もう無理。

リリースする

デフォルトでビルド後にAppCenterに投げるようなタスクが書かれてる。けどせっかく(?)なので、Releaseを使った。

トリガーに、CIビルドを設定。タスクにはAppCenterにDeployするタスクを設定しただけとても簡単。

Release notes fileに、ビルド時に生成したCHANGELOGを指定した。

f:id:tmyt:20181126010304p:plain

Gitのログを出力したのはここで使うためでした。

AppCenterのIn-app Updateを使う準備をする

In-app Updateを使うにはちゃんとバージョン番号が上がっていないとだめ。

  • iOSの場合CFBundleVersionが現在のバイナリより新しい場合
  • Androidの場合versionCodeが現在のバイナリより新しい場合

それぞれの場合に、アップデート通知が出る。なのでいい感じにバージョンを更新しないといけない。

調べるとVSTSのビルドタスクでできるよーとか書いてあったりいろいろ試したけどめんどくさくなった*1。 ので、macなんだろsedでいいだろsedで。という感じで解決しました。

Android

Androidはbuild.gradleのversionCode 1ってなってるところをsedで$(Build.BuildId)に置換するだけ。簡単

sed -i -e "s/versionCode 1/versionCode $(Build.BuildId)/" app/build.gradle

iOS

iOSはもっと簡単でmacなのでplistを編集するCLIツールがあるのでそれを使う。CFBundleVersionを文字列で$(Build.BuildId)に書き換える。こちらも簡単

plutil -replace 'CFBundleVersion' -string "$(Build.BuildId)" <プロジェクト名>/Info.plist

アプリにIn-app Updatesをセットアップする

実際にIn-app Updatesを有効にするには、アプリ側にライブラリをインストールして少しだけコードを書き足す必要があります。 ただこれも、使い方はdocs.comを読むと書いてます。

docs.microsoft.com

docs.com読めって言えばそれだけの話なんですが、とりあえず簡単に紹介だけしておきます。といってもdocs.comに書いてることと変わりません。

Android

Androidは簡単。Gradleに依存を書く。

dependencies {
   def appCenterSdkVersion = '1.10.0'
   implementation "com.microsoft.appcenter:appcenter-distribute:${appCenterSdkVersion}"
}

importを書いて、MainActivityのonCreateあたりに次のコードを埋める。

AppCenter.start(getApplication(), "{Your App Secret}", Distribute.class);

おわり。簡単。

iOS

iOSもだいたい同じ。

Cocoapodsからライブラリを入れる。

pod 'AppCenter/Distribute'

importを書いて、didFinishLaunchingWithOptionsあたりに次のコードを埋める。

MSAppCenter.start("{Your App Secret}", withServices: [MSDistribute.self])

ただ、iOSはInfo.plistをちゃんと書かないと動かない。 ドキュメントにもちゃんと書けよ。って書いてあるけど見落とすと動かなくて悩むのでちゃんと書きましょう*2

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>appcenter-${APP_SECRET}</string>
        </array>
    </dict>
</array>

おわり

*1:PowerShellタスクだからmacなので動かないとかあって嫌になった

*2:1時間くらい悩んだ