
OpenWork 發布流程實戰指南Tag 驅動的零提交 GitHub Actions 發布管線【免費下載鏈接】openworkThe open-source alternative to Claude Cowork (powered by opencode)項目地址: https://gitcode.com/GitHub_Trending/ope/openworkOpenWork基于 opencode 的開源 Claude Cowork 替代品的發布流程完全由GitHub Actions GitHub Releases驅動版本只存在于 git tag 中倉庫內所有package.json永久保留0.0.0-dev占位符CI 在構建時把 tag 派生的版本號蓋章進工作區——發一次版對倉庫做零提交。本文以倉庫內.opencode/commands/release.md命令文檔為主體結合.opencode/skills/release/SKILL.md技能文檔與docs/RELEASING.md完整 runbook并深入scripts/release/*.mjs與.github/workflows/release-macos-aarch64.yml源碼完整講解 OpenWork 發布流程的觸發方式、內部機制、驗證清單、故障恢復與回滾方案。核心原則一次發布 一個 tag零提交在動手前先建立三個基本認知它們是整個發布流程設計的基石版本只存在于 git tag發布的唯一事實來源是vX.Y.Z形式的穩定 tag。所有已提交的package.jsonapps/app/package.json、apps/desktop/package.json、apps/server/package.json一律持有永久的0.0.0-dev占位符由 CI 在構建時通過 stamp-version.mjs 寫入真實版本。發布對倉庫零改動沒有 bump 提交、沒有 backfill PR、沒有打包 PR——切一個版本不會在倉庫留下任何提交docs/RELEASING.md明確Cutting a release makes zero commits to this repo。發布的完成標準不是 tag 創建成功而是Release App工作流運行全綠且Publish GitHub Release步驟把 draft 翻轉成公開 release。命令入口與參數release.md命令文檔定義了$ARGUMENTS的語義為空默認打一個 patch 版本X.Y.Z的Z1為minorX.(Y1).0為major(X1).0.0。命令運行器會據此加載并遵循 .opencode/skills/release/SKILL.md完整 runbook 見 docs/RELEASING.md默認走tag-firsttag 優先路徑除非用戶明確要求 PR-first。當前倉庫根目錄 package.json 實際暴露的發布腳本為pnpm release:cut # dispatch Release Appbumppatch pnpm release:cut minor # 或 major pnpm release:cut:watch # dispatch 后實時 tail 運行日志 pnpm release:review # 健康檢查占位符完好、opencode pin 存在 pnpm release:rollback # 回滾已發布的版本release:cut對應 scripts/release/cut.mjs其參數解析邏輯cut.mjs#L20-L24確認默認 bump 類型是patch支持--version X.Y.Z顯式指定版本支持--dry-run與--watch。腳本先檢查gh auth status然后執行gh workflow run Release App --repo repo -f bumppatch或-f versionX.Y.Z完成 dispatch。發布前的閘門先處理 open fix PR 與 fork PR發布前有一個強制前置步驟來自SKILL.md其起因是 2026-09-09 一次空白窗口回歸修復 PR 滯留一天后才被 tag 的事故fork 分支的 PR 永遠不會獲得 Warden 清障warden.yml跳過 fork PR而warden-clearance.yml要求head_repository repository因此必須主動列出上一個穩定 tag 之后、針對dev打開、標題或正文匹配fix(app)|crash|blank|white screen|regression|first launch的 PR該時間窗口內創建或更新的所有 fork PR任意歷史的、描述崩潰或啟動失敗類 bug 的 open fork PR。對每一個命中的 PR必須明確三選一并記錄在案先合并再 tag、照常發布但記錄已知未合并修復清單放入 changelog 自動打開的 release notes PR 的Known open fixes小節或臨時寫入 release body、判定與本次無關也要占一行避免下次發布重復排查。空清單也要記錄Known open fixes: none matched。帶著非空清單且無記錄決定就 tag正是這一步要阻止的失敗模式。完整發布流程六步走release.md給出了端到端的六步流程第 1 步基于干凈的origin/dev工作先git fetch origin/dev且只從基于其當前 tip 的干凈 checkout 工作。如果當前 checkout 是臟的或dev已經被檢出就創建一個隔離的 release worktree原 checkout 保持不動。這條紀律保證了發布操作永遠不會污染開發者自己的工作區。第 2 步準備發布prepare依次執行pnpm release:prepare:dry -- bump pnpm release:prepare -- bump在隔離分支 worktree 中只有獨立確認該分支基于當前origin/dev且 worktree 干凈后才可加--ci。與當前倉庫腳本的關系release.md中描述的release:prepare/release:ship及其伴隨的 backfill PR 屬于提交式發布流程。而 docs/RELEASING.md 的 History 小節說明自 2026-08 起發布已演進為commit-freetag 驅動模式當前倉庫以release:cutdispatch為主線不再需要 bump 提交與 backfill PR。閱讀本文時可將第 2、3 步理解為命令文檔對發布準備動作的完整描述實際執行以倉庫當前的pnpm release:cut為準。第 3 步執行發布ship執行pnpm release:ship。其中一步——向受保護的dev直接推送被拒絕——是預期行為release:ship必須推送release/vX.Y.Z-dev-sync分支并打開 backfill PR。任何情況下不得繞過或強推dev。第 4 步盯到 Release App 跑完Release App工作流必須完整跑完。在Publish GitHub Release成功且 release 變為公開之前發布不算完成——draft 狀態下的 release 對組織安裝入口和更新門禁都是不可見的。第 5 步合并 backfill PR處理 AUR PR讓版本 backfill PR 獲得批準并合并。若工作流打開了 AUR 打包 PR報告其 URL、等待其合并然后按 release 技能描述的規則用同一個 tag 重跑Release App。第 6 步驗證公開資產驗證公開 release 資產可解析、npm view openwork-server version與 tag 一致、最新的 Daytona snapshot 運行是綠的。最后報告以下信息tag、release URL、workflow 判定、已合并的 backfill PR、npm 版本、公開資產檢查結果以及任何非阻塞渠道的狀態。不要把 Node 運行時棄用警告或預期的受保護分支拒絕當作發布失敗去診斷——它們屬于正常現象。分支保護兩條發布路徑docs/RELEASING.md詳細說明了保護機制的實際形態dev分支對所有人包括 admin受保護要求 PR、1 個 approval、approval 必須來自非最后推送者、提交簽名、線性歷史。tag 驅動發布根本不觸碰dev因此沒有 backfill 需求。v*tag 創建受限admin 與 GitHub Actions 主體創建 tag 的工作流可以創建。由此形成兩條進入路徑路徑 ADispatch默認——pnpm release:cut。tag 創建在origin/devHEAD 上所以發布出去的代碼一定是經過評審的代碼。路徑 BTag-first緊急僅 admin——當必須立即發布一個尚未上dev的提交如 incident response時git tag vX.Y.Z sha git push origin vX.Y.Ztag 精確指向實際發布的代碼沒有 bump 提交。Expedited Release Audit工作流會在已發布 tag 的提交不在dev上時自動打開事后評審 issue之后應通過正常評審 PR 把相同改動落到dev閉環。Release App 工作流內部機制源碼級Release App定義在 .github/workflows/release-macos-aarch64.yml1288 行觸發方式包括v*tag 推送與workflow_dispatchdispatch 輸入包括bumppatch/minor/major默認 patch、version顯式版本覆蓋 bump、tag恢復重跑已存在 tag、draft默認 true、prerelease、notarize、publish_npm、publish_daytona_snapshot、build_electron、sign_windows、benchmark_only等。其核心作業鏈如下resolve-release版本計算與 tag 創建版本計算使用 scripts/release/versions.mjsreadStableTagVersions()讀取全部v*taghighestStableVersion()取最高穩定版本bumpStableVersion(version, type)按 patch/minor/major 遞增versions.mjs#L57-L65。tag 創建在origin/devHEAD 上。關鍵在于GitHub 內置的 Actions app不能作為 ruleset bypass actorGitHub 會拒絕所以工作流用 org 擁有的diff-wardenGitHub Appv*tag ruleset 的 bypass 名單成員通過REST API創建 tag ref——token 來自WARDEN_APP_IDWARDEN_PRIVATE_KEYwarden-clearanceenvironment。該 environment 的部署策略dev v* tag保證 key 只能被已評審代碼觸達feature 分支上的工作流改版既不能刪掉權限檢查也拿不到 key。app 創建的 tag 會再次觸發本工作流push事件但重復運行被 actor 守衛github.actor ! diff-warden[bot]跳過——dispatch 運行才是發布運行。dispatch 還受權限門禁約束Require release permission步驟workflow#L123-L143要求 dispatch 者是 repo admin或在RELEASE_MANAGERS變量逗號分隔的登錄名中。若 app token 不可用回退到GITHUB_TOKENpush tag通常會被 ruleset 拒絕并給出明確失敗指引。verify-releasetag 與占位符校驗scripts/release/verify-tag.mjs 校驗嚴格穩定格式vX.Y.Zprerelease 永遠不會通過 Release App 發布、tag 在 clone 中存在需要 fetch-depth: 0且 fresh 模式下必須嚴格大于其它所有穩定 tagverify-tag.mjs#L41-L53。恢復重跑使用--mode recovery跳過單調性檢查。node scripts/release/review.mjs --strict守衛占位符三個package.json必須仍是0.0.0-dev并檢查constants.json中的 opencode 版本 pin 存在review.mjs。構建矩陣版本蓋章與 18 個 electron legs構建作業 checkouttag 本身源碼永遠 pin 到 tag恢復重跑時 workflow 定義從 dispatch ref 運行因此工作流文件的修復會自動生效而 shipped 代碼保持 tag 所指向的內容不變。scripts/release/stamp-version.mjs 把版本寫入 CI 工作區內的apps/{app,desktop,server}/package.jsonSTAMPED_PACKAGE_PATHSstamp-version.mjs#L17-L21這就是 electron-builder、app.getVersion()、Vite renderer bundle 與openwork-servernpm 發布共同讀取的版本來源。構建矩陣包含 macOS/Linux/Windows 三平臺 × x64/arm64 兩種架構 × public/cloud/enterprise 三種分發配置共 18 個 leg分別使用 electron-builder.yml、electron-builder.cloud.yml、electron-builder.enterprise.yml。macOS 強制 notarize未配置 Apple 簽名密鑰直接失敗Windows 安裝包經 Azure Artifact Signing 簽名sign_windows開關簽名后用 refresh-signed-windows-artifacts.mjs 刷新 blockmap 與 manifest。每個 leg 有belt-and-braces斷言產物文件名必須攜帶$RELEASE_VERSION防止蓋章失敗導致0.0.0-dev產物被靜默發布。public 分發之外的 custom 分發cloud/enterprise會把latest*.yml歸一化為cloud*.yml/enterprise*.yml避免更新通道串味。publish-release翻轉 draft 即發布時刻Publish Electron Assets GitHub Release作業workflow#L973-L1048在 electron 矩陣、electron 資產、npm 發布全部就緒后將 release 從 draft 翻轉為--latest或--prerelease并輸出published_stabletrue隨后 dispatchchangelog.yml生成 changelog PR 與 release notes。發布門禁放行/阻塞清單條件是否阻塞發布electron 矩陣18 legs構建上傳阻塞electron 資產與 updater manifest 存在阻塞latest*.yml未發布時桌面 updater 404 是預期的自愈openwork-servernpm 發布阻塞Publish AURcontinue-on-error不阻塞aur.archlinux.org 故障不算發布失敗AUR 發布用 CI 工作區渲染提交的 packaging/aur 模板pkgver0.0.0 真實版本與校驗和只推送到 AUR remote倉庫零改動Build Push Daytona Snapshot不阻塞快照事后可用同一 tag 重跑重建den-api 的運行時版本發現發布公開后組織側如何拿到新版本ee/apps/den-api/src/desktop-releases.ts 在運行時讀取 GitHub Releases API緩存 TTL 5 分鐘desktop-releases.ts#L7排除 draft 與 prerelease——因此回滾降級會立即把版本從發布列表移除。提交的 generated/desktop-versions.ts 只是冷啟動/離線回退快照可偶爾用node scripts/release/generate-desktop-versions.mjs --version latest刷新MIN_SUPPORTED_DESKTOP_VERSION策略常量定義在 generate-desktop-versions.mjs。org 安裝門/v1/install/:platform302 到帶版本的資產因此桌面安裝包的修復只有通過新 release 才能觸達用戶。發布后驗證清單gh run list --repo repo --workflow Release App --limit 3 gh release view vX.Y.Z --repo repo # 必須是 published不是 draft gh release view vX.Y.Z --repo repo --json assets --jq .assets[].name核對要點Release非 draft且標記為 Latest資產數量正確macOS Linux Windows updaterlatest*.ymlmanifestmanifest 未發布時桌面 updater 會 404npm view openwork-server version顯示新版本curl -s https://api.openworklabs.com/v1/app-version在 den-api 緩存刷新后≤5 分鐘列出新版本資產抽查curl -sIrelease 下載 URL 返回 302指向 release-assets CDN期望出現的典型資產openwork-mac-arm64-X.Y.Z.dmg、openwork-mac-x64-X.Y.Z.dmg、openwork-win-x64-X.Y.Z.exe。故障恢復與重跑重跑已存在 tag基礎設施故障、回放 AUR/Daytonagh workflow run Release App --repo repo -f tagvX.Y.Z恢復運行跳過 tag 創建與單調性檢查源碼 pin 到 tag工作流文件修復自動從dev生效workflow 定義從 dispatch ref 運行。已 tag 但發布前發現缺陷保持 release 為 draft 或刪除gh release delete vX.Y.Z在dev上修復后切下一個 patch。若壞版本已到 npm執行npm deprecate openwork-serverX.Y.Z reason — use X.Y.Z1。回滾已發布的版本當壞版本已published且標記 Latest 時使用release:rollback流程第 1 步止血stop the bleedpnpm release:rollback pnpm release:rollback --bad vX.Y.Z --execute先 dry-run 再執行。執行時必須 pin--bad——成功回滾后goodrelease 成為 Latest裸跑會把 good 誤選為 bad。腳本邏輯在 scripts/release/rollback.mjs自動選擇低于壞版本的最高已發布穩定 release 作為目標selectRollbackTarget把 Latest 從壞版本重指向目標版本把壞版本降級為 prerelease資產與 tag 保留——這同時把版本從 den-api 的運行時發布列表移除org 安裝與更新門禁在緩存窗口內停止提供它在壞版本 release notes 前置回滾橫幅 ?? Rolled back on date. Do not install; use target instead.rollback.mjs#L120-L123重復執行冪等hasRollbackBanner檢測已存在橫幅。第 2 步為已更新客戶端重新發布Updater 拒絕降級。把最后 good 提交打一個高于壞版本的 tag 即可——無需提交、無需 worktreegit tag vX.Y.Z1 last-good-tag git push origin vX.Y.Z1第 3 步deprecate npmnpm deprecate openwork-serverbad-version rolled back — use next客戶端狀態恢復手段尚未更新第 1 步即可修復已更新只有第 2 步能修復撤銷出問題的 PR 走dev上的正常評審 PR 流程該清理不在用戶恢復的關鍵路徑上。版本信息速查問題答案存在哪些版本git tag --list v*/ GitHub Releases最新版本gh release view --json tagNamevX.Y.Z 是哪個提交git rev-parse vX.Y.Z當前 checkout 是什么版本git describe --tagspackage.json 故意顯示0.0.0-dev受支持的最老桌面版本MIN_SUPPORTED_DESKTOP_VERSIONgenerate-desktop-versions.mjs 中的提交策略唯一的例外pull-only 評估棧packaging/docker/docker-compose.eval.yml 按versiondigestpin 了 den-api 與 den-web 鏡像。在Publish EE Artifacts推送穩定 tag 鏡像后用 pin-compose-images.mjs 更新 pin含 docs 提交 sha 校驗和check-compose-pins.mjs 在 tag 存在后校驗{ok:true,...}——pin PR 與 changelog PR 一樣跟隨發布不屬于切版本本身。Troubleshooting 速查表癥狀原因修復運行在推送 tag 時失敗diff-warden app 不在v*ruleset bypass 名單或其 secrets 未設置重新添加 appSettings → Rules/ 恢復WARDEN_APP_IDWARDEN_PRIVATE_KEY或 admin 手動 push tag 后重跑全新 cut 報Tag vX.Y.Z already exists版本已發布用-f tagvX.Y.Zrecovery重跑或選更高版本verify-release單調性失敗手動 tag 低于已存在 release選擇高于當前最高穩定 tag 的版本release:review占位符檢查失敗有人把真實版本提交進了 package.json恢復0.0.0-dev——CI 從 tag 蓋章版本桌面應用對新版本 updater 404tag 存在但 release 仍是運行中的 draft等待Publish GitHub Release自愈僅 AUR / Daytona 標紅外部渠道故障release 照常發布渠道恢復后用同一 tag 重跑全部electron-linux-*編譯原生模塊失敗原生模塊需適配新 Electron 頭文件raw-V8全 workspace 的原生依賴收斂到同一個基于 N-API 的大版本見 #3561/#3563 的教訓Electron 35→43 升級時apps/server停在 better-sqlite3 v12 而 desktop 已到 v13electron-builder 會重建找到的每一份原生模塊副本導致三次發布標紅最終收斂到 v13 并用bun:sqlite解決Windows afterPack 報Missing staged MCP runtime packageasar 路徑分隔符不匹配已修復——normalizeAsarEntryPathelectron-after-pack.cjs發布成功后的最后一道關validate-a-release資產公開后、對外宣布版本安全可鋪開之前運行 .opencode/skills/validate-a-release/SKILL.md 技能用已發布 mac-arm64 zip 啟動 enterprise 與 cloud 二進制覆蓋packaged-first-launch全新安裝與released-enterprise-activated激活安裝、舊版本 profile 被新構建打開等場景核對 updater manifest 的 sha512并驗證簽名/notarization。歷史演進為什么是現在這套設計2026-08發布變成 commit-free——tag 是唯一版本來源CI 蓋章工作區den-api 運行時讀取已發布 releaseAUR 渲染已提交模板。此前每次發布都需要版本 bump 提交、dev backfill PR 和 AUR 打包 PR。2026-08-05v0.18.15/v0.18.16Electron 35→43 升級引發三次發布標紅根源是原生依賴版本分裂最終通過 workspace 收斂統一 N-API 大版本并讓opencode-db在 Bun 下使用bun:sqlite解決。這套 tag 驅動的設計把發版收斂為一個不可變的 tag 一條可觀測的 CI 管線版本語義由versions.mjs單點計算發布完整性由verify-tag.mjs與review.mjs --strict把關公開與否由publish-release一個作業決定回滾則是重指 Latest 降級 橫幅三個 gh 調用。理解這條鏈路就能在 OpenWork 上安全地執行從 patch 到回滾的每一次發布操作。【免費下載鏈接】openworkThe open-source alternative to Claude Cowork (powered by opencode)項目地址: https://gitcode.com/GitHub_Trending/ope/openwork創作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考