本週先保留鎖檔,再按故障層定位
CocoaPods 官方專案倉庫將專案標示為維護模式,這表示我們應以官方命令與當次 CI 日誌核對行為,而不是預設某種錯誤已無法修復。官方倉庫的專案狀態說明
本週建議動作:先在遠端 Runner 確認實際呼叫的 Ruby、Bundler 與 CocoaPods,再依序查 Specs/CDN、私有來源認證、Podfile.lock 和依賴下載;用原提交復現,不要先執行 pod update 或盲目清快取。
適合維護 macOS CI 流水線、需要釐清 Runner 與本機工具差異的工程師。
使用私有 Pod 倉庫、必須確認 CI 帳戶讀取權限的 iOS 團隊,也可依本文核對憑據。
若需要保留既有依賴版本並驗證修復結果,請從同一提交開始。
本機成功、遠端失敗:先對齊執行條件
「本機 pod install 成功」不能直接證明遠端失敗是網路問題。兩邊可能使用不同的執行帳戶、工作目錄、Ruby 安裝位置,或由不同 Shell 載入 PATH。遠端流程也可能在 CocoaPods 啟動前,就因環境變數或權限而中斷。
先固定比較範圍:確認本機與 Runner 使用同一提交、同一份 Podfile.lock,以及相同的依賴安裝命令。接著記錄失敗命令前後的完整輸出,辨認錯誤發生在 CocoaPods 命令啟動、依賴解析、來源下載,還是後續 Xcode 建置。
| 核對項目 | 本機記錄 | 遠端 Runner 記錄 | 差異可能指向 |
|---|---|---|---|
| 提交與工作目錄 | Git 提交、pwd |
Git 提交、pwd |
執行的不是同一版程式碼,或讀取錯目錄 |
| 執行帳戶與 Shell | whoami、Shell 類型 |
whoami、CI Shell 類型 |
權限差異、未載入預期設定 |
| 工具來源 | Ruby、Bundler、pod 路徑 | Ruby、Bundler、pod 路徑 | PATH 指向不同工具安裝位置 |
| 首個錯誤位置 | 安裝輸出的首個失敗點 | 安裝輸出的首個失敗點 | 命令、解析、下載或整合故障 |
我們建議先保存原始日誌,再做單一變更重試。若同時換 Ruby、改來源並刪除快取,即使流程恢復,也很難確認真正原因。需要評估遠端執行環境時,可先了解 MESHLAUNCH 遠端 Mac 的使用方式,但環境變更仍應以可重現的 CI 證據驗收。
Ruby、Bundler 與 pod:先確認命令從哪裡來
CI 的非互動 Shell 不一定會載入互動式終端設定。即使本機終端找得到 pod,流水線也可能呼叫另一個 RubyGems 目錄,或根本找不到 Bundler。CocoaPods 官方安裝指南說明其 RubyGems 安裝方式;若專案使用 Gemfile,官方 Gemfile 指南則說明如何把 Ruby 依賴交由 Bundler 管理。CocoaPods 安裝指南;Gemfile 與 Bundler 指南
先在發生錯誤的 CI 工作中執行並保存輸出:
whoami
pwd
which ruby
ruby -v
which bundle
bundle -v
which pod
pod --version
gem env
逐項確認輸出屬於同一個預期環境。不要只看版本字串:which 顯示的路徑能協助判斷工具是否來自預期安裝位置,gem env 則可用來核對 RubyGems 的安裝路徑與搜尋路徑。
若專案有 Gemfile 與 Gemfile.lock,檢查它們是否納入版本控制,並確認 CI 在包含這些檔案的目錄執行。安裝專案指定的 Ruby 依賴後,使用 bundle exec pod install,避免 CI 呼叫全域安裝的另一套 CocoaPods。若專案沒有採用 Bundler,也要記錄 CI 安裝 CocoaPods 的方式,避免只在開發者電腦上存在的工具被誤認為專案依賴。
Specs/CDN 與私有來源:把解析錯誤和連線錯誤分開
看到 Specs 或 CDN 字樣,不代表來源服務已被證明故障。日誌可能反映來源設定不符、Pod 名稱或版本無法解析、HTTP 回應錯誤、TLS 握手問題,或 Runner 無法連線。判斷前,先找出日誌中的請求目標、回應或錯誤類型,再核對 Podfile 的 source 與實際網路存取證據。Podfile 的來源設定語法可協助確認專案宣告的來源;故障表現則應依照官方 CocoaPods 故障排查指南逐項檢查。
| 日誌線索 | 優先檢查 | 不要先下的結論 |
|---|---|---|
| 找不到 Pod 或指定版本 | Podfile 來源、Pod 名稱、版本宣告及鎖檔 | 不要直接判定網路中斷 |
| HTTP 回應錯誤 | 失敗請求的 URL、回應內容及該 Runner 的存取結果 | 不要推論所有 Runner 都有同一故障 |
| TLS 或連線失敗 | Runner 的 DNS、代理、憑證信任及實際連線輸出 | 不要未檢查就替換上游來源 |
| 私有規格可讀、原始碼下載失敗 | Specs Repo 與原始碼倉庫的權限是否分開配置 | 不要把讀取規格等同於讀取程式碼 |
私有 Pod 要拆成兩個驗證目標:CI 帳戶是否能讀取私有 Specs Repo,以及是否能讀取 Podfile 指向的 Pod 原始碼倉庫。CocoaPods 私有 Pod 指南說明私有規格來源的配置方式;來源存在並不等於 CI 帳戶已取得讀取權限。官方私有 Pod 指南
檢查憑據時,只使用受控的變數名稱作占位符,例如 $PRIVATE_REPO_TOKEN。核對該憑據是否注入目前 CI 工作、是否具備所需讀取權限,以及非互動式 Git 是否能使用它。不要把真實 Token 寫進 Podfile、命令列範例或 CI 日誌,也不要輸出包含憑據的完整倉庫 URL。
注意:單次連線測試只能說明該次 Runner、該個 URL 的結果。請保留測試時間、目標來源與錯誤輸出;不要把個案日誌擴大成 CDN 當前可用性或全域故障的結論。
Podfile.lock 漂移:安裝不等於更新
Podfile.lock 是復現已解析依賴的重要依據。先確認它在版本控制中,且 CI 的工作目錄確實包含預期檔案。再檢查安裝命令有沒有切換到另一個目錄,或流程是否刻意修改了解析結果。CocoaPods 官方將 pod install 與 pod update 的用途分開說明:前者用於依照專案現有依賴狀態安裝,後者用於更新依賴。官方命令差異說明
因此,依賴安裝失敗時,不要先用 pod update 當作通用修復。它可能改變解析結果,讓「原始安裝故障」變成「更新後的版本差異」。如果確實需要更新依賴,應在獨立變更中處理,檢查 Podfile.lock 的差異,並讓審查者確認版本變動符合預期。
可先用以下方式檢查 CI 工作目錄是否包含鎖檔:
pwd
git status --short
git ls-files --error-unmatch Podfile.lock
若最後一個命令無法找到檔案,先查清楚鎖檔是否未提交、工作目錄是否錯誤,或專案是否採用另一種目錄結構。不要為了讓安裝繼續,就在 CI 中悄悄生成並覆寫鎖檔。
CocoaPods 安裝成功、Xcode 仍失敗:分開驗收
pod install 結束不代表整個 iOS 建置已通過。應分開確認 CocoaPods 是否完成依賴取得、Pods 工程產生與工作區整合,再檢查後續 Xcode 建置日誌。官方命令參考可用來核對 CocoaPods 命令及參數的行為;不要把後續編譯或簽署錯誤歸因於已成功完成的依賴安裝。CocoaPods 命令列參考
按照以下順序完成復測:
- [ ] 固定原始提交,確認 CI 工作目錄與 Podfile.lock 內容一致。
- [ ] 記錄實際執行帳戶、Shell、工作目錄及
ruby、bundle、pod的路徑。 - [ ] 確認安裝命令使用專案預期的工具;有 Gemfile 時,核對是否透過
bundle exec呼叫 CocoaPods。 - [ ] 從首個錯誤開始讀日誌,將問題分類為命令啟動、依賴解析、來源連線、私有倉庫認證或下載。
- [ ] 每次只改一項設定,保存變更前後日誌與 CI 輸出,避免多項改動掩蓋根因。
- [ ] 確認
pod install完成後,再以同一提交執行 Xcode 建置,分別記錄安裝與建置結果。 - [ ] 若仍失敗,回到新日誌所指向的故障層;不要把重建 Runner 當成第一個修復步驟。
FAQ:依症狀選擇下一個檢查點
為什麼本機安裝成功,CI 卻失敗?
先核對提交、工作目錄、執行帳戶與完整命令。然後比對 Ruby、Bundler、CocoaPods 的路徑與版本。如果工具環境相同,再從日誌定位 Specs 查詢、私有倉庫讀取、依賴原始碼下載或 Xcode 整合的首個失敗點;不要僅憑本機結果推論遠端網路有問題。
遠端 Mac 找不到正確的 Ruby 或 pod,怎麼處理?
在 CI 工作本身執行 which ruby、ruby -v、which bundle、bundle -v 和 which pod,不要以登入終端的輸出代替 Runner 證據。專案採用 Gemfile 時,核對 Gemfile.lock 並在正確目錄執行 bundle exec pod install;若未採用 Bundler,則記錄 CI 實際安裝及呼叫 CocoaPods 的方式。
Specs/CDN 下載失敗,如何判斷網路還是來源設定?
從完整日誌找出失敗的來源 URL、HTTP 回應、TLS 或連線錯誤,再核對 Podfile 中的 source 與 Runner 對該來源的實際存取結果。Pod 名稱或版本無法匹配,與連線失敗不是同一類問題;保留可重現的請求和錯誤輸出,不要因單次失敗便替換來源或宣稱 CDN 故障。
CI 讀不到私有 Pod,哪些憑據和權限要查?
分別確認 CI 帳戶能否讀取私有 Specs Repo,以及能否讀取 Podfile 指向的原始碼倉庫。再核對來源 URL、憑據是否注入該工作、權限是否足夠,以及非互動式 Git 認證是否生效。憑據只放在受控秘密變數中;不要輸出真實 Token,也不要把含憑據的 URL 留在日誌。
如果依賴設定、權限與命令都已核實,但團隊仍缺少可持續使用的 macOS 執行環境,遠端 Mac 租用可作為購買實機之外的選項:不必先準備一台專用 Mac,也能在真實 macOS 環境驗證依賴安裝與建置流程。若工作負載長期穩定且需要實體接口,自購設備可能更合適;若只是按 CI 週期取得執行環境,可查看 MESHLAUNCH 遠端 Mac 方案,再依工具鏈、存取方式與使用週期評估。