Skip to content

Commit 1886bb2

Browse files
committed
a configured gtc is authentication, and a skipped host was not a pass
TWO DEFECTS, ONE MEASUREMENT. A local top-up exited 0 and printed `all assets mirrored + verified on 1 host(s)` while `no GITCODE_TOKEN/gtc; skipping gitcode mirror` sat one line above it, and nothing had reached GitCode. FIRST: the gate asked the wrong question. `gtc` resolves its own credentials — `GITCODE_TOKEN` first, then the config file its `--help` documents — exactly as `gh` does, and the github leg has always accepted either. This leg demanded the variable, so a machine with a working, configured gtc was told it had none. That is the machine this script is run on by hand, which is the whole reason it can be run by hand: the cross-border upload from a GitHub runner is the shaped path that has cost four releases their aarch64 asset. SECOND, AND WORSE: `verify` iterates the hosts that turned out to be ENABLED, so its denominator came from the same enumeration as its numerator. It could not tell "both hosts serve every asset" from "one host was skipped and the other serves every asset" — the skip was invisible to the only check that could have reported it. `MIRROR_HOSTS` states the required set before anything is probed, and defaults to `both`. Wanting one leg stays possible, because topping GitCode up by hand is legitimate, but it has to be asked for rather than being what happened. Missing credentials for a required host now exit 2 and name both places a token can live. Measured, four paths: local, gtc configured, no env var skipped silently, exit 0 -> 2 hosts MIRROR_HOSTS=gtc n/a -> 1 host, stated gtc present with no token skipped silently, exit 0 -> exit 2 CI (both tokens in the environment) 2 hosts -> unchanged The third case had to be isolated with a config home carrying gh and not gtc: emptying the whole config home fails the upstream download instead and never reaches the gate, which is a test that would have passed for the wrong reason.
1 parent fe49665 commit 1886bb2

2 files changed

Lines changed: 85 additions & 18 deletions

File tree

.agents/docs/2026-09-21-openkal-ecosystem-completion-and-acceptance.md

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,12 +1008,25 @@ artifact 发布 → `xlings install mcpp@2026.9.21.3` 成功。
10081008
⭐ B/C/D 在两条腿上都绿是**对的**:它们是上一批的 CHANGE,发布之后就转为 guard。
10091009
本批只有 G 和 H 是 CHANGE,**而它们在旧版上都红**——这正是 CHANGE 段必须具备的性质。
10101010

1011-
**一个只有实测才能发现的空转。** 第一次本地补 GitCode 退出码为 0 并打印
1012-
「all assets mirrored + verified on 1 host(s)」,而上一行写着
1013-
`no GITCODE_TOKEN/gtc; skipping gitcode mirror`:`mirror_res.sh` 的闸要求
1014-
**环境变量** `GITCODE_TOKEN` 非空,而 `gtc` 把 token 放在自己的配置文件里,于是
1015-
**唯一要做的那条腿被跳过,包在一条成功消息后面**。是我按判据去 GET
1016-
`gitcode.com` 读到 404 才发现的——**退出码不是判据,资产能不能被取回才是**
1011+
**一个只有实测才能发现的空转,以及它已经被修掉。** 第一次本地补 GitCode 退出码为 0
1012+
并打印「all assets mirrored + verified on 1 host(s)」,而上一行写着
1013+
`no GITCODE_TOKEN/gtc; skipping gitcode mirror`:`mirror_res.sh` 的闸要求**环境变量**
1014+
`GITCODE_TOKEN` 非空,而 `gtc``gh` 一样自己解析凭据(先环境变量、再它 `--help`
1015+
写明的配置文件),于是**一台 gtc 完全可用的机器被判定为没有 gtc**——而那正是这个脚本
1016+
被手动运行的那台机器。是我按判据去 GET `gitcode.com` 读到 404 才发现的。
1017+
1018+
⭐⭐ **更深的一层在验收环节:`verify` 只遍历「实际启用了的」host。** 分母与分子取自
1019+
同一次枚举,于是它分不出「两个 host 都齐」和「一个 host 被跳过、另一个齐」。
1020+
修法是把「这次必须完成哪些 host」在探测之前就声明出来(`MIRROR_HOSTS`,默认 `both`):
1021+
想只补一条腿是合法的——从 CN 宿主手动补 GitCode 正是本地运行的理由——**但它必须被要求,
1022+
不能是意外的结果**。凭据缺失现在硬退 2 并指出 token 可以放的两个位置。
1023+
1024+
| 情形 | 修之前 | 修之后 |
1025+
| --- | --- | --- |
1026+
| 本地,gtc 已配置、无环境变量 | **静默跳过,退 0** | 两个 host 都镜像并核验 |
1027+
| `MIRROR_HOSTS=gtc` || 明确排除 GitHub,退 0 |
1028+
| gtc 在但没有 token | **静默跳过,退 0** | **退 2**,指出两个可放 token 的位置 |
1029+
| CI(两个 token 都在环境里) | 两个 host | 不变,两个 host |
10171030

10181031
## 8. 本方案自身的失败模式
10191032

.github/tools/mirror_res.sh

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -246,22 +246,76 @@ mirror_host() { # kind(gh|gtc) base_url deadline_seconds
246246

247247
# ── Both hosts IN PARALLEL: they are fully independent, and the gitcode
248248
# leg is cross-border-slow — serializing them doubled wall time for nothing.
249+
# ── WHICH HOSTS THIS RUN MUST COMPLETE, STATED BEFORE ANYTHING IS PROBED ──
250+
#
251+
# The verify gate below iterates the hosts that turned out to be ENABLED, so
252+
# until this variable existed its denominator came from the same enumeration
253+
# as its numerator and could not tell "both hosts serve every asset" from
254+
# "one host was skipped and the other serves every asset". Measured, 2026-09-21:
255+
# a local top-up run exited 0 and printed `all assets mirrored + verified on
256+
# 1 host(s)` with `no GITCODE_TOKEN/gtc; skipping gitcode mirror` one line
257+
# above it, and nothing had reached GitCode at all.
258+
#
259+
# `both` is the default because that is what this script is for: the two hosts
260+
# serve the GLOBAL and CN install paths, and an incomplete mirror surfaces as
261+
# a 404 in the first user's install. Wanting one leg is legitimate --- topping
262+
# GitCode up by hand from a CN host is the reason this runs locally at all ---
263+
# but it has to be asked for.
264+
: "${MIRROR_HOSTS:=both}"
265+
case "$MIRROR_HOSTS" in
266+
both|gh|gtc) ;;
267+
*) echo "[mirror] MIRROR_HOSTS must be both|gh|gtc, not '$MIRROR_HOSTS'" >&2; exit 2 ;;
268+
esac
269+
WANT_GH=0; WANT_GTC=0
270+
[[ "$MIRROR_HOSTS" == both || "$MIRROR_HOSTS" == gh ]] && WANT_GH=1
271+
[[ "$MIRROR_HOSTS" == both || "$MIRROR_HOSTS" == gtc ]] && WANT_GTC=1
272+
273+
# CAN `gtc` AUTHENTICATE, NOT IS THE VARIABLE SET.
274+
#
275+
# gtc resolves its own credentials -- `GITCODE_TOKEN` first, then the config
276+
# file its `--help` documents -- exactly as `gh` does, and the github leg below
277+
# has always accepted either. This leg demanded the variable, so a machine with
278+
# a working, configured gtc was told it had none. That is the machine this
279+
# script is run on by hand.
280+
gtc_can_auth() {
281+
command -v gtc >/dev/null 2>&1 || return 1
282+
[[ -n "${GITCODE_TOKEN:-}" ]] && return 0
283+
local cfg="${XDG_CONFIG_HOME:-$HOME/.config}/gitcode-tool/config.json"
284+
[[ -s "$cfg" ]] && grep -q '"token"[[:space:]]*:[[:space:]]*"[^"]\+"' "$cfg"
285+
}
286+
249287
GH_ENABLED=0
250-
if [[ -n "${XLINGS_RES_TOKEN:-}" ]] || gh auth status >/dev/null 2>&1; then
251-
GH_ENABLED=1
252-
info "GitHub $GH_DST tag $VER"
253-
GH_TOKEN="${XLINGS_RES_TOKEN:-}" gh release view "$VER" -R "$GH_DST" >/dev/null 2>&1 \
254-
|| GH_TOKEN="${XLINGS_RES_TOKEN:-}" gh release create "$VER" -R "$GH_DST" --title "$VER" --notes "$PROJ $VER (mirror of $SRC_REPO)"
288+
if [[ "$WANT_GH" == 1 ]]; then
289+
if [[ -n "${XLINGS_RES_TOKEN:-}" ]] || gh auth status >/dev/null 2>&1; then
290+
GH_ENABLED=1
291+
info "GitHub $GH_DST tag $VER"
292+
GH_TOKEN="${XLINGS_RES_TOKEN:-}" gh release view "$VER" -R "$GH_DST" >/dev/null 2>&1 \
293+
|| GH_TOKEN="${XLINGS_RES_TOKEN:-}" gh release create "$VER" -R "$GH_DST" --title "$VER" --notes "$PROJ $VER (mirror of $SRC_REPO)"
294+
else
295+
echo "[mirror] FAIL: this run must mirror to GitHub and there is no auth for it." >&2
296+
echo "[mirror] set XLINGS_RES_TOKEN, or run \`gh auth login\`," >&2
297+
echo "[mirror] or pass MIRROR_HOSTS=gtc to mirror only GitCode." >&2
298+
exit 2
299+
fi
255300
else
256-
info "no github auth; skipping github mirror"
301+
info "MIRROR_HOSTS=$MIRROR_HOSTS: not mirroring to GitHub"
257302
fi
303+
258304
GTC_ENABLED=0
259-
if [[ -n "${GITCODE_TOKEN:-}" ]] && command -v gtc >/dev/null 2>&1; then
260-
GTC_ENABLED=1
261-
info "GitCode $GTC_DST tag $VER"
262-
gtc release create "$GTC_DST" --tag "$VER" --name "$VER" 2>/dev/null || true
305+
if [[ "$WANT_GTC" == 1 ]]; then
306+
if gtc_can_auth; then
307+
GTC_ENABLED=1
308+
info "GitCode $GTC_DST tag $VER"
309+
gtc release create "$GTC_DST" --tag "$VER" --name "$VER" 2>/dev/null || true
310+
else
311+
echo "[mirror] FAIL: this run must mirror to GitCode and gtc cannot authenticate." >&2
312+
echo "[mirror] put gtc on PATH and give it a token -- GITCODE_TOKEN, or" >&2
313+
echo "[mirror] \"token\" in ${XDG_CONFIG_HOME:-$HOME/.config}/gitcode-tool/config.json --" >&2
314+
echo "[mirror] or pass MIRROR_HOSTS=gh to mirror only GitHub." >&2
315+
exit 2
316+
fi
263317
else
264-
info "no GITCODE_TOKEN/gtc; skipping gitcode mirror"
318+
info "MIRROR_HOSTS=$MIRROR_HOSTS: not mirroring to GitCode"
265319
fi
266320

267321
GH_PID=""; GTC_PID=""
@@ -313,5 +367,5 @@ if [[ $rc != 0 ]]; then
313367
echo "[mirror] hint: if the asset above was WARNed at a leg deadline, raise MIRROR_LEG_DEADLINE_GH/GTC for this run, or push it by hand:" >&2
314368
echo "[mirror] gh release download v$VER -R $SRC_REPO -p '<asset>' && gtc release upload $GTC_DST '<asset>' --tag $VER" >&2
315369
fi
316-
[[ $rc == 0 ]] && info "all assets mirrored + verified on ${#hosts[@]} host(s) in ${SECONDS}s"
370+
[[ $rc == 0 ]] && info "all assets mirrored + verified on ${#hosts[@]} host(s) (${hosts[*]}) in ${SECONDS}s"
317371
exit $rc

0 commit comments

Comments
 (0)