iT邦幫忙

2025 iThome 鐵人賽

DAY 30
0

本篇聚焦「讀者如何將 C 擴充的 Ruby 專案做成跨平台預編譯」,以 GitHub Actions 的 matrix native compile 為主軸,並示範 artifacts 與目錄 tree 的管理、跨平台打包與回退策略。內容讀者取向,可直接複製 YAML 進行調整。

——

讀者能學到什麼

  • 以 matrix 跑 macOS(x86_64/arm64)、Linux(glibc/musl)、Windows 的原生編譯。
  • 如何在工作流間傳遞 artifacts,與如何用 tree 檢視與對齊產出目錄結構。
  • 平台 gem 發佈流程與回退策略(先 source gem,後平台 gem)。

——

一、工作流切分思路

  • 基建工作流(可複用):針對 Linux/macOS/Windows 的「跨平台預編譯」步驟,抽成可重用工作流,以 workflow_call 呼叫。
  • 產品工作流(專案層):針對 release/tag 事件呼叫基建工作流,收集 artifacts,最後組裝發佈。

這種切分能讓讀者把「平台差異」集中在重用工作流,產品側只需要專注版本與簽名/發佈細節。

——

二、可直接套用的 YAML(精簡範本)

以下提供單檔精簡版,讀者可依專案拆為多個可重用工作流。示例採用 Ruby bundler 與 rake-compiler 常見流程;若專案直接以 extconf.rb 編譯核心原始碼,也同樣適用。

name: build-and-release

on:
  push:
    tags:
      - "v*.*.*"

jobs:
  build-matrix:
    name: build (${{ matrix.os }} / ${{ matrix.ruby }} / ${{ matrix.libc || 'mac/win' }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: macos-13
            ruby: "3.2"
            arch: x86_64
          - os: macos-14
            ruby: "3.2"
            arch: arm64
          - os: ubuntu-22.04
            ruby: "3.2"
            libc: glibc
          - os: ubuntu-22.04
            ruby: "3.2"
            libc: musl
          - os: windows-2022
            ruby: "3.2"

    steps:
      - uses: actions/checkout@v4

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: ${{ matrix.ruby }}
          bundler-cache: true

      - name: Install deps (Linux)
        if: startsWith(matrix.os, 'ubuntu')
        run: |
          sudo apt-get update
          sudo apt-get install -y build-essential pkg-config

      - name: Build gem (native)
        run: |
          bundle install --jobs 4 --retry 3
          bundle exec rake compile
          bundle exec rake build

      - name: Archive artifact
        uses: actions/upload-artifact@v4
        with:
          name: pkg-${{ matrix.os }}-${{ matrix.arch || matrix.libc || 'win' }}
          path: |
            pkg/*.gem
            ext/mongory_ext/*.so
            ext/mongory_ext/*.bundle
            ext/mongory_ext/*.dll

  release:
    needs: build-matrix
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v4

      - name: Download artifacts
        uses: actions/download-artifact@v4
        with:
          path: artifacts

      - name: Inspect tree
        run: |
          tree -a artifacts || ls -R artifacts

      - name: Publish gems
        env:
          RUBYGEMS_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
        run: |
          # 1) 建議先發佈 source gem(可回退且通用)
          gem push pkg/*.gem || true
          # 2) 再針對各平台的 gem(若有)逐一發佈
          find artifacts -name '*.gem' -print -exec gem push {} \; || true

說明:

  • macOS 以不同 runner 區分 x86_64/arm64。
  • Linux 以同一 runner,利用不同 job 標籤區分 glibc/musl(若採用 musl,需要自訂容器或 cross 編譯策略,此處先留白由讀者補上)。
  • Windows 以 windows-2022 runner。
  • 產出物(.gem、.so/.bundle/.dll)以 artifacts 管線匯總,最後在 release job 發佈。

——

三、Artifacts 與目錄 tree 的管理

  • 上傳時就用可識別名稱(含 os/arch/libc),下載後 tree 檢視,能快速對齊目錄與檔名。
  • 若要進一步壓縮或簽名,可在 release job 追加步驟:zip/tar + sha256sum。

——

四、跨平台打包與測試建議

  • macOS:同時涵蓋 x86_64 與 arm64。若只生成一個二進位,請於 README 清楚標註支援架構。
  • Linux:glibc 與 musl 可視需求二擇一,或以容器各自建置。
  • Windows:注意 .dll 與 Ruby 版本對應,建議在 CI 中以矩陣覆蓋常見 Ruby 版本。
  • 測試:每個矩陣節點都執行最小的 smoke test,確保 .so/.bundle/.dll 可被 require

——

五、回退策略(務實版)

  • 先釋出 source gem:即使沒有原生產物,讀者也能在本機編譯並使用。
  • 平台 gem 分開釋出:某平台失敗不阻斷其他平台發布。
  • 快速回滾:保留前一版 gem;必要時 yank 最新平台 gem,待修復後重發。

——

六、維運經驗(可操作項)

  • 在 PR 內跑小矩陣(少量 Ruby 版本與 1–2 平台)加速回饋;在 tag/release 時跑完整矩陣。
  • 把可重用步驟抽成獨立工作流(Linux/macOS/Windows),專案層只負責組裝。
  • 針對 Linux musl 場景,優先以容器固定 toolchain,避免動態鏈結帶來的相容性風險。

——

結語:CI/CD 與預編譯的關鍵,是把平台差異集中治理、把產出物管好、把回退路徑留好。沿用本文 YAML 與策略,讀者可在一兩個迭代內,把任何含 C 擴充的 Ruby 專案升級為「可預編譯、可回退、可維運」的產品級流程。

Mongory-rb github workflow 參考


上一篇
Bonus 2:C → Ruby bridge 落地手冊
系列文
Mongory:打造跨語言、高效能的萬用查詢引擎33
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言