症狀:appcast 已更新,使用者端卻仍看不到新版,或下載後無法完成安裝。

最快解法:把 Sparkle 自動更新部署當成完整發佈鏈路;先核對更新源與更新包簽名,再用舊版本實際升級驗收。本週先選一個仍在使用的舊版作為測試起點。構建、簽名與驗證都需要 macOS;沒有本地 Mac 時,可評估遠端 Mac 作為發佈環境。

適合首次為 macOS App 接入自動更新的獨立開發者,按步驟建立最小可用流程。
已發佈 App、準備取代手動下載的維護者,應先核對舊版相容性與更新簽名。
沒有本地 Mac、仍要負責 macOS 構建與發佈的小團隊,可評估遠端環境是否符合日常流程。

01

先確認舊版能否接上新流程

部署前先列出目前已發佈版本使用的 Sparkle 功能、版本識別方式、更新包格式,以及客戶端實際讀取的 feed。不要先改新版設定,再假設所有舊客戶端都會理解新格式。

舊客戶端可能使用不同的更新設定或簽名方式。Sparkle 的更新文件也有升級與遷移說明;因此,調整前應依現有 App 版本核對官方升級文件及EdDSA 遷移說明,確認需要相容的客戶端範圍。不要把遷移文件等同於所有歷史版本均可直接升級。

macOS App 怎麼用 Sparkle 推送自動更新?
先確認舊版已具備可用的 Sparkle 更新流程,再提供更新源、可識別的新版本與符合現有客戶端要求的更新包。接著以舊版安裝實際檢查、下載及安裝;只更新網站上的檔案,不代表 App 已能收到更新。

先界定分發方式。本文聚焦網站等站外渠道,不把 Sparkle 更新和 Mac App Store 更新混為一談。依 Apple 的macOS 軟體分發說明確認適用的發佈要求;站外分發時,也要核對Developer ID 簽名指南與Apple 公證說明。Apple 簽章、公證與 Sparkle 更新包簽名各有用途,不能互相替代。

提醒:本機開啟 App、開發環境可安裝,並不足以證明下載發佈後的安裝流程正常。驗收時要使用實際供應的更新檔與舊版客戶端。

02

接好更新源與版本識別

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 支援哪些欄位與格式,應以官方文件及現有客戶端設定為準。

03

建立更新包的簽名信任鏈

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 成功產生就視為部署完成。

04

發佈時讓 feed 與封存檔一致

首次發布前,先準備可供客戶端取得的更新封存檔,再產生或更新 appcast。核對 feed 指向的資源確實可取得,更新說明與版本項目對應本次產物,並確認 App 中的更新源設定與正式環境一致。對於需要簽名的封存檔,還要確認生成的簽名資料沒有在檔案替換或發布過程中遺失。

Sparkle appcast 發佈後,哪些地方最容易漏查?

  • feed 指向的封存檔路徑是否正確,而非下載頁或測試環境路徑。
  • 更新項目中的版本資訊是否能讓目標舊版判斷為新版本。
  • 更新包簽名是否對應目前 App 內配置的公鑰。
  • 更新說明是否描述實際發布內容,沒有沿用前一版文字。
  • feed 與封存檔是否屬於同一次發布,而非只替換其中一個檔案。

保留發布紀錄,包括產物識別、feed 內容、更新說明與可回退版本。若 feed 已更新但封存檔尚未就緒,舊版客戶端可能取得無效資源;若只更新封存檔,客戶端則可能仍看不到新項目。把兩者視為同一個發布單位。

05

用舊版完成一次升級驗收

驗收要從使用者仍在執行的舊版開始,不要只在開發機直接安裝最新版。這樣才能區分更新源無法連線、版本比較未觸發、簽名不符,以及安裝後啟動異常等不同問題。

Sparkle 更新發布後如何驗證舊版本升級?

  1. 從乾淨的測試環境安裝仍在支援範圍內的舊版。
  2. 確認該版本使用正式預期的更新源設定。
  3. 執行 App 內的檢查更新功能,記錄是否讀取到本次 appcast 項目。
  4. 下載更新封存檔,確認簽名檢查及安裝流程完成。
  5. 重新啟動 App,核對顯示版本、建置版本與發布紀錄相符。

每次測試都記下舊版版本、appcast 項目、下載封存檔與安裝後版本之間的對應關係。若檢查不到更新,先看更新源可達性與版本比較;若下載後遭拒,檢查更新包簽名;若安裝完成卻啟動異常,回到實際產物與安裝後狀態排查。這比把所有故障都歸因於「Sparkle 沒更新」更容易縮小範圍。

06

持續發佈與遠端 Mac 分工

每次發布都同步維護封存檔、appcast、更新說明及回退紀錄。簽名密鑰需要輪換時,先確認既有客戶端如何取得新公鑰、哪些版本仍要支援,再按 Sparkle 的密鑰與遷移文件設計相容驗證。不要先撤掉舊密鑰,再測試尚未更新的客戶端能否接收新版本。

沒有本地 Mac 可以部署 Sparkle 自動更新嗎?
可以評估遠端 Mac 作為 macOS 構建、程式碼簽署與發布驗收環境,但仍需確認團隊能安全存取簽名材料,並能取得發佈產物及查看失敗紀錄。遠端桌面可以連線,不代表無人值守的構建與更新鏈路已通過驗收。若需要評估 MESHLAUNCH 的遠端 Mac 環境,可先查看環境與服務資訊,再依團隊的簽名與發布方式判斷。

07

部署條件的決策分支

  • 若仍在使用的舊版能讀取新 feed、驗證新封存檔並完成安裝,就以該流程作為發布基線;否則先保留原有下載方式,補做相容或遷移驗收。
  • 若更新源、封存檔與簽名都能從正式環境核對,就可安排小範圍發布;若有任一項只能在本機成功,先不要將其視為已部署。
  • 若發布頻率低、已有可用的本地 Mac,且管理密鑰與產物沒有瓶頸,可繼續使用現有環境;若本地設備受儲存空間、可用時間或持續構建安排限制,再評估遠端 Mac。
  • 若工作需要直接連接特定實體裝置或長期穩定的高負載環境,先核對遠端方案是否符合需求;不適合遠端的工作,不要只為了自動更新遷移。

個人 Mac 可以減少環境切換,但會受設備可用性、儲存空間與維護安排限制;純手動下載則容易讓更新說明、檔案和使用者實際版本脫節。若這些限制正拖慢 macOS App 發佈,可比較Mac mini 遠端使用方案,評估 MESHLAUNCH 是否適合作為構建與驗收環境。需要長期固定的重負載或實體介面時,購買本地 Mac 可能更合適;若只是需要臨時算力或測試環境,遠端 Mac 則可先用於驗證整條 Sparkle 更新鏈路。