From 38294d8bde1fe5621baa3a9326a5e9c18c0dca04 Mon Sep 17 00:00:00 2001 From: Hoshi <132435834+hoshimoe@users.noreply.github.com> Date: Fri, 21 Aug 2026 22:16:20 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=E6=8E=83=E6=8F=8F=E6=8E=9B=E5=9B=9E=20PR?= =?UTF-8?q?=E3=80=81=E8=8D=89=E7=A8=BF=E4=B9=9F=E8=B7=91=20CI=EF=BC=8C?= =?UTF-8?q?=E4=B8=A6=E4=BF=AE=E6=8E=89=E4=B8=80=E6=AE=B5=E6=8C=87=E8=91=97?= =?UTF-8?q?=E6=A2=9D=E6=96=87=E8=AA=AA=E8=87=AA=E5=B7=B1=E4=B8=8D=E5=BF=85?= =?UTF-8?q?=E7=85=A7=E8=BE=A6=E7=9A=84=E8=A8=BB=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI 成本不再是判準(使用者裁示 2026-08-21,Enterprise 50k 分鐘/月), 判準收斂成一句:CI 做得到的驗證,就讓它在合併前跑。 - security.yml:那條 `if: github.event_name != 'pull_request'` 拆掉。 2026-08-16 那個取捨的前半仍然成立(這幾種找到的東西是修一次就結束的), 失效的是後半——省下的分鐘數值 0,而「在 main 才被攔下 = 已經合併」的 代價一直都在。 - ci.yml 的檔頭:草稿 PR 也跑 CI。舊註解寫著「草稿不跑(下面每個 job 的 if)」,而那個 if 十五個倉庫裡只有兩個真的有——註解描述的是一件沒有 發生的事,而且方向是「以為更省」,所以不會有帳單也不會有紅燈讓人發現。 - security job 上方那段註解:它寫著「本倉庫是公開的,所以掃描與基礎驗證 同時起跑,不等它綠燈」,並聲明「兩種形狀是刻意的,不是漂移;判準見 workspace AGENTS.md §1.9.1」。那段文字從 2026-08-16 起就是錯的,而且 取代它的 needs: 一直都在,就在同一個 job 裡下面幾行。一段指著條文說 自己不必照辦的註解比沒有註解更糟:讀到的人會以為這裡已經對照過了。 本倉庫沒有 Go 程式,所以這一輪的覆蓋率量測不適用。 決策見 workspace decisions/infrastructure/CI-成本不再是判準.md。 --- .github/workflows/ci.yml | 35 ++++++++++++++++++++------------- .github/workflows/security.yml | 36 +++++++++++++++++++--------------- 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9dd7dfb..7200a2c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,12 +12,17 @@ name: CI on: push: branches: [main] - # 開了 PR 就在合併前先驗一次,但**草稿不跑**(下面每個 job 的 `if`)。 - # 迭代期間開成 draft,改好再標 ready for review——那一刻才觸發。 + # 開了 PR 就在合併前先驗一次,**草稿也跑**(裁示 2026-08-21)。 # - # 這與「工作分支的頻繁推送不該花 CI」並不衝突:沒有開 PR 的分支不會觸發, - # 開了 PR 但還是草稿的也不會。換到的是**合併前就知道壞了**, - # 而不是像 2026-08-08 那次要等合併後才發現 hoshi-deploy 是紅的。 + # 沒有開 PR 的分支仍然不會觸發,所以「工作分支的頻繁推送不該花 CI」照舊 + # 成立;改掉的是草稿那一段。草稿不跑換到的是迭代期間省下的分鐘數,而升上 + # Enterprise 之後那不是收益;付出的是**最需要早點知道的那個階段沒有網子**。 + # + # > **註**:這段註解在 2026-08-21 之前寫著「草稿不跑(下面每個 job 的 + # > `if`)」,而那個 `if` **十五個倉庫裡只有兩個真的有**(hoshi-build 與 + # > hoshi-standards)。也就是說十三個倉庫的草稿 PR 一直都在跑 CI, + # > 註解描述的是一件沒有發生的事。它的方向是「以為更省」, + # > 所以不會有任何帳單或紅燈讓人發現它——**一份說謊的註解不會自己壞掉**。 pull_request: branches: [main] types: [opened, synchronize, reopened, ready_for_review] @@ -54,17 +59,19 @@ jobs: - run: npm run build - # **本倉庫是公開的,所以掃描與 `build` 同時起跑**,不等它綠燈。 - # - # 公開倉庫的 Actions 分鐘數不計費,所以「基礎驗證紅燈時整組 skipped、 - # 省下執行器時間」在這裡換不到任何東西,只換到更晚才知道掃描的結論。 - # 代價要講清楚:建置壞掉時 CodeQL 的 autobuild 會吐同一個錯誤換一種包裝, - # 所以一顆真的紅燈會伴隨一顆指向同一個根因的紅燈。 + # 安全掃描接在基礎驗證之後:基礎驗證紅燈時整組 **skipped**,而不是拿一份 + # 編譯不過的原始碼去跑掃描,再收到一顆與根因無關的第二紅燈。 # - # **私有倉庫維持 `needs:` 那道閘**——那裡的分鐘數要付錢。兩種形狀是刻意的, - # 不是漂移;判準與理由見 workspace `AGENTS.md` §1.9.1。 + # > **註**:這段文字到 2026-08-21 為止寫的是「**本倉庫是公開的,所以掃描與 + # > 基礎驗證同時起跑**,不等它綠燈」,理由是公開倉庫的 Actions 分鐘數不計費。 + # > 那個形狀在 2026-08-16 就被取代了,而**取代它的 `needs:` 一直都在** + # > (就在下面幾行,還帶著自己的註解)——沒有跟上的只有這段文字。 + # > + # > 它還聲明「兩種形狀是刻意的,不是漂移;判準見 workspace `AGENTS.md` + # > §1.9.1」,而 §1.9.1 說的正好相反。**一段指著條文說自己不必照辦的註解, + # > 比沒有註解更糟**:它讓讀者以為這裡已經對照過了,於是沒有人去比對。 # - # 掃描本身的定義在 `security.yml`,那支同時還掛著每週排程。 + # 掃描本身的定義在 `security.yml`,那支同時還掛著每週排程(**不**經過這道閘)。 security: # **這一組在 PR 上也跑,但裡面只有 Gitleaks 會動**(裁示 2026-08-16)。 # diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 734ec1a..4a951f2 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -73,16 +73,18 @@ permissions: jobs: codeql: - # 這一種在 PR 上不跑(裁示 2026-08-16):找到的東西是「修一次就結束」的, - # 在 PR 攔下與在 `main` 攔下代價一樣。Gitleaks 沒有這一行——它是例外, - # 理由見 `ci.yml` 的 `security` job。 + # **在 PR 上也跑**(裁示 2026-08-21)。 # - # 用 `!= 'pull_request'` 而不是 `== 'push'`:後者會順手把排程與 - # `workflow_dispatch` 的手動掃描也關掉,而那兩個都是要用的。 + # 這裡從 2026-08-16 起有一條 `if: github.event_name != 'pull_request'`, + # 理由是「找到的東西是修一次就結束的,在 PR 攔下與在 `main` 攔下代價一樣, + # 所以省下每個 PR 數分鐘」。**那句話的前半仍然成立,後半不再是收益**: + # 升上 Enterprise 之後分鐘數不是稀缺的東西了。 # - # 被 `ci.yml` 呼叫時,這裡讀到的 `github.event_name` 是**呼叫端的**事件, - # 所以這個判斷成立。 - if: github.event_name != 'pull_request' + # 而代價一直都在:一個在 `main` 才被攔下的問題,是一個**已經合併**的問題。 + # 判準因此收斂成一句——**CI 做得到的驗證,就讓它在合併前跑。** + # + # 每週排程仍然留著,它回答的是另一個問題:**沒有動過的程式**今天有沒有 + # 變成有問題的(見上方 `on:` 的註解)。 name: CodeQL (${{ matrix.language }}) runs-on: ubuntu-latest timeout-minutes: 40 @@ -186,16 +188,18 @@ jobs: if-no-files-found: warn trivy: - # 這一種在 PR 上不跑(裁示 2026-08-16):找到的東西是「修一次就結束」的, - # 在 PR 攔下與在 `main` 攔下代價一樣。Gitleaks 沒有這一行——它是例外, - # 理由見 `ci.yml` 的 `security` job。 + # **在 PR 上也跑**(裁示 2026-08-21)。 + # + # 這裡從 2026-08-16 起有一條 `if: github.event_name != 'pull_request'`, + # 理由是「找到的東西是修一次就結束的,在 PR 攔下與在 `main` 攔下代價一樣, + # 所以省下每個 PR 數分鐘」。**那句話的前半仍然成立,後半不再是收益**: + # 升上 Enterprise 之後分鐘數不是稀缺的東西了。 # - # 用 `!= 'pull_request'` 而不是 `== 'push'`:後者會順手把排程與 - # `workflow_dispatch` 的手動掃描也關掉,而那兩個都是要用的。 + # 而代價一直都在:一個在 `main` 才被攔下的問題,是一個**已經合併**的問題。 + # 判準因此收斂成一句——**CI 做得到的驗證,就讓它在合併前跑。** # - # 被 `ci.yml` 呼叫時,這裡讀到的 `github.event_name` 是**呼叫端的**事件, - # 所以這個判斷成立。 - if: github.event_name != 'pull_request' + # 每週排程仍然留著,它回答的是另一個問題:**沒有動過的程式**今天有沒有 + # 變成有問題的(見上方 `on:` 的註解)。 name: Trivy runs-on: ubuntu-latest timeout-minutes: 25 From 940fa06fcabb1b2dd289c4b8e5aef76cbe8b75db Mon Sep 17 00:00:00 2001 From: Hoshi <132435834+hoshimoe@users.noreply.github.com> Date: Sat, 22 Aug 2026 12:35:32 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=E5=AE=89=E5=85=A8=E6=8E=83=E6=8F=8F?= =?UTF-8?q?=E9=82=A3=E6=AE=B5=E8=A8=BB=E8=A7=A3=E5=B7=B2=E7=B6=93=E9=81=8E?= =?UTF-8?q?=E6=9C=9F=EF=BC=9A=E5=AE=83=E6=8F=8F=E8=BF=B0=E7=9A=84=E9=96=98?= =?UTF-8?q?=E9=96=80=E5=9C=A8=202026-08-21=20=E5=B0=B1=E6=8B=86=E6=8E=89?= =?UTF-8?q?=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `security` job 的註解還寫著「**這一組在 PR 上也跑,但裡面只有 Gitleaks 會動**」,以及「閘門下移到被呼叫的那三個 job 上(`security.yml` 裡各自的 `if: github.event_name != 'pull_request'`)」。 **那三條 `if` 已經不存在了**——2026-08-21 隨「CI 成本不再是判準」一起拆掉, 四種掃描現在在 PR 上全部會跑。`security.yml` 自己的註解是對的(它用過去式 記下了那條閘為什麼被移除),沒有跟上的只有呼叫端這一段。 這正是同一個檔案下面幾行已經記過的那個形狀:**一段描述著不存在的機制的 註解,比沒有註解更糟**——讀者會以為這裡已經對照過了,於是沒有人去比對。 而它不會有任何症狀:workflow 照跑,掃描照綠。 改成用過去式記下那個取捨的哪一半失效了(分鐘數不再稀缺,而 「在 `main` 才攔下=已經合併」的代價一直都在),並講明 `needs:` 那道閘為什麼**與成本無關**、所以照樣留著。 十五個倉庫同一段,一起改。 --- .github/workflows/ci.yml | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7200a2c..24219cc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,22 +73,23 @@ jobs: # # 掃描本身的定義在 `security.yml`,那支同時還掛著每週排程(**不**經過這道閘)。 security: - # **這一組在 PR 上也跑,但裡面只有 Gitleaks 會動**(裁示 2026-08-16)。 + # **這一組在 PR 上全部會跑**(裁示 2026-08-21)。 # - # 判準是「漏到 `main` 之後要付什麼」: + # 2026-08-16 到 08-21 之間只有 Gitleaks 會動,其餘三種各自帶一條 + # `if: github.event_name != 'pull_request'`。當時的判準是「漏到 `main` + # 之後要付什麼」:CodeQL/govulncheck/Trivy 找到的東西**修一次就結束**, + # 在 PR 攔下與在 `main` 攔下代價一樣,所以省下每個 PR 數分鐘;只有 + # Gitleaks 代價不同(憑證已經在 git 歷史裡,刪掉不夠,**必須輪替**), + # 所以它留在 PR。 # - # | | 補救 | - # |---|---| - # | CodeQL/govulncheck/Trivy | **修程式**,修好就結束 | - # | **Gitleaks** | 刪掉不夠——憑證已經在 git 歷史裡,**必須輪替** | + # **前半仍然成立,後半不再是收益**:升上 Enterprise 之後分鐘數不是稀缺的 + # 東西了,而代價一直都在——一個在 `main` 才被攔下的問題,是一個**已經 + # 合併**的問題。判準因此收斂成一句:**CI 做得到的驗證,就讓它在合併前跑。** + # 那三條 `if` 已於 2026-08-21 從 `security.yml` 拆掉。 # - # 前三種在 PR 攔下與在 `main` 攔下代價一樣,所以留在 `main`(省下每個 PR - # 數分鐘);Gitleaks 是唯一代價不同的,所以掛回 PR。 - # - # **閘門下移到被呼叫的那三個 job 上**(`security.yml` 裡各自的 - # `if: github.event_name != 'pull_request'`),不是留在這裡——留在這裡會把 - # Gitleaks 一起關掉。這樣做同時保住了檢查名稱:它仍然是 - # `安全掃描 / Gitleaks`,按名字釘住的分支保護不受影響。 + # **`needs: [verify]` 那道閘留著,理由與成本無關**:建置壞掉時 CodeQL 的 + # autobuild 與 govulncheck 吐的是同一個編譯錯誤換一種包裝,多餘的紅燈會 + # 稀釋掉真的那一顆。每週排程**不**經過它(見上方 `on:` 的註解)。 name: 安全掃描 # 閘門對公開倉庫也成立了(裁示 2026-08-16):掃描要先等基礎驗證綠。 # 取代 workspace decisions/infrastructure/公開倉庫的掃描不經閘門.md