fix(build): copy_bundled_data 改為冪等,清掉前次 build 的殘留
Windows/Linux build 卡在「預期 2 個 .nef,實際 8 個」。 payload-macos 呼叫前有 rm -rf payload/darwin,但 payload-windows 與 payload-linux 刻意不清(build-server-* 已先把 binary 放進 bin/), 導致 data/ 留著白名單機制加入前那 8 個 .nef,與新複製的 2 個相加後 觸發後置檢查。 後置檢查本身是對的 —— installer/windows/visiona-local.iss:86 是 recursesubdirs 整包收,殘留什麼就出貨什麼。問題在 helper 不冪等。 改為複製前先清空目標 data 目錄。清整個目錄而非只清 nef/,因為該目錄 內容全由此 helper 產生,只清 nef/ 無法處理未來移除非 nef 檔案的情況。 rm -rf 加四層防護:拒絕空值、絕對路徑與 ~、含 .. 的跳脫、不符 payload/*/data 格式的目標,另檢查目標不是檔案。用 case 而非 [[ ]] 以相容 Git Bash。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
61593f004d
commit
a05d206c07
@ -39,9 +39,34 @@ BUNDLED_NEFS := \
|
|||||||
# copy_bundled_data:把 server/data/ 複製到 $(1),但 nef/ 只帶 BUNDLED_NEFS 白名單。
|
# copy_bundled_data:把 server/data/ 複製到 $(1),但 nef/ 只帶 BUNDLED_NEFS 白名單。
|
||||||
# $(1) = 目標 data 目錄(例:payload/darwin/data)
|
# $(1) = 目標 data 目錄(例:payload/darwin/data)
|
||||||
#
|
#
|
||||||
# 步驟:(a) 複製 server/data/ 下除了 nef/ 以外的所有東西(models.json 等)
|
# 步驟:(a) 先清空 $(1),確保這個 helper 是冪等的(見下方「為什麼要清空」)
|
||||||
# (b) 再逐一複製白名單內的 .nef
|
# (b) 複製 server/data/ 下除了 nef/ 以外的所有東西(models.json 等)
|
||||||
# (c) 白名單檔案不存在就直接 fail,避免安靜地產出缺 model 的安裝包
|
# (c) 再逐一複製白名單內的 .nef
|
||||||
|
# (d) 白名單檔案不存在就直接 fail,避免安靜地產出缺 model 的安裝包
|
||||||
|
# (e) 最後數 .nef 個數,與白名單不符就 fail
|
||||||
|
#
|
||||||
|
# 為什麼要清空 $(1)((a) 步驟):
|
||||||
|
# payload-windows / payload-linux 刻意不 rm -rf 整個 payload/<os>/(因為
|
||||||
|
# build-server-* 已先把 binary 放進 bin/),所以先前 build 留下的檔案會殘留。
|
||||||
|
# 白名單機制(M5-a)之前的舊 build 會把 8 個 .nef 全部複製進去,升級到白名單
|
||||||
|
# 版本後再 build,就變成「新複製 2 個 + 殘留 6 個 = 8 個」,被下方的後置檢查
|
||||||
|
# 擋下來,build 直接失敗。清空目標目錄讓這個 helper 重複執行結果一致,不受
|
||||||
|
# 目標目錄既有內容影響。
|
||||||
|
# (payload-macos 沒踩到只是因為它有 rm -rf payload/darwin。)
|
||||||
|
#
|
||||||
|
# 清整個 $(1) 而不是只清 nef/:$(1) 的內容 100% 由本 helper 產生(Makefile 中
|
||||||
|
# 只有這裡寫入 payload/<os>/data/),沒有其他來源的檔案需要保留。只清 nef/ 的話,
|
||||||
|
# models.json 以外的殘留(例如未來從 server/data/ 移除的檔案)仍會被 installer
|
||||||
|
# 打包進去 —— installer/windows/visiona-local.iss 是用 data\* + recursesubdirs
|
||||||
|
# 整包收,殘留什麼就出貨什麼。清整包才是真正的冪等。
|
||||||
|
#
|
||||||
|
# rm -rf 安全防護($(1) 來自 make 變數,打錯會刪掉不該刪的東西):
|
||||||
|
# 1. 空值檢查:$(1) 展開為空就 fail,避免變成 `rm -rf /`(rm -rf "" 在部分
|
||||||
|
# shell 下是 no-op、但空值代表呼叫端寫錯,直接擋掉比較安全)
|
||||||
|
# 2. 絕對路徑 / 跳脫檢查:只接受相對路徑、且不得含 `..`,避免 `/`、`$$HOME`、
|
||||||
|
# `../..` 這類目標
|
||||||
|
# 3. 白名單前綴:路徑必須以 payload/ 開頭並以 /data 結尾,鎖死在 build 產物區
|
||||||
|
# 4. 刪的是「已存在且確定是目錄」的路徑,且刪除後立刻重建
|
||||||
#
|
#
|
||||||
# 只用 POSIX find / cp,不用 rsync —— Windows CI 跑在 Git Bash(windows-2022 +
|
# 只用 POSIX find / cp,不用 rsync —— Windows CI 跑在 Git Bash(windows-2022 +
|
||||||
# shell: bash),該環境沒有 rsync。
|
# shell: bash),該環境沒有 rsync。
|
||||||
@ -49,8 +74,27 @@ define copy_bundled_data
|
|||||||
@set -e; \
|
@set -e; \
|
||||||
echo "==> 複製 server/data → $(1)(.nef 白名單:$(words $(BUNDLED_NEFS)) 個)"; \
|
echo "==> 複製 server/data → $(1)(.nef 白名單:$(words $(BUNDLED_NEFS)) 個)"; \
|
||||||
if [ ! -d server/data ]; then echo "!! ERROR: server/data 不存在 !!"; exit 1; fi; \
|
if [ ! -d server/data ]; then echo "!! ERROR: server/data 不存在 !!"; exit 1; fi; \
|
||||||
mkdir -p "$(1)"; \
|
target='$(strip $(1))'; \
|
||||||
dest="$$(cd "$(1)" && pwd)"; \
|
if [ -z "$$target" ]; then \
|
||||||
|
echo "!! ERROR: copy_bundled_data 的目標目錄為空,拒絕執行 !!"; exit 1; \
|
||||||
|
fi; \
|
||||||
|
case "$$target" in \
|
||||||
|
/*|~*) echo "!! ERROR: 目標目錄必須是相對路徑,收到 '$$target' !!"; exit 1 ;; \
|
||||||
|
*..*) echo "!! ERROR: 目標目錄不得含 '..',收到 '$$target' !!"; exit 1 ;; \
|
||||||
|
esac; \
|
||||||
|
case "$$target" in \
|
||||||
|
payload/*/data) : ;; \
|
||||||
|
*) echo "!! ERROR: 目標目錄必須符合 payload/<os>/data,收到 '$$target' !!"; exit 1 ;; \
|
||||||
|
esac; \
|
||||||
|
if [ -e "$$target" ] && [ ! -d "$$target" ]; then \
|
||||||
|
echo "!! ERROR: '$$target' 存在但不是目錄,拒絕刪除 !!"; exit 1; \
|
||||||
|
fi; \
|
||||||
|
if [ -d "$$target" ]; then \
|
||||||
|
echo " 清空既有的 $${target}(確保冪等,不留前次 build 的殘留)"; \
|
||||||
|
rm -rf -- "$$target"; \
|
||||||
|
fi; \
|
||||||
|
mkdir -p "$$target"; \
|
||||||
|
dest="$$(cd "$$target" && pwd)"; \
|
||||||
( cd server/data && \
|
( cd server/data && \
|
||||||
find . -path ./nef -prune -o -type d -print | while read -r d; do mkdir -p "$$dest/$$d"; done && \
|
find . -path ./nef -prune -o -type d -print | while read -r d; do mkdir -p "$$dest/$$d"; done && \
|
||||||
find . -path ./nef -prune -o -type f -print | while read -r f; do cp "$$f" "$$dest/$$f"; done ); \
|
find . -path ./nef -prune -o -type f -print | while read -r f; do cp "$$f" "$$dest/$$f"; done ); \
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user