Skip to content

Commit 080ff50

Browse files
genednaclaude
andcommitted
v0.41.5: BB-03 opt-in stack switch helper
Add scripts/bb_optin_run.sh (plan-20261001 BB-03): runs one opt-in smoke case on mega2 recreated with the auth-none override, the artifacts-GC env file or the local-storage env file, and restores the default stack from an EXIT trap with a compose config hash comparison. --selftest proves the switch through the artifacts discovery document. An exclusive lock keeps concurrent runs from sharing the stack; logs are mode 0600. Documents the helper and exit codes 0/1 in deploy-trunk §8. Releases the BB-05 commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018bJDjze83ToyPysYzmxxWS Signed-off-by: Eli Ma <eli@patch.sh>
1 parent b51f4b1 commit 080ff50

5 files changed

Lines changed: 147 additions & 4 deletions

File tree

‎Cargo.lock‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mega2"
3-
version = "0.41.4"
3+
version = "0.41.5"
44
edition = "2024"
55
license = "MIT OR Apache-2.0"
66
description = "Monorepo engine and Git hosting server for AI agents: trunk-based storage, Git Smart HTTP, Git LFS, OCI registry, and Agent Session Capture"

‎docs/deploy-trunk.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,16 @@ docker compose -p mega2-trunk -f docker/docker-compose-storage-only.yml --profil
140140

141141
容器内的环回中继让 `127.0.0.1:9000`(HTTP)、`127.0.0.1:2222`(SSH)、`127.0.0.1:29000`(RustFS)与宿主机地址一致。
142142

143+
opt-in case(需要切换 mega2 配置的 case)一律经宿主侧 helper 运行,helper 用 `trap` 保证无论成败都把 mega2 恢复为默认配置并比对 compose config hash:
144+
145+
```bash
146+
scripts/bb_optin_run.sh <none|gc|local> <script> '<case>' target/tmp/<log>
147+
scripts/bb_optin_run.sh --selftest local target/tmp/<log> # 自测:桩命令退出 1
148+
```
149+
150+
- `scripts/bb_optin_run.sh` 退出码 0:case 通过,且 mega2 已恢复默认配置(log 含 `bb-optin: restored mega2 (config hash match)`)。
151+
- `scripts/bb_optin_run.sh` 退出码 1:case 失败,且 mega2 已恢复默认配置。
152+
143153
### 8.1 Compose 黑盒 Git 协议 smoke(`git` 客户端)
144154

145155
Trunk / storage-only 协议冒烟使用 **`scripts/git_protocol_smoke_storage_only.sh`**,经 compose `--profile smoke` 的 `git-smoke` 容器内真实 **`git` / `git-lfs` / `ssh`** 调用已发布端口。这是 **compose 黑盒**,与 cargo `CARGO_BIN_EXE` 黑盒分层并存;**不要**用 `libra` 作协议客户端,也**不要**在 trunk 上跑 review/CL 语义的 `scripts/git_protocol_smoke.sh`。

‎docs/plan/plan-20261001.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@
749749
### Task BB-05: libra 作用域注记
750750

751751
**Task type:** `docs`
752-
**Lifecycle / Acceptance:** `in-progress` / `locally-accepted`(Codex R1 PASS;本地提交 `BB-05:`,随 BB-03 发布推送)
752+
**Lifecycle / Acceptance:** `in-progress` / `remote-pending`(本地提交 `BB-05:`,随 v0.41.5 推送并继承 BB-03 的 C / D)
753753
**Description:** 按 ADR-BB-03 在 plan-20260906 ADR-SO-09、plan-20260904 GC-AW-04、plan-20260917 GC-LB-04、plan-20260918 GC-FT-04、`docs/refactoring/test-infra.md`、`docs/deploy-trunk.md` 的 libra 禁令处加「作用域 = Git 协议 / API 写 smoke;Libra 互通 smoke 见 plan-20261001」注记,并用零命中守卫证明既有两个脚本仍无 libra 协议调用。唯一行为轴:libra 禁令的作用域表述。
754754
**Out of scope:** 改既有脚本(永久非目标);推翻 ADR-SO-09(永久非目标,ADR-BB-03)。
755755
**Current evidence:**
@@ -820,7 +820,7 @@
820820
### Task BB-03: opt-in 切栈 helper
821821

822822
**Task type:** `implementation`
823-
**Lifecycle / Acceptance:** `pending` / (空)
823+
**Lifecycle / Acceptance:** `in-progress` / `remote-pending`(v0.41.5;Codex R2 PASS;C 组 2023 测试通过;待 Release 与 D 组 `docker` job)
824824
**Description:** 新建宿主侧 `scripts/bb_optin_run.sh <none|gc|local> <script> <case> <log>`(另有 `--selftest <mode> <log>`:不跑 smoke 脚本,而在 `interop-smoke` 内执行桩命令——打印 `bb-optin-selftest-case-ran`、用 `curl` 读取 `/api/v1/repos/bb-selftest/artifacts/discovery` 并打印 `bb-optin-selftest-signed_url_put=<值>`,然后退出 1):记录切换前 `docker compose config --hash mega2`,按模式切换 mega2(none = 叠加 auth-none override;gc / local = 对应 env-file)并 `--force-recreate`,打印 `bb-optin: switched config hash <before> != <after>`,以对应开关环境变量在 `interop-smoke` 内运行单 case 并 tee 到 log;`trap` 保证无论 case 成败都恢复默认栈并比对 hash。唯一行为轴:opt-in 栈切换与恢复(正常路径)。
825825
**Out of scope:** 任何 case(opt-in 场景卡承接);输入校验与错误退出码(BB-07);创建 GC env-file(BB-46 承接)。
826826
**Current evidence:**

‎scripts/bb_optin_run.sh‎

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#!/usr/bin/env bash
2+
# Host-side helper that runs one opt-in smoke case of plan-20261001 on a
3+
# temporarily switched mega2 and always restores the default stack
4+
# (ADR-BB-06).
5+
#
6+
# Usage:
7+
# scripts/bb_optin_run.sh <none|gc|local> <script> <case> <log>
8+
# scripts/bb_optin_run.sh --selftest <none|gc|local> <log>
9+
#
10+
# Modes (mega2 is recreated with --force-recreate):
11+
# none overlay docker/docker-compose-storage-only.auth-none.yml (push_auth=none)
12+
# gc --env-file config/compose.env.storage-only.artifacts-gc
13+
# local --env-file config/compose.env.storage-only.local (local object storage)
14+
#
15+
# The case runs inside the `interop-smoke` service with its opt-in switch set
16+
# (MEGA2_SMOKE_AUTH_NONE / MEGA2_SMOKE_ARTIFACTS_GC / MEGA2_SMOKE_LOCAL_STORAGE)
17+
# and its output is tee'd to <log>. An EXIT trap recreates mega2 with the
18+
# default configuration and compares its compose config hash with the one
19+
# recorded before the switch.
20+
#
21+
# --selftest runs a stub instead of a smoke script: it prints
22+
# `bb-optin-selftest-case-ran`, reads the artifacts discovery document and
23+
# prints `bb-optin-selftest-signed_url_put=<value>`, then exits 1.
24+
#
25+
# Exit codes: 0 = case passed and stack restored; 1 = case failed and stack
26+
# restored; 2 = another helper run holds the stack lock (nothing switched).
27+
#
28+
# Only one helper run may own the mega2-trunk stack at a time: a lock
29+
# directory is held from the initial config hash through restoration.
30+
set -euo pipefail
31+
32+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
33+
cd "$ROOT"
34+
35+
COMPOSE=(docker compose -p mega2-trunk -f docker/docker-compose-storage-only.yml)
36+
CONFIG_DIR="config"
37+
38+
selftest=0
39+
if [ "${1:-}" = "--selftest" ]; then
40+
selftest=1
41+
mode="${2:-}"
42+
script=""
43+
case_name="selftest"
44+
log="${3:-}"
45+
else
46+
mode="${1:-}"
47+
script="${2:-}"
48+
case_name="${3:-}"
49+
log="${4:-}"
50+
fi
51+
52+
switched_args=()
53+
switch_var=""
54+
case "$mode" in
55+
none)
56+
switched_args=(-f docker/docker-compose-storage-only.auth-none.yml)
57+
switch_var=MEGA2_SMOKE_AUTH_NONE
58+
;;
59+
gc)
60+
switched_args=(--env-file "$CONFIG_DIR/compose.env.storage-only.artifacts-gc")
61+
switch_var=MEGA2_SMOKE_ARTIFACTS_GC
62+
;;
63+
local)
64+
switched_args=(--env-file "$CONFIG_DIR/compose.env.storage-only.local")
65+
switch_var=MEGA2_SMOKE_LOCAL_STORAGE
66+
;;
67+
*)
68+
echo "usage: $0 <none|gc|local> <script> <case> <log> | --selftest <mode> <log>" >&2
69+
exit 64
70+
;;
71+
esac
72+
73+
LOCK_DIR="${TMPDIR:-/tmp}/mega2-trunk-optin.lock"
74+
if ! mkdir "$LOCK_DIR" 2>/dev/null; then
75+
echo "bb-optin: another helper run holds $LOCK_DIR; nothing switched" >&2
76+
exit 2
77+
fi
78+
trap 'rmdir "$LOCK_DIR"' EXIT
79+
80+
mkdir -p "$(dirname "$log")"
81+
umask 077
82+
: > "$log"
83+
chmod 600 "$log"
84+
say() { echo "$*" | tee -a "$log"; }
85+
86+
config_hash() {
87+
"$@" config --hash mega2 | awk '{print $2}'
88+
}
89+
90+
default_hash=$(config_hash "${COMPOSE[@]}")
91+
say "bb-optin: config hash before: $default_hash"
92+
93+
# shellcheck disable=SC2317,SC2329 # invoked indirectly via `trap restore EXIT`
94+
restore() {
95+
local rc=$?
96+
set +e
97+
"${COMPOSE[@]}" up -d --wait --no-deps --force-recreate mega2 >> "$log" 2>&1
98+
local up_rc=$?
99+
local after
100+
after=$(config_hash "${COMPOSE[@]}")
101+
if [ "$up_rc" -eq 0 ] && [ "$after" = "$default_hash" ]; then
102+
say "bb-optin: restored mega2 (config hash match)"
103+
else
104+
say "bb-optin: restore FAILED (up exit $up_rc, hash $after, want $default_hash)"
105+
fi
106+
rmdir "$LOCK_DIR"
107+
exit "$rc"
108+
}
109+
trap restore EXIT
110+
111+
"${COMPOSE[@]}" "${switched_args[@]}" up -d --wait --no-deps --force-recreate mega2 >> "$log" 2>&1
112+
switched_hash=$(config_hash "${COMPOSE[@]}" "${switched_args[@]}")
113+
if [ "$switched_hash" = "$default_hash" ]; then
114+
say "bb-optin: switch did not change the mega2 config (hash $switched_hash)"
115+
exit 1
116+
fi
117+
say "bb-optin: switched config hash $default_hash != $switched_hash"
118+
119+
set +e
120+
if [ "$selftest" -eq 1 ]; then
121+
# shellcheck disable=SC2016 # the script body is expanded inside the container
122+
"${COMPOSE[@]}" --profile interop exec -T interop-smoke bash -c '
123+
echo bb-optin-selftest-case-ran
124+
v=$(curl -fsS http://127.0.0.1:9000/api/v1/repos/bb-selftest/artifacts/discovery | jq -r .transfers.signed_url_put)
125+
echo "bb-optin-selftest-signed_url_put=$v"
126+
exit 1' 2>&1 | tee -a "$log"
127+
else
128+
"${COMPOSE[@]}" --profile interop exec -T -e "$switch_var=1" -e "MEGA2_SMOKE_CASE=$case_name" \
129+
interop-smoke bash "/repo/scripts/$script" 2>&1 | tee -a "$log"
130+
fi
131+
case_rc=${PIPESTATUS[0]}
132+
set -e
133+
exit "$case_rc"

0 commit comments

Comments
 (0)