Commit fda88865f822e79e95b005a354a451c2b9226bfe

Authored by zichun
1 parent b3977095

update

skills/coding/mr-create/scripts/create-mr.sh
... ... @@ -76,14 +76,35 @@ awk -v report="$REPORT" '
76 76 mv .tmp/mr-desc.final "$DESC_FILE"
77 77  
78 78 # 7. 幂等守门:查已有 opened MR
79   -HTTP_CODE=$(curl -sS -o .tmp/existing.json -w '%{http_code}' \
  79 +CURL_META=$(curl -sS -o .tmp/existing.json -w '%{http_code}|%{url_effective}' \
80 80 --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
81 81 "${GITLAB_API_URL}/projects/${GITLAB_PROJECT_ID}/merge_requests?source_branch=${CURRENT_BRANCH}&state=opened")
82 82  
  83 +HTTP_CODE=${CURL_META%%|*}
  84 +EFFECTIVE_URL=${CURL_META#*|}
  85 +
83 86 if [ "$HTTP_CODE" != "200" ]; then
84 87 echo "[create-mr] ⚠️ 查询已有 MR 失败 (HTTP $HTTP_CODE)" >&2
85   - jq -r '.message // .error // .' .tmp/existing.json | head -c 200 >&2
86   - echo >&2
  88 + echo " effective URL: $EFFECTIVE_URL" >&2
  89 + FIRST=$(head -c 1 .tmp/existing.json 2>/dev/null || echo "")
  90 + case "$FIRST" in
  91 + '{'|'[')
  92 + echo " 响应(JSON):" >&2
  93 + jq -r '.message // .error // .' .tmp/existing.json 2>/dev/null | head -c 200 >&2
  94 + echo >&2
  95 + ;;
  96 + '<')
  97 + echo " 响应是 HTML(很可能反代/路由失配,把 API 请求送进了 web 处理链):" >&2
  98 + head -c 200 .tmp/existing.json >&2
  99 + echo >&2
  100 + echo " 常见原因:GITLAB_API_URL 错 / GITLAB_PROJECT_ID 不是数字 ID / 反代规范化路径" >&2
  101 + ;;
  102 + *)
  103 + echo " 响应非 JSON 非 HTML(前 200 bytes):" >&2
  104 + head -c 200 .tmp/existing.json >&2
  105 + echo >&2
  106 + ;;
  107 + esac
87 108 rm -f .tmp/existing.json "$DESC_FILE"
88 109 exit 1
89 110 fi
... ...
skills/plan/downstream-gen/scripts/derive-gitlab.sh
... ... @@ -4,8 +4,9 @@
4 4 # 用法: bash derive-gitlab.sh [.env.local 路径,默认 .env.local]
5 5 #
6 6 # 派生字段:
7   -# GITLAB_PROJECT_ID = origin 的 namespace/path(/ 编码成 %2F)
8 7 # GITLAB_API_URL = <scheme>://<host>/api/v3
  8 +# GITLAB_PROJECT_ID = 通过 GitLab API(GET /projects?search=...)解析得到的项目数字 ID
  9 +# 要求 GITLAB_TOKEN 已填且有效;token 缺失 / 验证失败 / 未匹配时留 TBD
9 10 #
10 11 # 仅当字段值为 TBD(A5 自动补) 或空时回填;用户手填值不动。
11 12 # 仅支持 http(s) origin URL;其他协议(ssh / git@)跳过。
... ... @@ -39,8 +40,8 @@ REST=${URL#${SCHEME}://}
39 40 HOST=${REST%%/*}
40 41 PATH_RAW=${REST#*/}
41 42 PATH_RAW=${PATH_RAW%.git}
  43 +REPO_NAME=$(basename "$PATH_RAW")
42 44  
43   -PROJECT_ID=${PATH_RAW//\//%2F}
44 45 API_URL="${SCHEME}://${HOST}/api/v3"
45 46  
46 47 update_field() {
... ... @@ -99,6 +100,36 @@ report_token() {
99 100 }
100 101  
101 102 echo "derive-gitlab.sh: 从 origin ($URL) 派生 GitLab 凭据:"
102   -update_field GITLAB_PROJECT_ID "$PROJECT_ID"
103 103 update_field GITLAB_API_URL "$API_URL"
  104 +
  105 +# GITLAB_PROJECT_ID:通过 GitLab API 解析数字 ID(要求 token 已填且有效)
  106 +TOKEN_LINE=$(grep -E '^GITLAB_TOKEN=' "$ENV_FILE" | head -1)
  107 +TOKEN_VAL=${TOKEN_LINE#GITLAB_TOKEN=}
  108 +case "$TOKEN_VAL" in
  109 + \'*\') TOKEN_VAL=${TOKEN_VAL#\'}; TOKEN_VAL=${TOKEN_VAL%\'} ;;
  110 + \"*\") TOKEN_VAL=${TOKEN_VAL#\"}; TOKEN_VAL=${TOKEN_VAL%\"} ;;
  111 +esac
  112 +
  113 +case "$TOKEN_VAL" in
  114 + ""|"【人工填写:"*|"TBD"*)
  115 + echo " GITLAB_PROJECT_ID = TBD [token 未填,跳过 API 解析;填完 token 后重跑此脚本]"
  116 + ;;
  117 + *)
  118 + USER_HTTP=$(curl -sS -o /dev/null -w '%{http_code}' --header "PRIVATE-TOKEN: $TOKEN_VAL" "$API_URL/user" 2>/dev/null || echo "000")
  119 + if [ "$USER_HTTP" != "200" ]; then
  120 + echo " GITLAB_PROJECT_ID = TBD [token 验证失败 HTTP $USER_HTTP,留 TBD 待人工确认]"
  121 + else
  122 + SEARCH_RESP=$(curl -sS --header "PRIVATE-TOKEN: $TOKEN_VAL" \
  123 + "$API_URL/projects?search=$REPO_NAME&simple=true&per_page=50" 2>/dev/null || echo "[]")
  124 + NUMERIC_ID=$(echo "$SEARCH_RESP" | jq -r --arg p "$PATH_RAW" \
  125 + '.[] | select(.path_with_namespace == $p) | .id' 2>/dev/null | head -1)
  126 + if [ -n "$NUMERIC_ID" ]; then
  127 + update_field GITLAB_PROJECT_ID "$NUMERIC_ID"
  128 + else
  129 + echo " GITLAB_PROJECT_ID = TBD [API 未匹配 path_with_namespace=$PATH_RAW,请到 GitLab 项目设置页查数字 ID 后填入]"
  130 + fi
  131 + fi
  132 + ;;
  133 +esac
  134 +
104 135 report_token
... ...
skills/plan/skeleton-gen/templates/env-local-template
... ... @@ -29,8 +29,9 @@ TEST_DB_ALLOWED_HOSTS=
29 29 # 自动派生为 `<scheme>://<host>/api/v3`;如派生的 scheme 错(例如远程是 ssh 但实际 web 走 https),手动改掉即可
30 30 # - GITLAB_TOKEN:GitLab v3 的 **Private Token**(用户 Profile → Account → Private token 生成;HTTP 调用仍用
31 31 # `PRIVATE-TOKEN` 头。v3 token 是全权限、无细粒度 scope)。**无法派生,必须人工填**
32   -# - GITLAB_PROJECT_ID:A5 从 origin 远程路径自动派生为 URL-encoded 形式(如 `zhuzc/test` → `zhuzc%2Ftest`);
33   -# 也可手动改成项目数字 ID(GitLab 项目设置页可见)
  32 +# - GITLAB_PROJECT_ID:项目数字 ID(GitLab 项目设置 → General → 顶部 Project ID 字段,纯整数)。
  33 +# A5 `downstream-gen` 在 GITLAB_TOKEN 已填的前提下会调 API 自动解析数字 ID 写入;
  34 +# token 未填 / API 解析失败时留 TBD,请人工到设置页查到后填入
34 35 GITLAB_API_URL='TBD(A5 自动补)'
35 36 GITLAB_TOKEN=【人工填写:GitLab Private Token(Profile → Account → Private token)】
36 37 GITLAB_PROJECT_ID='TBD(A5 自动补)'
... ...
skills/plan/skeleton-gen/templates/scripts-test-template.sh
1 1 #!/usr/bin/env bash
2 2 # scripts/test.sh —— 合并到默认分支(main / master)前的测试闸门。
3   -# 顺序:setup-db → build → lint → unit+integration → e2e → reset-db
  3 +# 顺序:detect → setup-db → build → lint → unit+integration → e2e → reset-db
4 4 # 由 .githooks/pre-push 和 test-gate skill(通过子会话)调用。
5 5  
6 6 set -euo pipefail
... ... @@ -8,17 +8,28 @@ set -euo pipefail
8 8 PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
9 9 cd "$PROJECT_ROOT"
10 10  
  11 +# Stack detection (runtime, mode-agnostic)
  12 +HAS_BACKEND=0; [ -d backend ] && HAS_BACKEND=1
  13 +HAS_FRONTEND=0; [ -d frontend ] && HAS_FRONTEND=1
  14 +if [ $HAS_BACKEND -eq 0 ] && [ $HAS_FRONTEND -eq 0 ]; then
  15 + echo "[test.sh] FATAL: neither backend/ nor frontend/ exists" >&2
  16 + exit 1
  17 +fi
  18 +
11 19 echo "[test.sh] 1/6 setup test db"
12 20 ./scripts/setup-test-db.sh
13 21  
14 22 echo "[test.sh] 2/6 build"
15   -{{build_cmd}}
  23 +if [ $HAS_BACKEND -eq 1 ]; then (cd backend && {{backend_build}}); else echo "[test.sh] skip backend build"; fi
  24 +if [ $HAS_FRONTEND -eq 1 ]; then (cd frontend && {{frontend_build}}); else echo "[test.sh] skip frontend build"; fi
16 25  
17 26 echo "[test.sh] 3/6 lint"
18   -{{lint_cmd}}
  27 +if [ $HAS_BACKEND -eq 1 ]; then (cd backend && {{backend_lint}}); else echo "[test.sh] skip backend lint"; fi
  28 +if [ $HAS_FRONTEND -eq 1 ]; then (cd frontend && {{frontend_lint}}); else echo "[test.sh] skip frontend lint"; fi
19 29  
20 30 echo "[test.sh] 4/6 unit + integration"
21   -{{test_cmd}}
  31 +if [ $HAS_BACKEND -eq 1 ]; then (cd backend && {{backend_test}}); else echo "[test.sh] skip backend test"; fi
  32 +if [ $HAS_FRONTEND -eq 1 ]; then (cd frontend && {{frontend_test}}); else echo "[test.sh] skip frontend test"; fi
22 33  
23 34 echo "[test.sh] 5/6 E2E"
24 35 {{e2e_cmd}}
... ...