技術部のid:gfxです。iOSアプリ開発に欠かせないパッケージ管理ツールといえばCocoaPodsですが、これはPrivate Podsを作って社内ライブラリ専用のSpecs(private Specs)を管理することができます。
private SpecsがなくてもGit URLを指定することで社内用podspecを開発・管理することはできますが、private SpecsがあるとURL指定を簡略化したり依存関係の解決が簡単になるというメリットがあります。クックパッドでもすでに十数個のprivate podspecが登録されており、CookpadUIやAPI clientなどはpodspecとしてprivate Specsに登録されています。
そこで本エントリでは、Specsを運用している間に起きた問題などを共有します。なお、CocoaPodsのバージョンは v0.35.0.rc2 です。v0.34.xだとGit SSH URLを使う際にトラブルがあったのでRC版を使っていますが、インストールの際に --pre
が必要なので注意してください。また、private Specsの仕様はまだ流動的なので、実際に運用に入る際は仕様をご確認ください。
概要
- podspecでGit SSH URLを参照しているときは
pod lib lint
に--only-errors
をつける pod repo push
には--allow-warnings
をつける- podspecでprivate Specsに依存する場合、
pod lib lint
には `--sources=...'でprivate SpecsのURLを与える
詳細
まずCocoaPods Specsの実体ですが、これはただの特別なパス構造を持ったgit repositoryです。仕様に従ったgit repositoryを用意すれば、検索こそできませんがPodfileでデフォルトのCocoaPods/Specs同様に使えます。
なお、本エントリでは以下の3つのgit repositoryを使います。
- Specs https://github.com/gfx/PrivateSpecsExample
- podspec example: https://github.com/gfx/ExamplePod
- podspec example (private podspecに依存): https://github.com/gfx/ExamplePod2
また、以下のようにprivate Specsを登録しておきます。PrivateSpecsExampleは空でかまいません。git repositoryの構成についてはpodコマンドがすべて面倒をみてくれるので、気にする必要がないのです。
$ pod repo add myspecs git@github.com:gfx/PrivateSpecsExample.git
podspecを作る
それでは、podspecをひとつ作り、private Specsに登録してみましょう。podspecのリポジトリはExamplePodです。
podspecは pod spec create ExamplePod
で作り、生成されたExamplePodを修正します。 s.source
はGitHub Enterpriseを想定しているのでGit SSH URLで指定しています。
- s.source = { :git => "http://EXAMPLE/ExamplePod.git", :tag => "0.0.1" }+ s.source = { :git => "git@github.com:gfx/ExamplePod.git", :tag => "0.0.1" }
ここでポイントその一ですが、pod lib lint
は Git SSH URLだとfirewall越しにアクセスできない可能性があるというwarningsを出します 。そして、 pod lib lintはデフォルトでwarningsを致命的エラー扱いにします。errorのみを致命的エラーにするには、 --only-errors
オプションを指定しなければいけません。
このオプションのもとでの結果は以下のようになります。warningsは出ていますがvalidationはパスしています。
$ pod lib lint --only-errors -> ExamplePod (0.0.1) - WARN | [source] Git SSH URLs will NOT work for people behind firewalls configured to only allow HTTP, therefore HTTPS is preferred. ExamplePod passed validation.
なお、ここではやむを得ずwarningsを無視していますが、基本的にはwarningsを無視するべきではありません。他のwarningsが出ていないかの確認はするほうがいいでしょう。
podspecをpushする
次に、これをprivate Specsにpushしてみます。今回は同じrepositoryを使いますが、実際には社内のSpecsに対して行います。この時、前述の理由でGit SSH URLだとspec validationに失敗するのですが、このとき必要なオプションは--allow-warnings
です。これが第二のポイントです。
# tagを打ってpodspecをpushする $ git tag 0.0.1 && git push origin 0.0.1 $ pod repo push --allow-warnings myspecs *.podspec
これでpodspecをprivate Specsに登録できました。あとはこのpodspecを使いたいプロジェクトのPodfileで以下のように source
を指定すれば、そこに登録されたpodspecを使うことができます。
# Podfile source 'git@github.com:gfx/PrivateSpecsExample.git' source 'https://github.com/CocoaPods/Specs.git' pod 'ExamplePod'
private podspecに依存したpodspecを作る
さて、このprivate podspecに更に依存したpodspecを作ってみます。内容はExamplePodと同じのExamplePod2をつくり、podspecの名前やパスを書き換えます。また、 s.dependency 'ExamplePod'
を加えてprivate podspecへの依存を宣言します。
# ExamplePod2.podspec s.dependency "ExamplePod"
これを pod lib lint
で検証すると、ExamplePodがみつからず以下の様なエラーになります。
$ pod lib lint [!] Unable to find a specification for `ExamplePod` depended upon by `ExamplePod2`
ExamplePodはprivate podspecなので、そのままでは見つからないのです。しかしPodfileでは source
でprivate Specsを指定できましたが、 pod lib lint
によるpodspecの検証のときはPodfileは使われないので、private podspecを参照できないのです。そして pod repo add
で指定したSpecsが暗黙のうちに使われるということもありません。
このため、pod lib lint
に --sources
オプションでprivate Specsを指定する必要があります。デフォルトのCocoaPods/Specsも必要なので、カンマ区切りでURLのリストを渡します。これが三つ目のポイントです。
$ pod lib lint --only-errors --sources='git@github.com:gfx/PrivateSpecsExample.git,https://github.com/CocoaPods/Specs' -> ExamplePod2 (0.0.2) - WARN | [source] Git SSH URLs will NOT work for people behind firewalls configured to only allow HTTP, therefore HTTPS is preferred. - WARN | [iOS] Unable to find a license file ExamplePod2 passed validation.
これで通常通り検証ができました。 pod repo push
は検証のロジックがlintとは違うらしく、 --sources
は不要です。
$ git tag 0.0.1 && git push origin 0.0.1 $ pod repo push --allow-warnings myspecs *.podspec
これですべて問題なくできました。各種コマンドのオプションがが複雑なので、Makefileを作っておきましょう。CIでログなどをとるため、 --verbose
もつけておくといいでしょう。
lint: pod lib lint --verbose --only-errors --sources='git@github.com:gfx/PrivateSpecsExample.git,https://github.com/CocoaPods/Specs' release: pod repo push --verbose --allow-warnings myspecs *.podspec .PHONY: lint release
これでprivate Specsを使う準備はすべて整いました。
まとめ
CocoaPod private Specsはいくつか運用のポイントがあり、本エントリではそれらを紹介しました。private Specs周りはハマるところが多く、バージョンによって挙動が異なることも多いので、安定して運用できるよう情報を共有できればと思います。