跳到內容

發佈

本頁寫給檢查或發佈 Graft 的貢獻者。

在專案的 devenv shell 中執行每一個命令:

Terminal window
devenv shell -- pnpm install
devenv shell -- pnpm build
devenv shell -- pnpm typecheck
devenv shell -- pnpm test
devenv shell -- pnpm test:packages

進入該 shell 時會用 treefmt 格式化程式碼。pnpm test:packages 測試發佈腳本。

CLI 的建置也會寫出 packages/cli/schema.json,也就是設定檔的 JSON Schema,由載入器的項目欄位和 CLI 登記的 intercept 產生。它不會提交到版本庫;每次發佈都會打包建置時產生的那一份。

pnpm test 會檢查所有發布入口是否引用了無法從公開入口存取的型別,並為不寫型別註記的使用範例產生宣告檔。檢查失敗時,應從公開簽名中移除實作細節,或補上公開契約型別的匯出;不要替範例加上註記來避開問題。

工作流程 .github/workflows/ci.yml 會在 pull request、推送到 main,以及 v1.2.3 或 v1.2.3-beta.0 這類標籤時執行。

工作 執行時機 作用
check 一律 檢查格式、建置、型別檢查、測試,並打包每個公開套件。
github-packages 推送和標籤 將打包好的檔案發佈到 GitHub Packages。
npm 標籤 透過受信任的發佈,將打包好的檔案發佈到 npm。

發佈工作只會在 check 通過後執行。它們發佈的正是 check 打包並測試過的檔案,絕不會再次建置。

每個 registry 都有固定的工作並行群組,設定為 cancel-in-progress: false 和 queue: max。

Registry 群組
npm publish-npm
GitHub Packages publish-github-packages
  • 範圍。 群組涵蓋整個發佈工作:讀取標籤、選擇標籤、上傳套件和處理重試。不同版本不能在同一個 registry 上混用這些操作。
  • 獨立性。 兩個 registry 有各自獨立的佇列,可以同時發佈。
  • 順序。 佇列順序依工作開始等待的時間,而不是版本順序,所以仍然需要版本比較。
  • 容量。 使用 queue: max 時,GitHub 並行佇列最多保留 100 個等待中的工作。佇列已滿時,GitHub 會取消多出來的工作,所以請檢查 Actions 的執行紀錄中是否有被取消的發佈工作,並在佇列清空後重新執行。沒有 queue: max 時,GitHub 只保留一個等待中的工作,第三個工作會取代它。

所有套件以同一個版本一起發佈。pnpm packages:pack 會在每個公開套件中設定該版本,將它們之間的相依項目固定到該版本,把套件打包到 .release/,並將每個檔案的雜湊寫入 .release/release.json。

事件 版本 npm 標籤 發佈到
推送到 main 0.0.0-commit-<full hash> sha-<full hash> GitHub Packages
v1.2.3-beta.0 類標籤 1.2.3-beta.0 alpha、beta 或 rc GitHub Packages 和 npm
v1.2.3 類標籤 1.2.3 latest GitHub Packages 和 npm

預發佈標籤會指明它的頻道:alpha、beta 或 rc,後面接一個數字。它的套件放在該頻道的 npm 標籤之下,絕不會成為 latest,所以 npm install @graftland/graft 仍然安裝最後一個穩定版本。

你想要… 執行
預發佈版本 npm install @graftland/graft@beta
main 的任一個 commit npm install @graftland/graft@0.0.0-commit-<full hash> --registry=https://npm.pkg.github.com

commit 快照請使用工作流程執行時的版本。即使是公開套件,GitHub Packages 也需要具有 read:packages 的 token。首次發佈到那裡的套件可能是私有的;請在 GitHub 的套件設定中設定一次可見性。

你可以在同一個 registry 佇列下重新執行發佈。

情況 npm GitHub Packages
版本已存在且內容相同 略過。標籤不會變更。 略過。如果不會讓標籤倒退,它可以修復其頻道標籤。
版本已存在但內容不同 腳本停止。 腳本停止。
標籤遺失或被外部變更 具有標籤權限的維護者在相同的獨佔發佈規則下另行修復。重新執行工作不會修復它。 如上所述修復。

npm 受信任的發佈者只有發佈權限,所以重試絕不會呼叫 npm dist-tag。

因為發佈一次只執行一個,latest、alpha、beta 和 rc 絕不會退回較舊的版本。

  • 首次上傳和 GitHub 標籤修復,使用同一種 SemVer 優先順序,與目標頻道目前的版本比較。
  • 數字型的預發佈識別符以數字比較(beta.10 比 beta.2 新)。主版本、次版本和修補版本先於預發佈序列。建置中繼資料不影響優先順序。
  • 腳本以明確的 @<channel> 選擇器讀取完整的 dist-tags 物件,因此只有預發佈版本的套件不需要 latest 標籤。
  • 頻道不存在(E404)時可以建立。只有預發佈版本的套件還沒有 latest,這時改用 npm dist-tag ls 讀取它的標籤,第一個正式版本同樣會建立 latest。成功但內容為空或格式錯誤的回應會讓發佈停止。
  • 再次執行頻道上已有的版本,標籤保持不變。

如果新上傳的版本比該頻道目前的版本舊,Graft 仍會用後備標籤發佈該套件:

發佈類型 後備標籤
穩定版 backport
預發佈版 alpha-backport、beta-backport 或 rc-backport

這些標籤標示較晚的上傳,不保證會跟隨最新版本。要安裝較舊的版本,請使用確切的版本號。再次執行較舊的既有版本,不會移動它的頻道,也不會修復後備標籤。例如,如果你在 0.2.0-beta.1 之前發佈 0.2.0-beta.2,或之後再次執行 beta.1,beta 仍停留在 beta.2。

  1. 確認 main 通過 CI。

  2. 為該 commit 加上標籤並推送,例如 v1.2.3。Graft 還在 0.x 階段時直接發佈一般版本,例如 v0.3.0:0.x 版本號本身就表示 API 可能變動,不需要再加 -beta 後綴。 v1.2.3-beta.0 這類預發佈標籤仍可使用:

    Terminal window
    git tag v1.2.3
    git push origin v1.2.3
  3. npm 工作會等待 npm 環境(如果它需要核准),然後發佈。

npm 工作使用 npm 的受信任發佈:npm 接受工作流程執行的 OIDC token,而不是存取 token,並為每個套件加上來源證明。版本庫不保存任何機密。每個套件都信任 npm 環境中 graftland/graft 的 ci.yml 工作流程:

Terminal window
npm trust github @graftland/graft --file ci.yml --repo graftland/graft --env npm --allow-publish
npm trust list @graftland/graft

npm 只能信任已經存在的套件。維護者要先用 CI 打包的檔案發佈一次新套件,之後再設定信任:

Terminal window
gh run download <run id> --name packages-<commit hash> --dir .release
npm login
devenv shell -- pnpm packages:publish npm

工作流程 .github/workflows/docs.yml 從 packages/docs 建置本網站,並部署到Cloudflare Pages:graft-docs-ekb.pages.dev。main 上的每個 commit 和每個發佈 tag 都會保留當時的文件。

位址 內容
https://graft-docs-ekb.pages.dev/ main 上最新的 commit。
https://<hash 前 12 碼>.graft-docs-ekb.pages.dev/ 該 commit,永久保留。
https://versions.graft-docs-ekb.pages.dev/versions.json 所有已部署的 commit,及其日期、標題和 tag。
https://graftland.github.io/graft/<path> 重新導向到正式網站的 <path>。
觸發方式 建置 之後
推送到 main 推送的 commit。 加入清單,並設為正式網站。
推送 v1.2.3 這類 tag tag 指向的 commit,僅在它還沒有文件時。 在清單中為該 commit 標上 tag。
在 Actions 分頁勾選 backfill 文件網站出現以來 main 上的每個 commit 和每個 tag 中還沒有文件的。 加入清單;正式網站不變。
在 Actions 分頁填寫 rebuild 填寫的 commit,即使它們已有文件。 取代它們的部署並更新清單。
  • 每個 commit 只建置一次。 使用該 commit 自己的 lockfile 與工具鏈建置,上傳後不再取代。正式網站是同一份建置再上傳一次,Cloudflare 會略過已有的檔案。
  • 順序。 各次執行逐一更新清單。正式網站只會前進到目前 commit 的後代,較晚完成的執行不會讓它倒退。
  • 失敗。 已經無法建置的 commit 會被略過,其他 commit 照常部署。讀取線上清單失敗時,執行會停止,而不是建立新的清單。
  • 上限。 一次 backfill 最多建置 256 個 commit,其餘的再執行一次。

每個已部署的頁面都從版本位址載入下拉選單,所以在它出現之前建置的版本也有。

  • 下拉選單。 在主題選單旁邊。由新到舊列出所有已部署的 commit,顯示 tag 或短 hash,選取後開啟同一頁面在該版本中的位址。當時還不存在的頁面會顯示該版本的 404 頁。
  • 提示。 不是正式網站 commit 的頁面頂端會說明這一點,並連結到最新文件中的同一頁面。
任務 做法
Cloudflare 專案 執行一次 npx wrangler pages project create graft-docs --production-branch main,再把 Cloudflare 分配的 *.pages.dev 名稱填入工作流程的 DOCS_PAGES_HOST 和 DOCS_URL。
docs 環境的 secret CLOUDFLARE_API_TOKEN(需要 Cloudflare Pages: Edit 權限)和 CLOUDFLARE_ACCOUNT_ID。
舊位址 將版本庫的 Pages 來源設為 GitHub Actions。
補齊以前的文件 在 Actions 分頁對 main 手動執行該工作流程,並勾選 backfill。
在本機處理網站 devenv shell -- pnpm --filter @graftland/docs dev;下拉選單只出現在已部署的頁面上。
語言 資料夾
英文 packages/docs/content/docs
簡體中文 packages/docs/content/docs/zh-cn
繁體中文 packages/docs/content/docs/zh-tw
  • 每個資料夾使用相同的檔名。
  • 頁面之間使用相對連結,例如 ../plugins/,這樣連結才能在網站的 base path 下正常運作。
  • 優先使用表格、編號步驟和簡短清單,而不是冗長的段落。頁面開頭先說明涵蓋的內容,結尾指出接下來可以去哪裡。
  • 每個 README 旁邊都有 README.zh-CN.md 和 README.zh-TW.md 翻譯,依英文 README 撰寫。如果你修改英文 README 或英文文件頁面,請在同一次變更中更新翻譯。