14
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

くふうカンパニーAdvent Calendar 2018

Day 6

iOSアプリ開発自動化Tips

Last updated at Posted at 2018-12-05

この記事はくふうカンパニー Advent Calendar 2018の6日目の記事です。


手作業を減らせばミスが減り、開発に集中する時間が生まれるため、なるべく自動化したいところです。
そんな思いで行なっている、iOSアプリ開発における自動化のTipsを共有したいと思います。

fastlane

モバイルアプリ開発を便利にしてくれるRuby製のツールです。
自分はプロジェクト直下にGemfileを置いてbundle install --path vendor/bundlerを叩いて(bundlerが入っていない方はgem install bundlerを事前に行なっておく)gemを入れて導入しています。楽です。

ここからは自分が普段行なっている作業を書いていきます。

リリース作業

リリース作業というと

  • バージョンを変える
  • ビルド番号を変える
  • アーカイブする
  • AppStoreConnectにアップロード
  • git関連(commitしたりtag打ったり)

あたりが必須の作業になると思いますが、手作業だと面倒だしミスする可能性もあります。
fastlaneを使うと

  • increment_build_number
  • upload_to_app_store

などactionが用意されており、それをFastfileに書いていくとリリース用のlaneが出来上がります。
以下参考のlane.
bundle exec fastlane release ver:{#ver(例: 1.0.0)}とコマンドを叩くと順に実行されていきます。

  before_all do
    ENV["SLACK_URL"] = "your slack url"
  end

  desc "App Store Connectにアップロード"
  lane :release do |options|
    number = increment_build_number
    # verを指定しなければpatchが上がる
    ver = increment_version_number(
      version_number: options[:ver]
    )
    cocoapods
    carthage(
      use_binaries: false,
      platform: "iOS",
      configuration: "Release",
      cache_builds: true
    )
    build_ios_app(
      scheme: "Release"
    )
    # ENV["APPLE_ID"]をアップロードを行う人は自分の端末に設定しておくこと
    # screenshotsはUITestで使っているためスキップ
    upload_to_app_store(
      force: true,
      skip_metadata: true,
      skip_screenshots: true
    )
    slack(
      message: "アップロード完了"
    )

    message = "ver#{ver}(#{number})をアップロード"
    git_add
    git_commit(
      path: "./*",
      message: message
    )
    add_git_tag(
      tag: "#{ver}"
    )
    push_to_git_remote
    # GITHUB_API_TOKENを環境変数として登録しておくとターミナルで聞かれなくて楽
    create_pull_request(
      repo: "your repository",
      title: message
    )
    sh("say", "-v", "Kyoko", "おめでとうございます。リリース作業が完了しました。")
  end

GithubにPull Requestを送る

git関連の作業は全部fastlaneでやってしまえば良いのでは? という思いつきから作ったのですが意外と便利です。
こういう使い方をfastlaneでやっている人はあまり見かけませんがカスタマイズして使ってみてください。

  desc "developブランチへのpull requestを作る"
  lane :pr do |options|
    message = options[:message]
    git_add
    git_commit(
      path: "./*",
      message: message
    )
    push_to_git_remote
    title = options[:title] || git_branch
    create_pull_request(
      repo: "your repository",
      base: "develop",
      title: title
    )
  end

dsymのダウンロード・アップロード

Appleが推奨しているのでbitcodeを有効にしているのですが、後述するクラッシュ計測ツールの分析がそのままだと行えません。dsymをダウンロードしてアップロードして、というのも面倒なのでlaneを用意しました。

  desc "Crashlyticsにdsymをアップロードする"
  lane :dsyms do
    download_dsyms                  # Download dSYM files from iTC
    upload_symbols_to_crashlytics   # Upload them to Crashlytics
    clean_build_artifacts           # Delete the local dSYM files
  end

参考: https://krausefx.com/blog/download-dsym-symbolication-files-from-itunes-connect-for-bitcode-ios-apps

自動スクリーンショット生成

端末ごとにどんな画面になっているのか見たい場面というのはあります。
だいたい下記の記事を参考にしてもらえると良いです。
bundle exec fastlane snapshotを叩いてある程度時間が経つとSnapfileで設定した端末のスクショが吐き出されていて気持ち良いです。

参考: https://docs.fastlane.tools/getting-started/ios/screenshots/#setting-up-snapshot

LicensePlist

アプリの中で利用しているOSSライブラリを、iOS標準の設定アプリに載せるというのが慣習となっています。
ただ、これを自作するのは結構手間がかかります。
そんな問題を解決しているのがLicensePlistです。
約1300Starを獲得している素晴らしいツールです。(Star数は2018/12/6時点)

導入はとても楽です。
自分はHomebrewで入れているのですがCocoaPodsでも入れられるそうです。
Homebrewでinstallした後にxcodeprojファイルのBuild PhasesからRun Script Phaseを選択してスクリプトを追加するとアプリビルド時に更新のあったライブラリを検知してライブラリ一覧を生成・更新してくれます。

詳しくは作者様のGithubのREADMEをどうぞ。
https://github.com/mono0926/LicensePlist

GAS + SlackでAppStoreConnectのステータスを通知

参考にしたのはこちらのスライドです。
AppStoreConnectのメールが来ないけど審査状況が気になる人、メールは届くのだけれどメールよりもSlackに通知される方が便利だと感じる人がそれなりにいたのでGoogleAppsScriptで書きました。
以下参考。

function onGotMail(subject, appname) {
  try {
    var threads = GmailApp.search(subject);
    var messages = GmailApp.getMessagesForThreads(threads);
    
    for (var i in messages) {
      for (var j in messages[i]) {
        var message = messages[i][j];
        message.markRead();
        var subject = message.getSubject();
        var body = message.getBody();
        
        // Version Numberはリジェクトメールに含まれないのでここでmatch判定
        if (subject.match(/New Message from App Store/)) {
          postSlack("Appleからのメールを確認しましょう。", appname);
        }
        
        var matched = body.match(/Version Number:\s+(\d+.\d+.\d+|\d+.\d+)/);
        if (matched) {
          var username = "ver" + matched[1] + appname;
          if (subject.match(/has completed processing/)) {
            postSlack("申請作業ができるようになりました! TestFlightで確認してから申請作業を行いましょう!", username);
          } else if (subject.match(/Waiting For Review/)) {
            postSlack("審査に出しました。1,2日ほどお待ちください。", username);
          } else if (subject.match(/In Review/)) {
            postSlack("審査中です……", username);
          } else if (subject.match(/Pending Developer Release/)) {
            postSlack("審査が通りました! AppStoreで公開しましょう!", username);
          } else if (subject.match(/Ready for Sale/)) {
            postSlack("公開作業が完了しました! AppStore反映まで1, 2時間ほどお待ちください。", username);
          }
        }
      }
    }
  } catch(error) {
    postSlack("GASでエラーが発生しました。エラーログ用のスプレッドシートを確認してください。", appname);
    logging(JSON.stringify(error));
  }
}

その他外部ツール

AppFollow

アプリのレビューやAppStoreでの検索キーワードの順位を教えてくれるツール。
Slackに流しています。無料プランで結構十分です。

AmazonPinpoint, Firebase

モバイル分析ツール。どの画面を見てどのような動きをしたか計測できます。
Firebaseの方がダッシュボードが見やすく使っている人が多いので情報も豊富ですが、Amazon Pinpointの方はセッションヒートマップが見れたり定期的なプッシュ通知が送れたりします。
どちらも一長一短あるなという印象です。

Crashlytics

クラッシュ解析ツール。ユーザーがアプリでクラッシュしたらこちらに飛んでくるので、バグをより早く減らせるようになりました。
どの画面でなんのイベントを行ったか、端末のOSやアプリバージョンなどがわかるのでそれを元に調査することとなります。

まとめ

いかがでしたでしょうか?
余力があればCIやSwiftlintなども導入してみると良いと思います。
ガンガン自動化して開発に集中しましょう!

参考サイト一覧

14
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?