怎么运用 Swift Package Manager(SPM) 开发一个命令行东西,并运用 GitHub Action 主动构建发布到 Homebrew

为了到达上述要求,咱们需求做到以下:

  1. 本地运用 SPM 开发一个命令行东西 CLI (Package)
  2. 装备 github workflow,运用 GitHub Action 装备主动构建发布二进制文件
  3. 主动发布到 Homebrew

Build a Command-line Tool

这儿咱们完结一个读取文件内容的命令行东西,功能类似于 linux cat 命令,就叫它 swiftcat 吧。

参考官方教程

SPM 工程

创立 SPM 工程:

mkdir swiftcat
cd swiftcat
swift package init --type executable

履行完上述命令后会得到 SPM 工程,工程文件目录如下:

├── Package.swift
└── Sources
   └── main.swift

Package.swift

Package.swift 是该 package 的装备文件,能够直接运用 Xcode 打开,运转该 SPM 工程,进行代码编写、调试。

Xcode 怎么设置命令行参数进行调试?

Edit Scheme > Run > Arguments > Arguments Passed On Launch 然后增加参数。

Swift 编写命令行东西并运用 GitHub Action 主动发布到 Homebrew

默认内容如下:

// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.import PackageDescription
​
let package = Package(
  name: "swiftcat",
  targets: [
    // Targets are the basic building blocks of a package, defining a module or a test suite.
    // Targets can depend on other targets in this package and products from dependencies.
    .executableTarget(
      name: "swiftcat"),
  ]
)

增加依靠

Package 能够增加依靠,运用他人现已开发好的包,这儿咱们增加苹果官方的 swift-argument-parser(后面会用到),这样咱们的 Package.swift 就更新为如下内容: 一般增加完依靠后,Xcode 会主动解析拉取依靠,假如没有或许由于网络拉取出错,咱们能够手动在 Xcode 状态栏,点击 File > Packages > Resolve Package Versions 手动触发一下解析。

// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.import PackageDescription
​
let package = Package(
  name: "swiftcat",
  dependencies: [
    .package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.0")
  ],
  targets: [
    // Targets are the basic building blocks of a package, defining a module or a test suite.
    // Targets can depend on other targets in this package and products from dependencies.
    .executableTarget(
      name: "swiftcat", dependencies: [
        .product(name: "ArgumentParser", package: "swift-argument-parser")
      ]),
  ]
)

main.swift

程序进口,你也能够删去该文件,另建 swift 文件,然后装备 @main 进口,完结 static main() 函数,main.swift@main 只能存在一个。 这儿咱们删去了 main.swift,新建了 ReadFile.swift 文件,而且运用上面依靠的swift-argument-parser直接写命令行完结相关代码。 如下所示:

import Foundation
import ArgumentParser
​
@main
struct SwiftCat: ParsableCommand {
  static var configuration: CommandConfiguration {
    let conf = CommandConfiguration(commandName: "swiftcat")
    return conf
  }
  
  @Argument(help: "文件路径")
  var filePath: String
  
  // 读取文件内容
  func run() throws {
    let fileContents = try String(contentsOfFile: filePath, encoding: .utf8)
    print(fileContents)
  }
}

filePath 是仅有的参数,传入待读取的文件路径,而且运用@Argument 包装, @Argument是直接赋值的位置参数,跟在参数最终位置,假如有多个,按声明顺序赋值。其他还有 标记 @Flag 可选@Option 类型参数。

ParsableCommand 内部完结了 static main() 函数,而且调用了 run() 函数,咱们只需求在run() 函数内部完结逻辑就行。

ReadFile run() 函数便是咱们这个 Package 中心代码了,代码很简陋,仅仅便是演示一下。

run cli

最终在终端来试一下 ,假如能正常读取文件内容,那么该命令行就算编码完结了。

# 读取文件内容
swift run swiftcat <filepath>

也能够直接在本地测验编译,或许直接运用 Xcode run

# 命令行编译
swift build -c release

最终在 GitHub 新建库房,并将此工程代码 push 到该库房。

GitHub Action

当咱们完结代码编写,接下来便是 GitHub workflow 装备了。

生成 yml 装备文件

在 GitHub 库房主页点击 Actions > New workflow > Swift Configuration,保存生成的 yml 格局文件,提交到库房。

或许直接在本地库房根目录新建一个 ci.yml 文件,保存在 .github/workflows ,push 到长途库房。

主动构建二进制文件并发布

将上述的 yml 装备文件内容更新为如下

name: "swiftcat CI"
 
on:
  push:
   tags:
    - "*"

jobs:
  build:
   runs-on: macos-13
   permissions:
    contents: write
   steps:
    - name: Swift version setup
     uses: swift-actions/setup-swift@v1
    - name: Get Swift version
     run: swift --version
    - name: Checkout
     uses: actions/checkout@v4
    - name: Build
     run: swift build -c release --arch arm64 --arch x86_64 --product swiftcat
    - name: Compress archive
     run: tar -czf ${{ github.ref_name }}.tar.gz -C .build/apple/Products/Release swiftcat
    - name: Relese
     uses: softprops/action-gh-release@v1
     with:
      files: ${{ github.ref_name }}.tar.gz

上述装备,当咱们推送任何 tag 到该库房时,就会起一个 build job 进行编译构建,生成一个兼容 arm64x86_64 的二进制文件,然后紧缩该二进制文件,发布到库房的 release 界面。

这个时候咱们能够手动打个 tag 0.0.1,推到长途,build 就会履行,不出意外的话就会发布成功。

发布成功后进入到该库房 Release 界面,找到二进制紧缩文件 tar.gz 的下载链接,仿制该链接,下文需求用。

Homebrew

The Missing Package Manager for macOS (or Linux)

homewbrew 官方库房有审核,像咱们这种小众的demo式软件,不一定让咱们进入他们的官方源, 所以这儿咱们新建一个自己的库房。

Homebrew 库房

  1. github 创立 homebrew 库房,命名格局为 homebrew-<repo>,库房姓名需求以 homebrew- 作为前缀,这儿我直接命名为 homebrew-tap

  2. 将库房增加到本地

    brew tap jacinzhang/homebrew-tap
    
  3. 切到库房目录下

    cd $(brew --repo)/Library/Taps/jacinzhang/homebrew-tap
    
  4. 库房根目录下创立Formula文件夹

    mkdir Formula
    

这儿需求创立一个 Formula 文件夹,否则后续的 Github Action 主动上传 Homebrew 会报错找不到目录。

构建 Formula

  • 创立一个新的 formula
# 创立一个新的 Formula,链接便是上述构建成功二进制文件链接
brew create --tap jacinzhang/homebrew-tap https://github.com/jacinzhang/swiftcat/releases/download/0.0.1/0.0.1.tar.gz

上述命令会生成一个 swiftcat.rb 文件,而且会主动打开。

运用brew audit --new swiftcat 查验一下该文件,提示咱们删掉注释,再修正更新一下内容,得到如下:

    class Swiftcat < Formula
     desc "CLI"
     homepage "https://github.com/jacinzhang/swiftcat"
     url "https://github.com/jacinzhang/swiftcat/releases/download/0.0.1/0.0.1.tar.gz"
     version "0.0.1"
     sha256 "6502c461d6e8547c5566ebd1d5f48745a26f17e06ebde6094efaebbf6fa5fc2d"
     license ""
    ​
     def install
      bin.install "swiftcat"
     endtest do
      system "false"
     end
    end
  • 保存文件,提交到 GitHub 长途库房
cd $(brew --repo)/Library/Taps/jacinzhang/homebrew-tap
git add --all
git commit -m 'add swiftcat'
git push
  • 装置
# 装置
brew tap jacinzhang/homebrew-tap && brew install jacinzhang/homebrew-tap/swiftcat

至此,咱们现已能够在恣意一台电脑运用 swiftcat 这个命令行东西了。

手动更新 Formula

  • 更新新版别信息:
brew edit jacinzhang/homebrew-tap/swiftcat
  • 获取新版别的 sha256
brew fetch jacinzhang/homebrew-tap/swiftcat --build-from-sourc
  • 更新 swiftcat.rb 中 sha256

  • 提交到长途库房

至此咱们已能够:

  • cli 的主动构建发布
  • 手动更新到 homebrew

可是,咱们的希望是 swiftcat 有版别更新时,能主动推送到 jacinzhang/homebrew-tap 库房,然后随时能在本地经过 homebrew 更新。

主动更新 Formula

主动更新的话,咱们需求在 swiftcat 这个库房完结构建发布后,有权限将信息更新到 jacinzhang/homebrew-tap 这个库房。

为此,咱们需求用到 bump-homebrew-formula-action 这个 github action,fastlane 也运用这个东西更新到 homebrew

按照其教程所示,咱们需求进行如下:

  1. generate a new Personal Access Token (classic) here

  2. 增加到 swiftcat 库房的 secrets 中,留意是 Repository secrets

Swift 编写命令行东西并运用 GitHub Action 主动发布到 Homebrew

  1. 在上述命令行源码库房的 ci.yml 装备文件中增加 Action
- name: Bump Homebrew formula
  uses: mislav/bump-homebrew-formula-action@v3
  with:
   formula-name: swiftcat
   homebrew-tap: jacinzhang/homebrew-tap
   download-url: https://github.com/jacinzhang/swiftcat/releases/download/${{ github.ref_name }}/${{ github.ref_name }}.tar.gz
  env:
   COMMITTER_TOKEN: ${{ secrets.COMMITTER_TOKEN }}

其中 COMMITTER_TOKEN 是步骤2中增加 token 时起的姓名。

  1. 最终提交一下,push 到长途库房。

最终咱们打一个 tag,推到长途,测试一下 build job 是成功履行了。

假如成功履行,咱们就能够直接经过 homebrew 装置、更新 swiftcat 了。

# 更新
brew upgrade swiftcat

jacinzhang/homebrew-tap

swiftcat