Skip to content

Commit c340749

Browse files
genednaclaude
andcommitted
v0.41.9: BB-12 OCI oras push and pull case
Register `OCI oras push and pull` (plan-20261001 BB-12): oras login with per-run credentials, push of two files, pull into an empty directory with byte-identical files, and the single pushed Digest equal to the manifest descriptor. Adds a per-case deadline (oci_case_begin / oci_t / oci_curl) and oci_run, which prints command output redacted only on failure. Marks BB-11 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 26c7f23 commit c340749

5 files changed

Lines changed: 60 additions & 8 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.8"
3+
version = "0.41.9"
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`。
398+
已登记 case:`OCI ping`、`OCI oras push and pull`。
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
@@ -1021,7 +1021,7 @@
10211021
### Task BB-11: OCI ping
10221022

10231023
**Task type:** `implementation`
1024-
**Lifecycle / Acceptance:** `in-progress` / `remote-pending`(v0.41.8;Codex R2 PASS;C 组 2023 测试通过;待 D 组 `docker` job)
1024+
**Lifecycle / Acceptance:** `done` / `complete`(v0.41.8;Codex R2 PASS;C 组 2023 测试通过;D 组 docker run 36927898869 success)
10251025
**Description:** 在 `scripts/oci_client_smoke_storage_only.sh` 注册 case `OCI ping`。匿名 `GET /v2/` 与无效 Bearer 的质询。 唯一行为轴:OCI 匿名 ping。
10261026
**Out of scope:** 其它 case(各自成卡);改 `src/**`(产品缺陷按 ADR-BB-08 立 `FIX-BB-*`);改既有 smoke 脚本(GC-BB-06);以 cargo IT 作 VER(GC-BB-04)。
10271027
**Current evidence:**
@@ -1072,7 +1072,7 @@
10721072
### Task BB-12: OCI oras push and pull
10731073

10741074
**Task type:** `implementation`
1075-
**Lifecycle / Acceptance:** `pending` / (空)
1075+
**Lifecycle / Acceptance:** `in-progress` / `remote-pending`(v0.41.9;Codex R2 PASS;C 组 2023 测试通过;待 D 组 `docker` job)
10761076
**Description:** 在 `scripts/oci_client_smoke_storage_only.sh` 注册 case `OCI oras push and pull`。`oras login --plain-http --password-stdin` 后推送两文件 artifact 到 `bb-${RUN_ID}/oras` 并拉回。 唯一行为轴:oras 高层推拉往返。
10771077
**Out of scope:** 其它 case(各自成卡);改 `src/**`(产品缺陷按 ADR-BB-08 立 `FIX-BB-*`);改既有 smoke 脚本(GC-BB-06);以 cargo IT 作 VER(GC-BB-04)。
10781078
**Current evidence:**

‎scripts/oci_client_smoke_storage_only.sh‎

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ SCRIPT_DIR="${BASH_SOURCE[0]%/*}"
1919
source "$SCRIPT_DIR/lib/smoke-runner.sh"
2020

2121
smoke_init "oci client"
22-
require_tools curl jq oras sha256sum mktemp date rm perl awk tr
22+
require_tools curl jq oras sha256sum mktemp date rm perl awk tr timeout rg grep
2323

2424
MEGA2_BASE_URL="${MEGA2_BASE_URL:-http://127.0.0.1:9000}"
2525
MEGA2_BASE_URL="${MEGA2_BASE_URL%/}"
@@ -38,8 +38,36 @@ code=$(curl -sS --connect-timeout 3 --max-time 5 -o /dev/null -w '%{http_code}'
3838
export REGISTRY RUN_ID WORK TOKEN MEGA2_BASE_URL
3939

4040
# --- shared OCI helpers -------------------------------------------------
41-
# oci_curl: curl with bounded connection and total time.
42-
oci_curl() { curl -sS --connect-timeout 5 --max-time 30 "$@"; }
41+
# Every case has one deadline (OCI_CASE_BUDGET seconds, default 60) set by
42+
# oci_case_begin; oci_curl and oci_t only get the time that is left.
43+
OCI_CASE_BUDGET="${OCI_CASE_BUDGET:-60}"
44+
oci_case_begin() { OCI_DEADLINE=$((SECONDS + OCI_CASE_BUDGET)); }
45+
oci_left() { echo $(( ${OCI_DEADLINE:-$((SECONDS + OCI_CASE_BUDGET))} - SECONDS )); }
46+
# oci_t <cmd...>: run a command within the remaining case budget.
47+
oci_t() {
48+
local left
49+
left=$(oci_left)
50+
[ "$left" -gt 0 ] || { echo "case budget exhausted" >&2; return 124; }
51+
timeout "$left" "$@"
52+
}
53+
# oci_curl: curl with a 5 s connect timeout and the remaining case budget.
54+
oci_curl() {
55+
local left
56+
left=$(oci_left)
57+
[ "$left" -gt 0 ] || { echo "case budget exhausted" >&2; return 124; }
58+
curl -sS --connect-timeout 5 --max-time "$left" "$@"
59+
}
60+
# oci_run <outfile> <cmd...>: run within the budget, keep stdout+stderr in
61+
# <outfile>, and print it redacted when the command fails.
62+
oci_run() {
63+
local out="$1"
64+
shift
65+
if oci_t "$@" > "$out" 2>&1; then
66+
return 0
67+
fi
68+
redact "$TOKEN" < "$out" >&2
69+
return 1
70+
}
4371
# oci_header <file> <name>: exact value of a response header (case-insensitive name).
4472
oci_header() {
4573
awk -v n="$(printf '%s' "$2" | tr '[:upper:]' '[:lower:]')" \
@@ -49,6 +77,7 @@ oci_header() {
4977
# --- BB-11 OCI ping -----------------------------------------------------
5078
case_oci_ping() {
5179
local hdr="$WORK/ping.hdr" code
80+
oci_case_begin
5281
code=$(oci_curl -D "$hdr" -o /dev/null -w '%{http_code}' "$MEGA2_BASE_URL/v2/")
5382
[ "$code" = 200 ] || { echo "anonymous GET /v2/ returned $code" >&2; return 1; }
5483
[ "$(oci_header "$hdr" docker-distribution-api-version)" = "registry/2.0" ] \
@@ -58,6 +87,29 @@ case_oci_ping() {
5887
[ -n "$(oci_header "$hdr" www-authenticate)" ] || { echo "401 without WWW-Authenticate" >&2; return 1; }
5988
}
6089

90+
# --- BB-12 OCI oras push and pull ---------------------------------------
91+
case_oci_oras_push_pull() {
92+
local dir="$WORK/oras" ref="$REGISTRY/bb-$RUN_ID/oras:v1" pushed fetched
93+
oci_case_begin
94+
mkdir -p "$dir/src" "$dir/out"
95+
export DOCKER_CONFIG="$dir/docker"
96+
printf 'bb oras one %s\n' "$RUN_ID" > "$dir/src/one.txt"
97+
printf 'bb oras two %s\n' "$RUN_ID" > "$dir/src/two.txt"
98+
printf '%s' "$TOKEN" | oci_run "$dir/login.out" oras login --plain-http -u bb --password-stdin "$REGISTRY"
99+
(cd "$dir/src" && oci_run "$dir/push.out" oras push --plain-http "$ref" one.txt two.txt)
100+
pushed=$(rg -o '^Digest: (sha256:[0-9a-f]{64})$' -r '$1' "$dir/push.out")
101+
[ "$(printf '%s\n' "$pushed" | grep -c '^sha256:')" = 1 ] || { echo "push output does not hold exactly one Digest line" >&2; return 1; }
102+
(cd "$dir/out" && oci_run "$dir/pull.out" oras pull --plain-http "$ref")
103+
for f in one.txt two.txt; do
104+
[ "$(sha256sum < "$dir/src/$f")" = "$(sha256sum < "$dir/out/$f")" ] \
105+
|| { echo "pulled $f differs from the pushed file" >&2; return 1; }
106+
done
107+
oci_run "$dir/desc.json" oras manifest fetch --plain-http --descriptor "$ref"
108+
fetched=$(jq -r .digest "$dir/desc.json")
109+
[ "$pushed" = "$fetched" ] || { echo "push digest $pushed != descriptor digest $fetched" >&2; return 1; }
110+
}
111+
61112
run_case "OCI ping" case_oci_ping
113+
run_case "OCI oras push and pull" case_oci_oras_push_pull
62114

63115
finish

0 commit comments

Comments
 (0)