読者です 読者をやめる 読者になる 読者になる

リリース自動化だけじゃないfastlane活用方法

iOS アドベントカレンダー

この記事はトレタ Advent Calendar 2016 1日目の記事になります。

こんにちは、昨日に引き続き開発部の堀見です。

今年はトレタ初のエンジニアアドベントカレンダーをやることになりました!
「トレタ Advent Calendar 2016」やります - トレタ開発者ブログ

弊社はまだまだ小さい組織で少人数なので、言い出した当初は「半分埋まれば良いか〜」とか言っていましたが、なんと・・・全日程埋まっています!!!!🎉🎉🎉

弊社のデザイナー・サーバサイド・インフラ・フロント・iOSのエンジニアが勢揃いしてますので、ぜひトレタ Advent Calendar 2016 の購読ボタンを押してウォッチしてください🙏

ということで、初日は筆者からiOSネタを投下します。

背景

最近多くのiOS開発現場ではfastlaneでリリース作業が自動化されていると思います。トレタでも去年からfastlaneを導入済みで、ブランチをmasterにマージするとCIでアーカイブ作成・iTunesConnectにバイナリをアップできるようになっています。これによりリリース作業の負担軽減や、作業の属人性が減らせました。

しかし、日々のiOS開発ではまだまだ作業効率化の余地があると思います。今回は筆者がよく非エンジニア等のチームメンバーから依頼される、ちょっとした作業をfastlaneを使って自動化してみました。おそらくiOSエンジニアであればお願いされた経験があるものが多いと思います。

Provisioning ProfileにUDIDを追加する

弊社ではベータ版アプリを社員にはIn-house、社外の協力会社様向けにはAd-Hocビルドで配布しています。そのため社外でテストしたい端末が増えると、都度UDIDをDeveloper Portalに追加するという作業が発生します。

一瞬で終わる作業ですが、大抵ログインセッションが切れていてポータルに再ログイン、ポータルTOPからDevice追加画面に進み(ページ遷移が多い!)、デバイス名とUDIDを入力してようやく終了。・・・と思いきや、provisioningにデバイスIDを追加しないと意味がありません。というか、これをよく忘れてビルドをアップし、インストールできませんと言われて気づくことが割とあります...。意外と時間がかかってしまう作業です。

そこで以下のようなlaneを用意し、コマンド一発でデバイス追加とprovisioningの更新を行えるようにしました。

desc 'Usage: fastlane add_device name:デバイス名 udid:デバイスのUDID'
lane :add_device do |options|
  if options[:name] && options[:udid]
    register_devices(devices: {options[:name]: options[:udid]})
    sigh(force: true)
  else
    UI.error "Usage: fastlane add_device name:'New device name' udid:'UDID'"
  end
end

ブラウザをポチポチ操作していれば数分はかかりますが、これなら10秒程度で終わります。デバイス追加をお願いする際は、name:デバイス名 udid:デバイスのUDIDの形式で送ってもらうようお願いしておけば、依頼が来て即ターミナルにコピペ・コマンドを叩いて終了です。

ベータ配布済みのアプリのProvisioningを新しいものに差し替えたい

ベータ版配布サービスで既に配布しているAd-Hocアプリに、利用できるユーザを追加したいというケースもよくあります。前述のデバイス追加とProvisioningの更新をやっていれば新しいビルドをアップするだけで解決するんですが、長いビルド時間を待つのは億劫だし、同じビルド番号のアプリが配布サイト上に重複していくのも嫌な感じです。なので、普段は既にアップしているipaを手元にダウンロードして、Provisioningを入れ替え、アップし直すという地味な作業をやっています。

これもfastlaneからコマンド一発で行えるようにしました。

まずベータ配布サービスからアップ済みのipaをダウンロードしてきます。弊社ではHockeyAppを使っているので、download_hockey_ipaというActionを作りました。ビルド番号などを指定したらAPI経由でipaをダウンロードしてくるシンプルなものですが、地味に行数が長いので詳しくはGistで。

download_hockey_ipa.rb

ダウンロードが完了したらsighで最新のProvisioningをダウンロードし、resignでipaの中身を差し替え、再度hockeyでipaをアップします。幸いダウンロード以降はfastlaneに含まれているアクションを組み合わせて完結しました。

desc 'Usage: fastlane update_hockey_ipa_profile build_number:1234'
lane :update_hockey_ipa_profile do |options|

  tmp_download_path = '/tmp/resign.ipa'
    
  download_hockey_ipa(
    api_token: ENV["FL_HOCKEY_API_TOKEN"],
    build_number: options[:build_number],
    public_identifier: 'Hockeyアプリのidentifier',
    ipa_path: tmp_download_path
  )

  sigh(username: "dev@example.com", development: true, app_identifier: "*")
  resign(signing_identity: ENV["DEVELOPMENT_SIGNING"], ipa: tmp_download_path)
    
  hockey(ipa: tmp_download_path, strategy: 'replace')
end

hockeyアクションはデフォルトだと新規のビルドとしてipaをアップしますが、strategy:'replace'オプションを加えておくとHockey上にある同じ番号のビルドを置き換えてくれるようです。

最新のLocalizationを適用した確認用アプリを用意する

弊社のアプリは英語圏にもサービス展開しており、通常の機能開発と並行してローカライズも行っています。言語リソースはCrowdinで管理していて、翻訳が完了したらxliff形式で訳語データをダウンロード、コードにimportするという流れです。

これもまたブラウザからファイルを取ってきてimportして...とやっていると地味に時間がかかるので、コマンド一発で解決します。

まずはCrowdinから言語リソースをダウンロードしてきます。OneSkyなどはfastlane-plugin-oneskyを使えば済むようですが、Crowdinは無かったので自前でActionを用意。こちらも長いのでGistを参照↓

download_crowdin_resource.rb

続いてCrowdinからダウンロードしたxliffをプロジェクトにインポートします。xcodebuildコマンドをシェルで叩いてもいいんですが、fastlane-plugin-localizationを使うと簡潔に書けそうなのでこちらを使います。

最終的なlaneはこんな感じ。import処理はprivate laneに書いて、betaビルドのlaneから必要に応じて呼び出し、Hockeyにバイナリアップするようにしています。

private lane :update_localization do |options|
  tmp_localization_path = '/tmp/localization.xliff'
  download_crowdin_resource(
    api_token: ENV["CROWDIN_API_TOKEN"],
    download_path: tmp_localization_path,
    project_identifier: 'toreta',
    language: options[:language],
    file_to_download: 'ipad.xliff'
  )
  import_localizations(source_path: tmp_localization_path, project: 'Toreta.xcodeproj')
end

desc 'Usage: fastlane beta update_localization:true language:en'
lane :beta do |options|
    
  if options[:update_localization]
    update_localization(language: options[:language])
  end
    
  sigh(username: "dev@example.com", app_identifier: "*")
  gym
  hockey
end

まとめ

fastlaneを使って日々の作業を地味に自動化する方法を紹介しました。 一つ一つは些細な作業ですが、意外と自分の時間が削られてしまうし、「後でいいや」と後回しにすればチームメンバーを待たせてしまいます。こうした小さな効率化もエンジニアの責務としてやるべきだなと思いました。

fastlaneはもはやリリース自動化ツールではなく、アプリエンジニアが日々こなすあらゆる仕事の量を軽減し、生産性を高めてくれるツールになっている印象です。fastlane/AvailablePluginsにもあるように有志で開発されたプラグインもどんどん充実してきているので、今後さらなる効率化が図れそうです。


明日は サーバサイドエンジニアの 芹沢PageRankについて調べてみたです。お楽しみに!

© Toreta, Inc.

Powered by Hatena Blog