クラシル開発ブログ

クラシル開発ブログ

Carthageで生成したframeworkの管理でRomeを導入してみた

f:id:funzin:20201206110341p:plain

はじめまして、dely開発部のfunzinです。普段はクラシルのiOSアプリ開発を担当しています。

この記事は「dely #1 Advent Calendar 2020」の13日目の記事です。

adventar.org adventar.org

昨日はbababachiさんのコンテナサポートされたLambdaで湯婆婆実装してみたという記事でした。 Lambdaによる湯婆婆実装が丁寧に説明されているので、気になる方はぜひみてみてください!

さっそく本題ですが、この記事ではCarthageで生成したframeworkの管理でRomeを導入したことについてまとめていきます。

Romeとは

Romeは、Carthageで生成したframeworkを様々なストレージで管理することを可能にしてくれるツールです。保存先はローカル、AWSのS3などが指定可能です。

なぜ導入したか

元々クラシルでは、carthage_cacheを使ってCarthageで生成したframeworkをS3に保存していました。また、自前のfastlane actionでライブラリのアップデートも自動化をしていました。 しかし、入社時のキャッチアップとしてライブラリ周りについて確認してみると以下のような課題がでてきました。

  • carthage_cache自体が3年ほど前からメンテナンスがされていない
  • carthage_cacheを利用した自前のライブラリアップデートも1~2年ほどメンテナンスがされていない状態、ライブラリの自動アップデートも毎週CIでfailしていた
  • 自前の自動アップデートが動いていなかったため、必要なタイミングでライブラリを手動アップデートして、carthage_cacheを通してアップロードしていた

利用しているcarthage_cacheが長年メンテナンスされていない、かつ社内でも自動化まわりのメンテナンスをする人がいないという状態の中で、このまま利用するべきなのかという議題がチーム内であがりました。このタイミングでcocoapods-binaryやSwiftPackageMangerに移行をすることも考えましたが、現状の開発フローで低コストに置き換えが可能であったのが今回紹介するRomeでした。

置き換え時の決め手となったのは以下の観点です。

  • carthage_cacheで元々利用していたS3を保存先として利用可能
  • carthage_cacheの利用箇所をRomeに置き換えるのみで対応可能(元々動かなくなっていた自動アップデートActionも含め)

導入手順

Romeの導入手順はREADMEにまとまっているため、こちらを参照してください。 その中でも特徴的な箇所を抜粋して説明していきます。

Romefile

Romeを利用する上でconfigファイルとして、Romefileを定義します。 以下のようなCartfileがある場合、Romefileは次のようになります。

Cartfile

github "ReactiveX/RxSwift"
github "ashleymills/Reachability.swift"
github "realm/realm-cocoa"

Romefile

cache:
  s3Bucket: your-bucket-name
repositoryMap:
- RxSwift:
  - name: RxSwift
  - name: RxTest
  - name: RxAtomic
  - name: RxBlocking
  - name: RxCocoa
  - name: RxRelay
- Reachability.swift:
  - name: Reachability
- realm-cocoa:
  - name: Realm
  - name: RealmSwift

注意しなければいけないこととして、RxSwiftのように複数のframeworkが生成される場合やrealm-cocoaのようにCartfileに記述した名前とframework名が異なる場合は、明示的に名前を指定してあげる必要があります。

Upload

ストレージにframeworkをアップロードする場合、Carthageでframeworkを生成後にrome uploadを実行することで指定のストレージにアップロードされます。

$ carthage update && rome upload

Download

ストレージからframeworkをダウンロードする場合、Cartfile.resolvedに定義してあるバージョンで既にアップロード済みの場合、以下のコマンドからダウンロードができます。

$ rome download

static/dynamic frameworkの指定が可能

Romefileにstatic/dynamicを指定することで、static/dynamic frameworkの管理することが可能です。 例えばAlamofireがstatic frameworkの場合、以下のように記述します。

repositoryMap:
- Alamofire:
  - name: Alamofire
    type: static

注意点として、typeのdefault値はdynamicなため、static frameworkの場合必ずrepositoryMapに記述する必要があるためRomefileの記述量は増えます。

Swiftのバージョンごとに管理可能

Romeではオプションとして--cache-prefixが用意されています。このオプションを利用することでprefixごとにframeworkを管理することが可能になります。

以下のようにprefixを指定することでSwiftのバージョンごとに管理するが可能になります。

--cache-prefix `xcrun swift --version | head -1 | sed 's/.*\((.*)\).*/\1/' | tr -d "()" | tr " " "-"`

クラシルではAWSのS3を利用しているため、実際には以下のように格納されています。 f:id:funzin:20201206105134p:plain

運用例

実際の運用では、Bitriseで最新のXcodeを利用するstackを指定して、carthage updateを実行後にrome uploadを実行するワークフローを平日の毎朝7時に実行しています。これによってSwiftのバージョンごとにframeworkがS3に格納されているため、Xcodeのバージョンを切り替え時にスムーズに移行することができるようになります。

実際にRome運用してみて

当初検討していたcarthage_cacheからRomeへの移行は、機能開発と並行して1~2週間で終えることができました。

f:id:funzin:20201206105657p:plain (9月に移行完了)

移行してすぐに、Xcode12でCarthageが動かない問題に直面しましたが、workaroundなscript対応で現状も問題なく動いています。

また、ライブラリの更新時やXcodeのバージョンを変更時に、rome downloadを実行することでバージョンに対応したframeworkがダウンロードできるため切り替えが楽になりました。

まとめ

Carthageで生成したframeworkをRomeで管理するようにしました。今後もRomeでiOSのライブラリ管理を進めていくというよりは、cocoapods-binary、SwiftPackageManagerに移行するなどの検討も引き続きしていきたいと思います。

明日はall-userさんの「Vue 2で書かれた個人プロジェクトをVue 3に書き換えてみた」です。Vue 3にしてどのような気づきがあるのか楽しみですね!

また、dely ではエンジニアを絶賛募集中です! ご興味あればこちらのリンクからお気軽にエントリーください!

join-us.dely.jp

さらに TechTalk というイベントも行っているので、dely について詳しく知りたい方は是非参加してみてください! bethesun.connpass.com