Skip to content

ci(release): publish no snapshot for a push with nothing user-facing - #606

Merged
whes1015 merged 1 commit into
mainfrom
ci/snapshot-only-when-user-facing
Oct 11, 2026
Merged

whes1015 merged 1 commit into
mainfrom
ci/snapshot-only-when-user-facing

Conversation

@whes1015

Copy link
Copy Markdown
Member

這個 PR 做了什麼

推上 main 的 commit 裡沒有任何更新日誌條目(New/Optimization/Fix(…))時,不再發快照。不發快照就代表不會有 GitHub pre-release、不會上傳 Play、不會送 TestFlight。這種 push 改由 android.yml、ios.yml 編譯,main 上每個 commit 仍然一定有人編譯。

判斷標準:從上一個 tag 到這次的 commit 之間,有沒有任何更新日誌條目。這跟 release note 的範圍完全相同,所以「不發版」剛好就是 note 原本只會寫「沒有使用者可見的變更。」的情況。被跳過的 commit 不會遺失,下一次有條目的 push,note 會從同一個 tag 算起。

手動觸發(workflow_dispatch)和 v* tag 照樣發版。

改動內容

  • tool/release/notes.sh:新增 --any [<range>] 模式,有條目回 0、沒有回 1。用的是跟產生 note 同一個正規表示式,所以各個 workflow 對「使用者可見」的判斷不會不一致。一般模式的輸出跟改之前逐字相同(同一組 label/code 比對過)。
  • release.yml:version job 新增 Anything to publish 步驟;build 只在要發版時才跑,publish 依賴 build,會跟著跳過。
  • android.yml、ios.yml:多了 push main 的觸發,只在 release 不發版時才編譯。push 時 checkout 用 blob:none,只讀 commit 訊息,不抓 70MB 的檔案內容。PR 上的行為完全不變。
  • README.md:把「每一次提交都會發布快照」改掉。

為什麼 android/ios 跟 release 問的範圍不同

android/ios 只看這次 push 自己帶的 commit;release 看的是從上一個 tag 到現在。這次 push 的 commit 一定落在 release 的範圍內,所以:

  • android/ios 判斷「release 會編」,release 就一定會編。
  • 最壞情況是兩邊都編,不會兩邊都不編。

如果直接照抄 release 的範圍會不安全。release 的 tag 在 run 的最後一步才打,而且 run 會排隊:push B 發生時,前一個 push A 的 release 還沒打 tag,A 的條目會讓 B 被判成「release 會編」;等 B 的 release 真的跑起來時,A 已經打了 tag,B 的範圍裡沒有條目,於是不發版。結果 B 兩邊都沒編。

相關 issue

沒有對應的 issue。

怎麼驗

  • notes.sh --any 對 main 最近 12 個 commit 逐一判斷,結果跟每個 commit 實際有沒有條目一致:fix(sponsor)、perf(data) 等回 0;ci:、test:、docs:、refactor(eew) 回 1。範圍不存在時回 1,也就是偏向編譯的安全方向。

  • 從 workflow 裡抽出實際的步驟腳本,在 scratch clone 模擬:

    情況 release 發版 android/ios 編譯
    push 只有 ci: 否 是
    push 有 fix: 和條目 是 否
    push B 在 A 的 release 還在排隊時到達,A 之後順利發版 否 是
    同上,但 A 的 release 失敗、沒有 tag 是(帶 A 的條目) 是
    v* tag 是 —
    手動觸發 是 —
  • actionlint 1.7.12、tool/check/tooling.sh、tool/check/layering.sh、tool/check/commits.sh origin/main..HEAD 都通過。

  • PR 上 android/ios 不會有任何差別,push main 的部分要合併後才看得到:合併這個 PR 本身就是一次沒有條目的 push,應該會看到 release 的 Anything to publish 顯示 no snapshot,build、publish 跳過,Android 和 iOS 則由 android.yml、ios.yml 編譯。

lib/features/changelog/ 有幾個註解寫著「每次 push 都會發快照」,用來說明分頁的理由。這個理由現在仍然成立(快照只會增加),程式也沒有依賴這個假設,所以這個 PR 沒有動 app 程式碼。

檢查清單

  • tool/check/commits.sh origin/main..HEAD 通過
  • 一個 commit 一件事
  • mise exec -- flutter analyze 與 mise exec -- flutter test 通過(只改 workflow、腳本和 README,交給 CI)
  • 新的使用者可見字串都走 AppLocalizations(沒有新字串)
  • 有 UI 變更的話(沒有 UI 變更)

Every push to main published a snapshot: a GitHub pre-release, a Play
upload and a TestFlight build. So a ci:, docs:, test: or refactor: push
went out to testers as a build whose whole note was "no user-facing
changes", and spent a store build number on it.

A push now publishes one only when a commit since the last tag carries
a changelog entry: exactly the case where the snapshot note has
something to say. The commits it skips are not lost; the next push
that does bring an entry runs its note from the same tag. A run started
by hand still publishes, and so does a v* tag.

android.yml and ios.yml built pull requests only, on the grounds that
release.yml builds every push to main; that no longer holds, and a
chore(deps) bump pushed straight to main would have been compiled by
nothing. They now also run for a push to main that publishes nothing.
They ask about the push's own commits, which always fall inside the
range release.yml asks about, so a push is built by release.yml, by
them, or at worst by both, never by neither. Asking release.yml's own
question instead would not be safe here: its tag is pushed at the end
of a run, and a run queued behind another sees a tag the push did not.

All of them ask through tool/release/notes.sh --any, which reads
entries with the same expression the note does, so they cannot
disagree on what counts as user-facing.
@whes1015
whes1015 merged commit 6e27209 into main Oct 11, 2026
@whes1015
whes1015 deleted the ci/snapshot-only-when-user-facing branch October 11, 2026 17:20
@codecov

codecov Bot commented Oct 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.26%. Comparing base (d32c91d) to head (cb9f91b).
⚠️ Report is 1 commits behind head on main.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant