项目文件夹

文件
wehub-resource-sync bcbd1bdb22
Integ / changes (push) Has been skipped
Pre-commit / pre-commit (push) Failing after 1s
CLI exit codes / changes (push) Has been skipped
Test (Install) / changes (push) Has been skipped
Test (Python) / changes (push) Has been skipped
Test (TypeScript) / changes (push) Has been skipped
CLI exit codes / cli-gate (push) Has been cancelled
Test (Install) / test-install-gate (push) Has been cancelled
Integ / integ-gate (push) Has been cancelled
Test (Python) / test-python-gate (push) Has been cancelled
Test (TypeScript) / test-typescript-gate (push) Has been cancelled
Test (Install) / python-minimal (3.12) (push) Has been cancelled
Test (Install) / python-minimal (3.11) (push) Has been cancelled
Test (Install) / python-extra (agno, mirage.agents.agno) (push) Has been cancelled
Test (Install) / python-extra (chroma, mirage.resource.chroma) (push) Has been cancelled
Test (Install) / python-extra (pdf, mirage.core.filetype.pdf) (push) Has been cancelled
Integ / integ (push) Has been cancelled
Integ / integ-database (push) Has been cancelled
Integ / integ-database-ts (push) Has been cancelled
Integ / integ-data (push) Has been cancelled
Integ / integ-ssh (push) Has been cancelled
Integ / integ-ssh-ts (push) Has been cancelled
Test (Python) / audit (push) Has been cancelled
Test (TypeScript) / test (push) Has been cancelled
Test (TypeScript) / python-fs-shim (push) Has been cancelled
CLI exit codes / Python CLI (push) Has been cancelled
CLI exit codes / TypeScript CLI (push) Has been cancelled
CLI exit codes / Cross-language snapshot interop (push) Has been cancelled
Test (Python) / test (push) Has been cancelled
Test (Python) / import-isolation (deepagents, openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Python) / import-isolation (deepagents, pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Integ / integ-ts (push) Has been cancelled
Integ / integ-fuse (push) Has been cancelled
Test (Install) / python-extra (databricks, mirage.resource.databricks_volume) (push) Has been cancelled
Test (Install) / python-extra (deepagents, mirage.agents.langchain) (push) Has been cancelled
Test (Install) / python-extra (email, mirage.resource.email) (push) Has been cancelled
Test (Install) / python-extra (fuse, mirage.fuse.mount) (push) Has been cancelled
Test (Install) / python-extra (hdf5, mirage.core.filetype.hdf5) (push) Has been cancelled
Test (Install) / python-extra (hf, mirage.resource.hf_buckets) (push) Has been cancelled
Test (Install) / python-extra (lancedb, mirage.resource.lancedb) (push) Has been cancelled
Test (Install) / python-extra (langfuse, mirage.resource.langfuse) (push) Has been cancelled
Test (Install) / python-extra (mongodb, mirage.resource.mongodb) (push) Has been cancelled
Test (Install) / python-extra (nextcloud, mirage.resource.nextcloud) (push) Has been cancelled
Test (Install) / python-extra (openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Install) / python-extra (openhands, mirage.agents.openhands, 3.12) (push) Has been cancelled
Test (Install) / python-extra (parquet, mirage.core.filetype.parquet) (push) Has been cancelled
Test (Install) / python-extra (postgres, mirage.resource.postgres) (push) Has been cancelled
Test (Install) / python-extra (pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Test (Install) / python-extra (qdrant, mirage.resource.qdrant) (push) Has been cancelled
Test (Install) / python-extra (redis, mirage.resource.redis) (push) Has been cancelled
Test (Install) / python-extra (s3, mirage.resource.s3) (push) Has been cancelled
Test (Install) / python-extra (ssh, mirage.resource.ssh) (push) Has been cancelled
Test (Install) / ts-minimal (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:30:44 +08:00

209 行
9.6 KiB
Bash
可执行文件

#!/usr/bin/env bash
# Cross-language CLI feature parity. Runs the SAME battery of commands on the
# Python CLI and the TypeScript CLI, records normalized results per language,
# then asserts (1) the two languages produce identical results and (2) the
# results match the expected values. Covers subshell isolation, sessions,
# git-backed versioning, and fuse config wiring. Uses RAM mounts only (no
# redis/minio/fuse kernel deps), so it runs anywhere both CLIs are built.
#
# Usage: parity.sh "<py-cli>" "<ts-cli>"
set -uo pipefail
PY_CLI="${1:?python mirage cli command}"
TS_CLI="${2:?typescript mirage cli command}"
HERE="$(cd "$(dirname "$0")" && pwd)"
fail=0
YAML=/tmp/parity-ws.yaml
cat > "$YAML" <<'YML'
mounts:
/:
resource: ram
mode: WRITE
YML
FUSE_YAML=/tmp/parity-fuse.yaml
cat > "$FUSE_YAML" <<'YML'
mode: WRITE
mounts:
/:
resource: ram
fuse: true
YML
freeport() { lsof -ti:8765 2>/dev/null | xargs kill -9 2>/dev/null; sleep 1; }
sout() { jq -r '.stdout // .result.stdout // empty'; }
sexit() { jq -r '.exit_code // .exitCode // .result.exit_code // empty'; }
# Run the full battery against one CLI; emit one "key=value" line per probe.
probe() {
local cli="$1" lang="$2"
export MIRAGE_VERSION_ROOT="/tmp/parity-repos-$lang"
rm -rf "$MIRAGE_VERSION_ROOT"
freeport
$cli daemon stop >/dev/null 2>&1 </dev/null || true
sleep 1
$cli workspace delete pw >/dev/null 2>&1 </dev/null || true
$cli workspace create "$YAML" --id pw >/dev/null </dev/null
$cli execute -w pw -c 'mkdir -p /data' </dev/null >/dev/null
# ── subshell: cd / export must not leak; exit + pipe ──
echo "subshell.cd_inner=$($cli execute -w pw -c '(cd /data && pwd)' </dev/null | sout)"
echo "subshell.cd_after=$($cli execute -w pw -c 'pwd' </dev/null | sout)"
echo "subshell.export_inner=$($cli execute -w pw -c '(export FOO=bar; echo $FOO)' </dev/null | sout)"
echo "subshell.export_after=$($cli execute -w pw -c 'echo [$FOO]' </dev/null | sout)"
echo "subshell.false_exit=$($cli execute -w pw -c '(false)' </dev/null | sexit)"
echo "subshell.pipe=$($cli execute -w pw -c '(echo a; echo b) | wc -l' </dev/null | sout)"
echo "subshell.oldpwd_no_leak=$($cli execute -w pw -c '(cd /data && (cd /) && echo $OLDPWD)' </dev/null | sout)"
echo "subshell.func_redef=$($cli execute -w pw -c '(f(){ echo A; }; (f(){ echo B; }); f)' </dev/null | sout)"
echo "subshell.func_no_leak=$($cli execute -w pw -c '(nofn(){ echo x; }); nofn 2>/dev/null || echo gone' </dev/null | sout)"
echo "subshell.positional=$($cli execute -w pw -c '(set -- a b c; (set -- x); echo $#)' </dev/null | sout)"
# ── cwd/env: HOME, PWD, OLDPWD, cd -, tilde (GNU cd + pwd) ──
$cli execute -w pw -c 'echo hi > /data/f.txt' </dev/null >/dev/null
echo "cwd.home_default=$($cli execute -w pw -c 'echo $HOME' </dev/null | sout)"
echo "cwd.pwd_var=$($cli execute -w pw -c '(cd /data && echo $PWD)' </dev/null | sout)"
echo "cwd.oldpwd=$($cli execute -w pw -c '(cd /data && cd / && echo $OLDPWD)' </dev/null | sout)"
echo "cwd.cd_dash=$($cli execute -w pw -c '(cd /data && cd / && cd -)' </dev/null | sout)"
echo "cwd.tilde_pwd=$($cli execute -w pw -c '(export HOME=/data && cd ~ && pwd)' </dev/null | sout)"
echo "cwd.tilde_cat=$($cli execute -w pw -c '(export HOME=/data && cat ~/f.txt)' </dev/null | sout)"
echo "cwd.rel_cat=$($cli execute -w pw -c '(cd /data && cat f.txt)' </dev/null | sout)"
echo "cwd.wc_disp=$($cli execute -w pw -c '(cd /data && wc -l f.txt)' </dev/null | sout)"
# ── sessions: default session persists cwd; -s session is isolated ──
$cli session create pw --id s2 </dev/null >/dev/null
$cli execute -w pw -c 'cd /data' </dev/null >/dev/null
echo "session.default_pwd=$($cli execute -w pw -c 'pwd' </dev/null | sout)"
echo "session.s2_pwd=$($cli execute -w pw -s s2 -c 'pwd' </dev/null | sout)"
# ── symlinks: namespace links follow on read; rm/mv act on the entry ──
$cli execute -w pw -c 'echo sym1 > /data/s.txt && ln -s /data/s.txt /data/link.txt' </dev/null >/dev/null
echo "sym.readlink=$($cli execute -w pw -c 'readlink /data/link.txt' </dev/null | sout)"
echo "sym.cat_follow=$($cli execute -w pw -c 'cat /data/link.txt' </dev/null | sout)"
echo "sym.write_through=$($cli execute -w pw -c 'echo via >> /data/link.txt && tail -n 1 /data/s.txt' </dev/null | sout)"
echo "sym.ls_arrow=$($cli execute -w pw -c 'ls -l /data | grep -- "->"' </dev/null | sout)"
echo "sym.mv_entry=$($cli execute -w pw -c 'mv /data/link.txt /data/moved.txt && readlink /data/moved.txt' </dev/null | sout)"
echo "sym.rm_entry=$($cli execute -w pw -c 'rm /data/moved.txt; readlink /data/moved.txt' </dev/null | sexit)"
echo "sym.dangle=$($cli execute -w pw -c 'ln -s /data/none /data/d.txt; cat /data/d.txt' </dev/null | sexit)"
echo "sym.eloop=$($cli execute -w pw -c 'ln -s /data/l2 /data/l1 && ln -s /data/l1 /data/l2; cat /data/l1 2>&1' </dev/null | sout)"
$cli workspace delete pw >/dev/null 2>&1 </dev/null || true
# ── versioning: commit/branch/log/clone/checkout/diff (git-backed) ──
$cli workspace delete vw >/dev/null 2>&1 </dev/null || true
$cli workspace create "$YAML" --id vw >/dev/null </dev/null
$cli execute -w vw -c 'echo one > /a.txt' </dev/null >/dev/null
$cli workspace commit vw -m first </dev/null >/dev/null
$cli workspace branch vw feature </dev/null >/dev/null # feature @ first
$cli execute -w vw -c 'echo two > /a.txt' </dev/null >/dev/null
$cli workspace commit vw -m second </dev/null >/dev/null # main @ second
echo "version.log=$($cli workspace log vw </dev/null | jq -r '[.[].message] | join(",")')"
echo "version.branch_log=$($cli workspace log vw -b feature </dev/null | jq -r '[.[].message] | join(",")')"
echo "ws.get_mounts=$($cli workspace get vw </dev/null | jq -r '[.mounts[].prefix] | join(",")')"
echo "ws.list_has_vw=$($cli workspace list </dev/null | jq -r 'if (map(.id) | index("vw")) != null then "yes" else "no" end')"
# clone live state (two), and clone from the first commit (one)
$cli workspace delete vwc >/dev/null 2>&1 </dev/null || true
$cli workspace clone vw --id vwc </dev/null >/dev/null
echo "clone.content=$($cli execute -w vwc -c 'cat /a.txt' </dev/null | sout)"
$cli workspace delete vwc >/dev/null 2>&1 </dev/null || true
local first
first="$($cli workspace log vw </dev/null | jq -r '.[-1].id')"
$cli workspace delete vwa >/dev/null 2>&1 </dev/null || true
$cli workspace clone vw --id vwa --at "$first" </dev/null >/dev/null
echo "clone.at_first=$($cli execute -w vwa -c 'cat /a.txt' </dev/null | sout)"
$cli workspace delete vwa >/dev/null 2>&1 </dev/null || true
$cli workspace checkout vw "$first" </dev/null >/dev/null 2>&1
echo "version.checkout_first=$($cli execute -w vw -c 'cat /a.txt' </dev/null | sout)"
$cli workspace checkout vw main </dev/null >/dev/null 2>&1
$cli execute -w vw -c 'echo three > /a.txt' </dev/null >/dev/null
echo "version.diff=$($cli workspace diff vw </dev/null | jq -rc '{added,modified,deleted}')"
$cli workspace delete vw >/dev/null 2>&1 </dev/null || true
# ── fuse: fuse:true config is accepted and the workspace operates ──
$cli workspace delete fw >/dev/null 2>&1 </dev/null || true
$cli workspace create "$FUSE_YAML" --id fw >/dev/null </dev/null
echo "fuse.operates=$($cli execute -w fw -c 'echo alive' </dev/null | sout)"
$cli workspace delete fw >/dev/null 2>&1 </dev/null || true
freeport
}
echo "===== probing Python CLI ====="
probe "$PY_CLI" py | sort > /tmp/parity-py.txt
echo "===== probing TypeScript CLI ====="
probe "$TS_CLI" ts | sort > /tmp/parity-ts.txt
echo
echo "===== Python results ====="
cat /tmp/parity-py.txt
echo
echo "===== language parity (py vs ts) ====="
if diff -u /tmp/parity-py.txt /tmp/parity-ts.txt; then
echo " OK Python and TypeScript produced identical results"
else
echo " FAIL Python and TypeScript diverged (see diff above)"
fail=1
fi
echo
echo "===== expected values ====="
expect() {
local key="$1" want="$2"
local got
got="$(grep -F "$key=" /tmp/parity-py.txt | head -1 | cut -d= -f2-)"
if [ "$got" == "$want" ]; then
echo " OK $key == $(printf '%q' "$want")"
else
echo " FAIL $key: got $(printf '%q' "$got") expected $(printf '%q' "$want")"
fail=1
fi
}
expect "subshell.cd_inner" "/data"
expect "subshell.cd_after" "/"
expect "subshell.export_inner" "bar"
expect "subshell.export_after" "[]"
expect "subshell.false_exit" "1"
expect "subshell.pipe" "2"
expect "subshell.oldpwd_no_leak" "/"
expect "subshell.func_redef" "A"
expect "subshell.func_no_leak" "gone"
expect "subshell.positional" "3"
expect "cwd.home_default" ""
expect "cwd.pwd_var" "/data"
expect "cwd.oldpwd" "/data"
expect "cwd.cd_dash" "/data"
expect "cwd.tilde_pwd" "/data"
expect "cwd.tilde_cat" "hi"
expect "cwd.rel_cat" "hi"
expect "cwd.wc_disp" "1 f.txt"
expect "session.default_pwd" "/data"
expect "session.s2_pwd" "/"
expect "version.log" "second,first"
expect "version.branch_log" "first"
expect "ws.get_mounts" "/"
expect "ws.list_has_vw" "yes"
expect "clone.content" "two"
expect "clone.at_first" "one"
expect "version.checkout_first" "one"
expect 'version.diff' '{"added":[],"modified":["a.txt"],"deleted":[]}'
expect "fuse.operates" "alive"
expect "sym.readlink" "/data/s.txt"
expect "sym.cat_follow" "sym1"
expect "sym.write_through" "via"
expect "sym.ls_arrow" "$(printf 'l\t-\t-\tlink.txt -> /data/s.txt')"
expect "sym.mv_entry" "/data/s.txt"
expect "sym.rm_entry" "1"
expect "sym.dangle" "1"
expect "sym.eloop" "cat: /data/l1: Too many levels of symbolic links"
if [ "$fail" != "0" ]; then
echo
echo "CLI feature parity FAILED."
exit 1
fi
echo
echo "CLI feature parity OK (subshell, sessions, versioning, fuse; py == ts)."