Skip to content

Commit 04e6af3

Browse files
genednaclaude
andcommitted
v0.41.12: BB-15 OCI cross-repo blob mount case
Register `OCI cross-repo blob mount` (plan-20261001 BB-15): mounting a blob from a source repository that holds it returns 201 and the target serves it; a source without the blob falls back to a new 202 upload session with Docker-Upload-UUID. Adds the oci_put_blob helper. Marks BB-14 done. 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 2a2a2f3 commit 04e6af3

5 files changed

Lines changed: 33 additions & 5 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.11"
3+
version = "0.41.12"
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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ CASE='OCI ping' # 换成要跑的 case 名
395395
docker compose -p mega2-trunk -f docker/docker-compose-storage-only.yml --profile interop exec -T -e MEGA2_SMOKE_CASE="$CASE" interop-smoke bash /repo/scripts/oci_client_smoke_storage_only.sh 2>&1 | tee target/tmp/bb-oci-case.log
396396
```
397397

398-
已登记 case:`OCI ping`、`OCI oras push and pull`、`OCI reject unauthenticated push`、`OCI chunked blob upload`。
398+
已登记 case:`OCI ping`、`OCI oras push and pull`、`OCI reject unauthenticated push`、`OCI chunked blob upload`、`OCI cross-repo blob mount`。
399399

400400
不设 `MEGA2_SMOKE_CASE` 时整跑全部默认栈 case;opt-in case(auth-none)只经 `scripts/bb_optin_run.sh none oci_client_smoke_storage_only.sh '<case>' <log>` 运行。
401401

‎docs/plan/plan-20261001.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,7 +1172,7 @@
11721172
### Task BB-14: OCI chunked blob upload
11731173

11741174
**Task type:** `implementation`
1175-
**Lifecycle / Acceptance:** `in-progress` / `remote-pending`(v0.41.11;Codex R2 PASS;C 组 2023 测试通过;待 D 组 `docker` job)
1175+
**Lifecycle / Acceptance:** `done` / `complete`(v0.41.11;C 组 2023 测试通过;D 组 docker run 36940801754 success)
11761176
**Description:** 在 `scripts/oci_client_smoke_storage_only.sh` 注册 case `OCI chunked blob upload`。`curl` 走 POST → 两次 PATCH → 状态 GET → PUT `?digest=`。 唯一行为轴:分块上传状态机。
11771177
**Out of scope:** 其它 case(各自成卡);改 `src/**`(产品缺陷按 ADR-BB-08 立 `FIX-BB-*`);改既有 smoke 脚本(GC-BB-06);以 cargo IT 作 VER(GC-BB-04)。
11781178
**Current evidence:**
@@ -1222,7 +1222,7 @@
12221222
### Task BB-15: OCI cross-repo blob mount
12231223

12241224
**Task type:** `implementation`
1225-
**Lifecycle / Acceptance:** `pending` / (空)
1225+
**Lifecycle / Acceptance:** `in-progress` / `remote-pending`(v0.41.12;Codex R1 PASS;C 组 2023 测试通过;待 D 组 `docker` job)
12261226
**Description:** 在 `scripts/oci_client_smoke_storage_only.sh` 注册 case `OCI cross-repo blob mount`。源仓单体上传 blob 后向目标仓 mount;再对无此 blob 的源仓 mount。 唯一行为轴:跨仓库挂载。
12271227
**Out of scope:** 其它 case(各自成卡);改 `src/**`(产品缺陷按 ADR-BB-08 立 `FIX-BB-*`);改既有 smoke 脚本(GC-BB-06);以 cargo IT 作 VER(GC-BB-04)。
12281228
**Current evidence:**

‎scripts/oci_client_smoke_storage_only.sh‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,37 @@ case_oci_chunked_upload() {
167167
[ "$(oci_header "$d/h4" docker-content-digest)" = "$dg" ] || { echo "Docker-Content-Digest mismatch" >&2; return 1; }
168168
}
169169

170+
# oci_put_blob <repo> <file>: monolithic upload, prints the HTTP status.
171+
oci_put_blob() {
172+
oci_curl -u "bb:$TOKEN" -X POST -o /dev/null -w '%{http_code}' \
173+
-H 'Content-Type: application/octet-stream' --data-binary @"$2" \
174+
"$MEGA2_BASE_URL/v2/$1/blobs/uploads/?digest=$(oci_digest "$2")"
175+
}
176+
177+
# --- BB-15 OCI cross-repo blob mount ------------------------------------
178+
case_oci_cross_repo_mount() {
179+
local d="$WORK/mount" src="bb-$RUN_ID/mount-src" dst="bb-$RUN_ID/mount-dst" code dg
180+
oci_case_begin
181+
mkdir -p "$d"
182+
head -c 512 /dev/urandom > "$d/blob"
183+
dg=$(oci_digest "$d/blob")
184+
code=$(oci_put_blob "$src" "$d/blob")
185+
[ "$code" = 201 ] || { echo "source upload returned $code" >&2; return 1; }
186+
code=$(oci_curl -u "bb:$TOKEN" -X POST -o /dev/null -w '%{http_code}' \
187+
"$MEGA2_BASE_URL/v2/$dst/blobs/uploads/?mount=$dg&from=$src")
188+
[ "$code" = 201 ] || { echo "mount from a source holding the blob returned $code" >&2; return 1; }
189+
code=$(oci_curl -I -o /dev/null -w '%{http_code}' "$MEGA2_BASE_URL/v2/$dst/blobs/$dg")
190+
[ "$code" = 200 ] || { echo "HEAD of the mounted blob returned $code" >&2; return 1; }
191+
code=$(oci_curl -u "bb:$TOKEN" -X POST -D "$d/h" -o /dev/null -w '%{http_code}' \
192+
"$MEGA2_BASE_URL/v2/$dst/blobs/uploads/?mount=$dg&from=bb-$RUN_ID/mount-empty")
193+
[ "$code" = 202 ] || { echo "mount from a source without the blob returned $code" >&2; return 1; }
194+
[ -n "$(oci_header "$d/h" docker-upload-uuid)" ] || { echo "fallback session without Docker-Upload-UUID" >&2; return 1; }
195+
}
196+
170197
run_case "OCI ping" case_oci_ping
171198
run_case "OCI oras push and pull" case_oci_oras_push_pull
172199
run_case "OCI reject unauthenticated push" case_oci_reject_unauth_push
173200
run_case "OCI chunked blob upload" case_oci_chunked_upload
201+
run_case "OCI cross-repo blob mount" case_oci_cross_repo_mount
174202

175203
finish

0 commit comments

Comments
 (0)