自作ライブラリ Carthage CocoaPods 公開を CI で自動化


GitHub Actions を利用し、Release 作成タイミングで、ライブラリ公開作業を自動化しましょう！


# 前提

- `Release` の作成 (= `tag` 作成) は手作業で行うものとします。
この記事で行う自動化は、Release 作成をトリガーとして行うものです。

- https://github.com/yuki0n0/WaveSlider/
解説するものは、こちらのライブラリを作成したときの情報に基づいています。
よかったら GitHub で **<font color="SandyBrown">Star ★</font>** つけてね。

- https://qiita.com/yuki0n0/items/290c6ab753634e7395f5
ライブラリ公開の手続きなどはこちらで解説しております。

- CI は GitHub Actions を利用しています。
大したことはやってないのでお好きな CI で読み替えてください

# CocoaPods

今回やることは下記です。

- `pod trunk push` を CI で自動的に実行
- push が行えるように認証情報を用意する
- バージョン情報を `tag` から取得

## 1. トークンを取得

登録 (もしくはログイン) します。メールが来たらアクティベートしましょう。

```sh
# 登録済みの場合は Name は必要ありません
pod trunk register mail@example.com Name
```

`~/.netrc` に認証情報があるため、 `password` を確認します。

```:~/.netrc
machine trunk.cocoapods.org
  login mail@example.com
  password 0000000a000000aaaaaaa0000aa00a0a
```

この `password` を GitHub Actions から利用できるように Secrets にセットします。
ここでは `COCOAPODS_TRUNK_TOKEN` としておきます。
<img alt="GitHub Actions Secrets" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42826/9dca41ac-933c-b972-7dd0-ecd9b98530d1.png">


## 2. バージョンを環境変数から取れるようにしておく

`.podspec` ファイルでバージョンを指定しますが、ここの値を**外部**から指定できるようにしておきます。
環境変数 `LIBRARY_VERSION` に `1.0.0` のような値が入っていることを想定します。

```ruby:LibraryName.podspec
# コードは一例です。お好きな方法で外部の値をとってこれるようにしましょう。
version = ENV["LIBRARY_VERSION"]
exit 1 if version.to_s.empty?

Pod::Spec.new do |spec|
  spec.name         = "LibraryName"
  spec.version      = version
  spec.source       = { :git => "https://...git", :tag => spec.version }
  ...
end
```

今回でいう**外部**は、 git の `tag` 名に基づいて指定したいということです。
つまり、必然的に `tag` 名は `1.0.0` というような CocoaPods のバージョン名と一致することが求められます。


## 3. GitHub Actions の Yaml ファイル

最低限の Yaml を下記に載せました。ポイントをまとめます。

- CocoaPods のトークン (`password`) を env として定義し忘れない
- env `LIBRARY_VERSION` に tag 名を渡す
- `github.event.release.tag_name` でタグ名を取れる！ (**これにたどり着くのに時間かかった**)


```yaml:GitHub&nbsp;Actions&nbsp;の&nbsp;Yaml&nbsp;ファイル
on:
  release:
    types: [published]

jobs:
  job-name:
    runs-on: macos-10.15

    env:
      COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
      LIBRARY_VERSION: ${{ github.event.release.tag_name }}

    steps:
    - uses: actions/checkout@v2
    - run: pod trunk push LibraryName.podspec
```

ソースコードはこちら
https://github.com/yuki0n0/WaveSlider/blob/1.0.2/.github/workflows/release_published.yaml

# Carthage

Carthage は公開を自動化するというより、
オプションとして行う「バイナリのアップロード」を自動化します。

## 1. 前提知識

### Release の Assets 

https://docs.github.com/ja/github/administering-a-repository/about-releases
GitHub の Release には、ファイルを **Assets** として置いておける場所があります。
<img width="300" alt="ReleaseのAssets" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42826/b99e2b7c-3dec-0fd8-28eb-457624abc888.png">
そして、ここにブラウザ上から手動でファイルをアップロードすることもできます。
<img width="400" alt="Releaseにアップロード" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42826/d35077dd-7793-d4ab-d828-63272a42c192.png">
このアップロードを自動化します。

### アップロードしたいバイナリ

下記コマンドを実行すると、 `LibraryName.framework.zip` を作成できます。

```sh
carthage build --archive
```

### バイナリを Assets に置いておくメリット

ビルド済みのバイナリを置いておくことにより、ライブラリ利用者はこれを使用できます。
通常はソースコードを各利用者の環境でビルドするので、この**ビルド時間を省略**[^carthage_cannot_use]できます。

[^carthage_cannot_use]: 一方で、このバイナリを「Swiftのバージョンが異なる」等の理由で利用できない場合があります。<br>その場合は Carthage 側が自動的に判断[^carthage0.20.0]して、バイナリは利用せずに通常通りソースコードからビルドして利用します。<br>どんな状況でもバイナリを使用したくない場合は `--no-use-binaries` オプションを付与してコマンドを実行します。

[^carthage0.20.0]: Carthage 0.20.0 以降


## 2. バイナリを自動アップロード

最小限のコードを、コメントと共に掲載しておきます。

```yaml:GitHub&nbsp;Actions&nbsp;の&nbsp;Yaml&nbsp;ファイル
on:
  release:
    types: [published]

jobs:
  job-name:
    runs-on: macos-10.15

    env:
      GITHUB_TOKEN: ${{ github.token }}

    steps:
    - uses: actions/checkout@v2

    # LibraryName.framework.zip を作成
    - run: carthage build --archive 

    # upload_url を取得するために使用させていただく
    - uses: bruceadams/get-release@v1.2.0
      id: get

    # Release の Assets にファイルをアップロード
    - uses: actions/upload-release-asset@v1.0.2
      with:
        upload_url: ${{ steps.get.outputs.upload_url }}
        asset_path: ./LibraryName.framework.zip
        asset_name: LibraryName.framework.zip
        asset_content_type: application/zip
```

ソースコードはこちら
https://github.com/yuki0n0/WaveSlider/blob/1.0.2/.github/workflows/release_published.yaml



# 参考

- **GitHub**: Carthage Readme<br>
https://github.com/Carthage/Carthage#supporting-carthage-for-your-framework
- **GitHub**: 公式ドキュメント リリースについて<br>
https://docs.github.com/ja/github/administering-a-repository/about-releases
- **GitHub Support Comunity**: How to get just the tag name? - GitHub Actions<br>
https://github.community/t/how-to-get-just-the-tag-name/16241/21
- **Qiita**: GitHub Actions で 自作Cocoapodsライブラリを自動デプロイする<br>
https://qiita.com/ry-itto/items/0fab3fdc4321bfbd3877