Swift PackagesでCLIツールを自作する方法

「Swift PackagesによるCLIツールの作成方法」は5部構成です。
記事を順番に読み進めると、Swift PackagesでCLIツールを自作して公開できるようになります。

第1部: Swift PackagesでCLIツールを自作する　__←イマココ__
第2部: [自作パッケージをSwift Package Indexに追加する](https://qiita.com/uhooi/items/689801dad2cf2e0a37b4)
第3部: [自作パッケージをMintに対応する](https://qiita.com/uhooi/items/fab2fa2f3dc540ad2315)
第4部: 自作パッケージをHomebrewに追加する（未投稿）
第5部: 自作パッケージをCocoaPodsに追加する（未投稿）

## はじめに

Swift製のCLIツールを自作する実績を解除したかったので、かんたんなCLIツールを自作することにしました。

## 「Swift Packages」とは？

[こちら](https://qiita.com/uhooi/items/2f36b85f5f41cbd35189#swift-packagesとは) をご参照ください。

## 環境

- OS： macOS Big Sur 11.6
- Xcode：12.5.1 (12E507)
- Swift：5.4.2
- swift-tools：5.4

## パッケージの作成方法

例として「swift-output-uhooi」というリポジトリに「OutputUhooi」というパッケージを作成します。

### GitHubにリポジトリを作成する

詳細は [こちら](https://qiita.com/uhooi/items/2f36b85f5f41cbd35189#githubにリポジトリを作成する) をご参照ください。

```shell-session
$ git clone https://github.com/uhooi/swift-output-uhooi.git
$ cd swift-output-uhooi
$ git switch -c feature/create_package
```

### パッケージの基盤を生成する

詳細は [こちら](https://qiita.com/uhooi/items/2f36b85f5f41cbd35189#パッケージの基盤を生成する) をご参照ください。

```shell-session
$ swift package init --name OutputUhooi --type executable
Creating executable package: OutputUhooi
Creating Package.swift
Creating Sources/
Creating Sources/OutputUhooi/main.swift
Creating Tests/
Creating Tests/OutputUhooiTests/
Creating Tests/OutputUhooiTests/OutputUhooiTests.swift
```

### .gitignoreを作成する

[こちら](https://qiita.com/uhooi/items/2f36b85f5f41cbd35189#gitignoreを作成する) をご参照ください。

### CIを構築する（任意）

できる限り実装前にCIを構築します。
GitHub Actionsを使えば一瞬で構築できます。

```yaml:main.yml
name: CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  run:
    runs-on: macos-11
    strategy:
      matrix:
        xcode: ["12.5.1", "13.0"]
        subcommand: ["Build", "Test"]
    steps:
    - uses: actions/checkout@v2
    - name: ${{ matrix.subcommand }}
      run: |
        xcodebuild -version
        swift --version
        swift package --version
        subcommand=`echo ${{ matrix.subcommand }} | tr '[:upper:]' '[:lower:]'`
        swift $subcommand -v
      env:
        DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app
```

これで `main` ブランチへPRを出すときとプッシュするとき（PRのマージを含む）に、自動でビルドとテストが実行されます。

### CDを構築する（任意）

GitHub Actionsを使い、リリース時に自動でソースをビルドし、バイナリをリリースのアセットに追加するCDを構築します。

```yaml:release.yml
name: Release

on:
  release:
    types: [published]

env:
  DEVELOPER_DIR: /Applications/Xcode_12.5.1.app

jobs:
  build-release:
    runs-on: macos-11
    steps:
    - uses: actions/checkout@v2
    - name: Build for release
      run: swift build -c release
    - name: Archive the binary
      run: zip -j uhooi.zip .build/release/uhooi
    - name: Upload the binary
      uses: actions/upload-artifact@v2
      with:
        name: uhooi
        path: uhooi.zip
        retention-days: 14

  deploy-binary:
    needs: build-release
    runs-on: macos-11
    steps:
    - uses: actions/download-artifact@v2
      with:
        name: uhooi
    - name: Deploy the binary
      uses: softprops/action-gh-release@v1
      with:
        files: uhooi.zip
```

`uhooi` の部分は自分のバイナリ名に置き換えてください。

これでGitHubからリリースするたびに自動でバイナリがアセットに追加されます。

以下の例だと `uhooi.zip` がバイナリを圧縮したファイルです。
2つの `Source code` はリリース時に自動で追加されるので、手動やワークフローで追加する必要がありません。
![スクリーンショット 2021-10-05 19.09.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138245/428aabd9-a493-c9f4-c89c-d63c89b5ab94.png)

### CLIツールを実装する

詳細な実装方法は別記事で紹介する予定なので、本記事では省略します。
基本的なパッケージ構成は [こちら](https://qiita.com/uhooi/items/2f36b85f5f41cbd35189#ライブラリを実装する) をご参照ください。

### 対応プラットフォームを明記する（任意）

詳細は [こちら](https://qiita.com/uhooi/items/2f36b85f5f41cbd35189#対応プラットフォームを明記する任意) をご参照ください。

CLIツールなのでmacOSのみ記述すればOKです。

```swift:Package.swift
// ...
let package = Package(
    // ...
    platforms: [
        .macOS(.v10_10),
    ],
    // ...
)
```

### READMEを編集する（任意）

最後にREADMEを編集します。
最低限「CLIツールのインストール方法」と「CLIツールの使い方」があると親切です。

詳細は [こちら](https://qiita.com/uhooi/items/2f36b85f5f41cbd35189#readmeを編集する任意) をご参照ください。

### 変更をコミットしてプッシュする

[こちら](https://qiita.com/uhooi/items/2f36b85f5f41cbd35189#変更をコミットしてプッシュする) をご参照ください。

### リリースする

[こちら](https://qiita.com/uhooi/items/2f36b85f5f41cbd35189#リリースする) をご参照ください。

## パッケージの使い方

自作パッケージを使う方法を説明します。

### ソースコードをビルドする

今回は最もわかりやすい、ソースコードをビルドしてバイナリを生成する方法を紹介します。

実務では [Mint](https://github.com/yonaskolb/Mint) やSwiftPMなどのパッケージ管理ツールを使うのが望ましいです。

```shell-session
$ git clone https://github.com/uhooi/swift-output-uhooi.git
$ cd swift-output-uhooi
$ swift build -c release
```

`-c release` オプションを付けることでリリースビルドになります。

### バイナリを実行する

生成したバイナリを実行します。

リリースビルドしたら `.build/release` フォルダにバイナリが生成されるので、 `.build/release/{バイナリ名}` で実行できます。

```shell-session
$ .build/release/uhooi "I'm uhooi."
┌|▼▼|┘<I'm uhooi.
```

見事に `uhooi` コマンドを使ってウホーイの喋るAAを出力できました。

### ヘルプを見る

だいたいのCLIツールにはヘルプが用意されているので、 `-h` オプションを付けて実行してみます。

```shell-session
$ .build/release/uhooi -h
OVERVIEW: Uhooi speak the phrase.

USAGE: uhooi [--include-counter] [--count <count>] <phrase>

ARGUMENTS:
  <phrase>                The phrase to repeat.
            
OPTIONS:
  --include-counter       Include a counter with each repetition.
  -c, --count <count>     The number of times to repeat 'phrase'.
  --version               Show the version.
  -h, --help              Show help information.
```

`uhooi` コマンドのヘルプが出力されました。
初めて使うコマンドは、ヘルプを見ると使い方がわかるのでオススメです。

## おわりに

Swift PackagesでCLIツールを自作する実績を解除できました！
ウホーイが喋るだけのCLIツールですが、よかったらスターを付けて、実際に使ってみてください :relaxed:

https://github.com/uhooi/swift-output-uhooi

みなさんの素晴らしい自作CLIツールにも期待しています :eyes:

## 参考リンク

- [softprops/action-gh-release: 📦 GitHub Action for creating GitHub Releases](https://github.com/softprops/action-gh-release)