@qijenchen/design-system 0.1.0-beta.56 → 0.1.0-beta.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -36,7 +36,11 @@ CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""' 2>/dev/null)
36
36
  [ "$TOOL" != "Bash" ] && exit 0
37
37
 
38
38
  # Heuristic:detect `git push origin <branch>` patterns
39
- if ! echo "$CMD" | grep -qE '\bgit\s+push\s+(-u\s+)?origin\b'; then
39
+ # 2026-06-06 fix:要求 `git push` 出現在「命令邊界」(行首 / ; / && / || / $( ),
40
+ # 否則 `P='git push origin'` 賦值、`echo "git push origin"`、`grep 'git push origin'` 等
41
+ # 「字串裡提到 push」會誤觸發 → falls-back 到 current branch 吐 404 preview URL 注入 context。
42
+ # 命令邊界 = 真的在執行 push,字串提及 = 噪音。對齊「只在真推送時 relay deploy URL」root invariant。
43
+ if ! echo "$CMD" | grep -qE '(^|[;&|(])[[:space:]]*git[[:space:]]+push[[:space:]]+(-u[[:space:]]+)?origin\b'; then
40
44
  exit 0
41
45
  fi
42
46
 
@@ -47,7 +51,29 @@ fi
47
51
 
48
52
  CWD=$(pwd)
49
53
  URLS_FOUND=""
50
- BRANCH=$(echo "$CMD" | grep -oE 'origin\s+\S+' | awk '{print $2}' | head -1)
54
+ # 2026-06-07 ROOT fix:只從「git push ... origin <ref>」這一段擷取 branch,不是整條 compound command
55
+ # 第一個 `origin X`。否則 `git fetch origin --quiet && git push origin main` 會誤抓 fetch 段的 `--quiet`
56
+ # 當 branch → 推導 `--quiet--site` 404(此前 5 道 guard 都沒擋到,因 `--quiet` 全是合法 git ref 字元)。
57
+ # 隔出 push 段(到下個 command 分隔 ; & | 為止)後,取 origin 後第一個 token。
58
+ PUSH_SEG=$(echo "$CMD" | grep -oE '(^|[;&|(])[[:space:]]*git[[:space:]]+push[[:space:]][^;&|]*' | head -1)
59
+ BRANCH=$(echo "$PUSH_SEG" | grep -oE 'origin[[:space:]]+[^[:space:]]+' | head -1 | awk '{print $2}')
60
+ # origin 後第一個 token 是 flag(`git push origin --force` = 無顯式 branch)→ 清空走 current-branch fallback
61
+ case "$BRANCH" in -*) BRANCH="" ;; esac
62
+ # 2026-06-06 fix:refspec `src:dst` → 取 dst(`HEAD:main` → `main`),否則推導出 `HEAD:main--site` 404 URL
63
+ case "$BRANCH" in *:*) BRANCH="${BRANCH##*:}" ;; esac
64
+ # 2026-06-06 fix:`git push origin HEAD`(或 `@`)= symbolic ref 指向當前 branch → 解析成真 branch 名,
65
+ # 否則把字面 "HEAD" 當 branch 推導出 `HEAD--site` 404 URL(real push 常用此式,會誤吐)。
66
+ if [ "$BRANCH" = "HEAD" ] || [ "$BRANCH" = "@" ]; then
67
+ BRANCH=$(git -C "$CWD" branch --show-current 2>/dev/null || echo "")
68
+ fi
69
+ # 2026-06-06 fix:BRANCH 含非法 git ref 字元(" ' 空白 \ 等)→ 此命令只是「字串裡含 git push origin」
70
+ # (測試迴圈 / 文件 / echo),非真推送 → skip,避免把 `main"` 等垃圾推導成 404 URL 注入 context。
71
+ # git ref 合法字元集 ⊂ [A-Za-z0-9._/-];非此集 = 必為解析噪音(root guard,涵蓋 refspec/tag 之外的雜訊)。
72
+ if [ -n "$BRANCH" ] && ! echo "$BRANCH" | grep -qE '^[A-Za-z0-9._/-]+$'; then exit 0; fi
73
+ # 2026-06-06 fix:tag push(`v1.2.3` 等)不產 branch-preview / production deploy → skip,
74
+ # 否則把 tag 名當 branch 推導出 `v0.1.0-beta.56--site` 404 URL(release tag push 每次都誤吐)
75
+ if echo "$BRANCH" | grep -qE '^v[0-9]'; then exit 0; fi
76
+ if [ -n "$BRANCH" ] && git -C "$CWD" rev-parse --verify --quiet "refs/tags/$BRANCH" >/dev/null 2>&1; then exit 0; fi
51
77
  [ -z "$BRANCH" ] && BRANCH=$(git -C "$CWD" branch --show-current 2>/dev/null || echo "main")
52
78
 
53
79
  # v3 2026-05-27:curl HEAD verify URL before reporting(per user「你確定有做到」complaint)
@@ -0,0 +1,135 @@
1
+ #!/bin/bash
2
+ # Tests for inject_deploy_url_after_push.sh
3
+ #
4
+ # 鎖住 2026-06-06 收斂的「只在真推送 + 真 branch 時 relay deploy URL」root invariant,
5
+ # 防 refspec / symbolic-ref / tag / 解析噪音 / 字串提及 等再吐 404 URL 進 context。
6
+
7
+ set -u
8
+
9
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10
+ HOOK="$SCRIPT_DIR/../inject_deploy_url_after_push.sh"
11
+ [ -f "$HOOK" ] || { echo "FATAL: hook not found"; exit 1; }
12
+
13
+ PASS=0; FAIL=0; FAILED=""
14
+
15
+ # 建一個臨時 git repo(branch=feature-test)+ netlify.toml,讓 Detection 2 可達;
16
+ # HOME 指向空 temp 確保無 USER_OVERRIDE(hermetic,不碰真實機 deploy-targets.json)。
17
+ setup() {
18
+ TMP=$(mktemp -d)
19
+ mkdir -p "$TMP/home"
20
+ (
21
+ cd "$TMP" || exit 1
22
+ git init -q -b feature-test 2>/dev/null || { git init -q; git checkout -q -b feature-test; }
23
+ : > netlify.toml
24
+ git add -A 2>/dev/null
25
+ GIT_AUTHOR_NAME=t GIT_AUTHOR_EMAIL=t@t GIT_COMMITTER_NAME=t GIT_COMMITTER_EMAIL=t@t \
26
+ git commit -q -m init 2>/dev/null
27
+ )
28
+ }
29
+ teardown() { rm -rf "$TMP"; }
30
+
31
+ # run_hook <command> [event] [tool]
32
+ run_hook() {
33
+ local cmd="$1" ev="${2:-PostToolUse}" tool="${3:-Bash}" json
34
+ json=$(printf '{"hook_event_name":"%s","tool_name":"%s","tool_input":{"command":"%s"}}' "$ev" "$tool" "$cmd")
35
+ STDOUT=$( cd "$TMP" && HOME="$TMP/home" CLAUDE_PROJECT_DIR="$TMP" bash "$HOOK" <<<"$json" 2>&1 )
36
+ EXIT=$?
37
+ }
38
+
39
+ injected() { echo "$STDOUT" | grep -q "Deploy URLs auto-detected"; }
40
+ head_leaked() { echo "$STDOUT" | grep -qE 'HEAD(--|:|\))'; }
41
+ fn7() { echo "$STDOUT" | grep -q "feature-test" && ! head_leaked; }
42
+ fn8() { ! head_leaked; }
43
+ fn9() { echo "$STDOUT" | grep -q "feature-test"; }
44
+ has_feature() { echo "$STDOUT" | grep -q "feature-test"; }
45
+ no_quiet() { ! echo "$STDOUT" | grep -q -- "--quiet"; }
46
+ fn10() { has_feature && no_quiet; } # compound:fetch 段的 --quiet 不可被誤抓為 branch
47
+ fn11() { has_feature; } # compound:pull 段的 main 不可被誤抓(否則 grep feature-test 失敗)
48
+ fn12() { has_feature; } # bare push origin → fallback current branch
49
+ fn13() { has_feature; } # flag-after-origin → 清空 → fallback current branch
50
+
51
+ check() { # <name> <expect: skip|fire> [extra-assert-fn]
52
+ local name="$1" expect="$2" extra="${3:-}"
53
+ local ok=1
54
+ if [ "$expect" = "skip" ]; then
55
+ { [ "$EXIT" = "0" ] && ! injected; } || ok=0
56
+ else # fire
57
+ { [ "$EXIT" = "0" ] && injected; } || ok=0
58
+ fi
59
+ if [ -n "$extra" ] && ! "$extra"; then ok=0; fi
60
+ if [ "$ok" = "1" ]; then
61
+ echo " PASS $name"; PASS=$((PASS+1))
62
+ else
63
+ echo " FAIL $name (exit=$EXIT, expect=$expect)"
64
+ echo " output=${STDOUT:0:240}"
65
+ FAIL=$((FAIL+1)); FAILED="${FAILED}\n - $name"
66
+ fi
67
+ }
68
+
69
+ setup
70
+
71
+ # 1. 非 PostToolUse event → skip
72
+ run_hook "git push origin feature-test" "UserPromptSubmit" "Bash"
73
+ check "1 non-PostToolUse event → skip" skip
74
+
75
+ # 2. 非 Bash tool → skip
76
+ run_hook "git push origin feature-test" "PostToolUse" "Edit"
77
+ check "2 non-Bash tool → skip" skip
78
+
79
+ # 3. tag push(v*)→ skip(原把 tag 名當 branch 推 404)
80
+ run_hook "git push origin v0.1.0-beta.56"
81
+ check "3 tag push → skip" skip
82
+
83
+ # 4. branch --delete(cleanup,非 deploy)→ skip
84
+ run_hook "git push origin --delete old-branch"
85
+ check "4 push --delete → skip" skip
86
+
87
+ # 5. 字串提及(賦值,非命令邊界)→ skip(command-boundary guard)
88
+ run_hook "P='git push origin'"
89
+ check "5 string-mention (assignment) → skip" skip
90
+
91
+ # 6. 解析噪音 / 非法 git ref 字元(~)→ skip(charset guard)
92
+ run_hook "git push origin foo~bar"
93
+ check "6 invalid-ref-charset branch → skip" skip
94
+
95
+ # 7. symbolic ref HEAD → fires + 解析成真 branch feature-test(非字面 HEAD)
96
+ run_hook "git push origin HEAD"
97
+ check "7 HEAD → fire + resolve to feature-test (no literal HEAD)" fire 'fn7'
98
+
99
+ # 8. refspec HEAD:main → 取 dst,不可洩漏字面 HEAD
100
+ run_hook "git push origin HEAD:main"
101
+ check "8 refspec HEAD:main → no HEAD leak" fire 'fn8'
102
+
103
+ # 9. positive control:真 branch push → fires(確保 skip 測試非因 hook 全壞而假過)
104
+ run_hook "git add -A && git push origin feature-test"
105
+ check "9 real branch push (positive control) → fire" fire 'fn9'
106
+
107
+ # 10. ROOT regression:compound 命令前段 `git fetch origin --quiet` 的 flag 不可被誤抓為 branch
108
+ # (2026-06-07 anchor:merge 時 `git fetch origin --quiet && ... && git push origin main` 吐 `--quiet--site` 404)
109
+ run_hook "git fetch origin --quiet && git push origin feature-test"
110
+ check "10 compound w/ fetch flag → branch from push seg only (no --quiet leak)" fire 'fn10'
111
+
112
+ # 11. compound 前段 `git pull origin main` 的 main 不可被誤抓(branch 必來自 push 段)
113
+ run_hook "git pull origin main && git push origin feature-test"
114
+ check "11 compound w/ pull → branch from push seg (not pull's main)" fire 'fn11'
115
+
116
+ # 12. bare `git push origin`(無顯式 branch)→ fallback 當前 branch
117
+ run_hook "git push origin"
118
+ check "12 bare push origin → fallback current branch" fire 'fn12'
119
+
120
+ # 13. flag-after-origin `git push origin --force`(無顯式 branch)→ fallback 當前 branch
121
+ run_hook "git push origin --force"
122
+ check "13 flag-after-origin → fallback current branch (no flag-as-branch)" fire 'fn13'
123
+
124
+ teardown
125
+
126
+ echo ""
127
+ echo "── Summary ──"
128
+ echo "PASS: $PASS / $((PASS+FAIL))"
129
+ if [ "$FAIL" -gt 0 ]; then
130
+ echo "FAIL: $FAIL"
131
+ printf "$FAILED\n"
132
+ exit 1
133
+ fi
134
+ echo "✅ All passed"
135
+ exit 0
@@ -7,7 +7,7 @@
7
7
  "scripts/composition-fidelity-visual-diff.mjs",
8
8
  "product-workspace apps/template/src/AllDsComponents.stories.tsx (ImportSmoke portal → DS Storybook link)"
9
9
  ],
10
- "generatedAt": "2026-06-06T11:34:35.406Z"
10
+ "generatedAt": "2026-06-06T10:07:05.357Z"
11
11
  },
12
12
  "components": {
13
13
  "accordion": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qijenchen/design-system",
3
- "version": "0.1.0-beta.56",
3
+ "version": "0.1.0-beta.58",
4
4
  "private": false,
5
5
  "description": "World-class design system — components, patterns, tokens, hooks (single source of truth for team distribution).",
6
6
  "type": "module",