症狀:appcast 已更新,使用者端卻仍看不到新版,或下載後無法完成安裝。
最快解法:把 Sparkle 自動更新部署當成完整發佈鏈路;先核對更新源與更新包簽名,再用舊版本實際升級驗收。本週先選一個仍在使用的舊版作為測試起點。構建、簽名與驗證都需要 macOS;沒有本地 Mac 時,可評估遠端 Mac 作為發佈環境。
適合首次為 macOS App 接入自動更新的獨立開發者,按步驟建立最小可用流程。
已發佈 App、準備取代手動下載的維護者,應先核對舊版相容性與更新簽名。
沒有本地 Mac、仍要負責 macOS 構建與發佈的小團隊,可評估遠端環境是否符合日常流程。
先確認舊版能否接上新流程
部署前先列出目前已發佈版本使用的 Sparkle 功能、版本識別方式、更新包格式,以及客戶端實際讀取的 feed。不要先改新版設定,再假設所有舊客戶端都會理解新格式。
舊客戶端可能使用不同的更新設定或簽名方式。Sparkle 的更新文件也有升級與遷移說明;因此,調整前應依現有 App 版本核對官方升級文件及EdDSA 遷移說明,確認需要相容的客戶端範圍。不要把遷移文件等同於所有歷史版本均可直接升級。
macOS App 怎麼用 Sparkle 推送自動更新?
先確認舊版已具備可用的 Sparkle 更新流程,再提供更新源、可識別的新版本與符合現有客戶端要求的更新包。接著以舊版安裝實際檢查、下載及安裝;只更新網站上的檔案,不代表 App 已能收到更新。
先界定分發方式。本文聚焦網站等站外渠道,不把 Sparkle 更新和 Mac App Store 更新混為一談。依 Apple 的macOS 軟體分發說明確認適用的發佈要求;站外分發時,也要核對Developer ID 簽名指南與Apple 公證說明。Apple 簽章、公證與 Sparkle 更新包簽名各有用途,不能互相替代。
提醒:本機開啟 App、開發環境可安裝,並不足以證明下載發佈後的安裝流程正常。驗收時要使用實際供應的更新檔與舊版客戶端。
接好更新源與版本識別
Sparkle 自動更新部署要先分清三個位置:下載頁提供給使用者的入口、App 定期檢查的 appcast,以及 feed 指向的更新封存檔。它們可能放在同一個網域,但不是同一個 URL 或檔案。
| 項目 | 用途 | 發佈前核對 |
|---|---|---|
| 下載頁 | 讓使用者取得 App 或閱讀發佈說明 | 頁面內容與當次版本資訊一致 |
| Sparkle appcast | 提供 App 可解析的更新項目與封存檔位置 | App 設定的更新源指向正確 feed |
| 更新封存檔 | 提供實際下載及安裝的更新內容 | feed 中的資源可取得,簽名驗證符合客戶端要求 |
依Sparkle 官方設定文件核對 Info.plist 中的更新配置與適用的更新包格式。設定時使用自己的佔位值,例如 https://<UPDATE-HOST>/<APPCAST-PATH>;不要把下載頁 URL 填成更新源,也不要把封存檔 URL 填入 feed 設定。
版本識別則決定客戶端如何比較目前版本與更新項目。每次發佈前,對照 App 顯示版本、建置版本和 appcast 項目,避免標題看似更新,實際比較欄位卻無法觸發升級。Sparkle 支援哪些欄位與格式,應以官方文件及現有客戶端設定為準。
建立更新包的簽名信任鏈
Sparkle 更新包簽名用來驗證更新封存檔,與 Apple Developer ID 對 App 程式碼所做的簽章不是同一層。即使 App 已完成 Apple 簽署或公證,也不能因此推論 Sparkle 更新包已通過客戶端的簽名驗證;同樣地,封存檔有 Sparkle 簽名,也不代表 Apple 的分發要求已完成。
依安全與可靠性文件及官方簽名工具的說明,確認 App 端配置的 EdDSA 公鑰與產生更新檔時採用的私鑰相對應。發布前,檢查工具輸出的簽名欄位是否進入 appcast,並用目標舊版客戶端驗證;私鑰只存放於經團隊核准的密鑰管理位置,不要提交到程式碼儲存庫、寫入範例或放進一般建置產物。
注意:appcast 是描述更新的 XML 文件,更新封存檔則是實際下載的內容。feed 中出現封存檔簽名資料,不等於整份 XML 已經由該簽名保護。要分別驗證 feed 的傳輸與存取設定,以及更新包的簽名檢查。
Sparkle 更新包簽名和 appcast 怎麼生成?
先以 Sparkle 官方發布工具根據更新包產生或更新 appcast,再核對其中的版本資訊、更新說明、下載位置與簽名資料。Sparkle 提供自動產生發布檔案的工具,也允許依流程維護 feed;選擇哪種方式,取決於團隊能否在每次發佈時穩定產生並審查相同欄位。依發布更新文件核對工具適用方式,不要只因 XML 成功產生就視為部署完成。
發佈時讓 feed 與封存檔一致
首次發布前,先準備可供客戶端取得的更新封存檔,再產生或更新 appcast。核對 feed 指向的資源確實可取得,更新說明與版本項目對應本次產物,並確認 App 中的更新源設定與正式環境一致。對於需要簽名的封存檔,還要確認生成的簽名資料沒有在檔案替換或發布過程中遺失。
Sparkle appcast 發佈後,哪些地方最容易漏查?
- feed 指向的封存檔路徑是否正確,而非下載頁或測試環境路徑。
- 更新項目中的版本資訊是否能讓目標舊版判斷為新版本。
- 更新包簽名是否對應目前 App 內配置的公鑰。
- 更新說明是否描述實際發布內容,沒有沿用前一版文字。
- feed 與封存檔是否屬於同一次發布,而非只替換其中一個檔案。
保留發布紀錄,包括產物識別、feed 內容、更新說明與可回退版本。若 feed 已更新但封存檔尚未就緒,舊版客戶端可能取得無效資源;若只更新封存檔,客戶端則可能仍看不到新項目。把兩者視為同一個發布單位。
用舊版完成一次升級驗收
驗收要從使用者仍在執行的舊版開始,不要只在開發機直接安裝最新版。這樣才能區分更新源無法連線、版本比較未觸發、簽名不符,以及安裝後啟動異常等不同問題。
Sparkle 更新發布後如何驗證舊版本升級?
- 從乾淨的測試環境安裝仍在支援範圍內的舊版。
- 確認該版本使用正式預期的更新源設定。
- 執行 App 內的檢查更新功能,記錄是否讀取到本次 appcast 項目。
- 下載更新封存檔,確認簽名檢查及安裝流程完成。
- 重新啟動 App,核對顯示版本、建置版本與發布紀錄相符。
每次測試都記下舊版版本、appcast 項目、下載封存檔與安裝後版本之間的對應關係。若檢查不到更新,先看更新源可達性與版本比較;若下載後遭拒,檢查更新包簽名;若安裝完成卻啟動異常,回到實際產物與安裝後狀態排查。這比把所有故障都歸因於「Sparkle 沒更新」更容易縮小範圍。
持續發佈與遠端 Mac 分工
每次發布都同步維護封存檔、appcast、更新說明及回退紀錄。簽名密鑰需要輪換時,先確認既有客戶端如何取得新公鑰、哪些版本仍要支援,再按 Sparkle 的密鑰與遷移文件設計相容驗證。不要先撤掉舊密鑰,再測試尚未更新的客戶端能否接收新版本。
沒有本地 Mac 可以部署 Sparkle 自動更新嗎?
可以評估遠端 Mac 作為 macOS 構建、程式碼簽署與發布驗收環境,但仍需確認團隊能安全存取簽名材料,並能取得發佈產物及查看失敗紀錄。遠端桌面可以連線,不代表無人值守的構建與更新鏈路已通過驗收。若需要評估 MESHLAUNCH 的遠端 Mac 環境,可先查看環境與服務資訊,再依團隊的簽名與發布方式判斷。
部署條件的決策分支
- 若仍在使用的舊版能讀取新 feed、驗證新封存檔並完成安裝,就以該流程作為發布基線;否則先保留原有下載方式,補做相容或遷移驗收。
- 若更新源、封存檔與簽名都能從正式環境核對,就可安排小範圍發布;若有任一項只能在本機成功,先不要將其視為已部署。
- 若發布頻率低、已有可用的本地 Mac,且管理密鑰與產物沒有瓶頸,可繼續使用現有環境;若本地設備受儲存空間、可用時間或持續構建安排限制,再評估遠端 Mac。
- 若工作需要直接連接特定實體裝置或長期穩定的高負載環境,先核對遠端方案是否符合需求;不適合遠端的工作,不要只為了自動更新遷移。
個人 Mac 可以減少環境切換,但會受設備可用性、儲存空間與維護安排限制;純手動下載則容易讓更新說明、檔案和使用者實際版本脫節。若這些限制正拖慢 macOS App 發佈,可比較Mac mini 遠端使用方案,評估 MESHLAUNCH 是否適合作為構建與驗收環境。需要長期固定的重負載或實體介面時,購買本地 Mac 可能更合適;若只是需要臨時算力或測試環境,遠端 Mac 則可先用於驗證整條 Sparkle 更新鏈路。