Skip to content

Commit fbec3ca

Browse files
aaajiaoclaude
andcommitted
feat: per-image sandbox build hash for selective rebuilds
Replace monolithic 6-file hash with 3 per-image hashes that respect the actual dependency chain (base→common cascade, browser independent). Only changed images rebuild during updates, saving several minutes when e.g. only the browser Dockerfile changes. Includes zero-rebuild migration for existing users: old hash file is converted to 3 per-image hashes without triggering unnecessary builds. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 24f2171 commit fbec3ca

6 files changed

Lines changed: 154 additions & 50 deletions

File tree

lang/en.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ MSG_CMD_UPDATE_SANDBOX_CHANGED=" 📦 Sandbox build files changed, rebuilding i
115115
MSG_CMD_UPDATE_SANDBOX_BASE=" Building base image..."
116116
MSG_CMD_UPDATE_SANDBOX_COMMON=" Building common image..."
117117
MSG_CMD_UPDATE_SANDBOX_BROWSER=" Building browser image..."
118+
MSG_CMD_UPDATE_SANDBOX_BASE_SKIP=" ✓ base image unchanged, skipping"
119+
MSG_CMD_UPDATE_SANDBOX_COMMON_SKIP=" ✓ common image unchanged, skipping"
120+
MSG_CMD_UPDATE_SANDBOX_BROWSER_SKIP=" ✓ browser image unchanged, skipping"
121+
MSG_CMD_UPDATE_SANDBOX_COMMON_CASCADE=" ↳ base changed, common must also rebuild"
118122
MSG_CMD_UPDATE_SANDBOX_NOTE=" 💡 Running containers still use old images, restart to apply"
119123
MSG_CMD_UPDATE_STARTING=" Starting service..."
120124
MSG_CMD_UPDATE_DONE="✅ Update complete!"

lang/zh-CN.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ MSG_CMD_UPDATE_SANDBOX_CHANGED=" 📦 检测到沙箱构建文件变化,自
115115
MSG_CMD_UPDATE_SANDBOX_BASE=" 构建基础镜像..."
116116
MSG_CMD_UPDATE_SANDBOX_COMMON=" 构建 common 镜像..."
117117
MSG_CMD_UPDATE_SANDBOX_BROWSER=" 构建浏览器镜像..."
118+
MSG_CMD_UPDATE_SANDBOX_BASE_SKIP=" ✓ 基础镜像无变化,跳过"
119+
MSG_CMD_UPDATE_SANDBOX_COMMON_SKIP=" ✓ common 镜像无变化,跳过"
120+
MSG_CMD_UPDATE_SANDBOX_BROWSER_SKIP=" ✓ 浏览器镜像无变化,跳过"
121+
MSG_CMD_UPDATE_SANDBOX_COMMON_CASCADE=" ↳ 基础镜像已变更,common 必须重建"
118122
MSG_CMD_UPDATE_SANDBOX_NOTE=" 💡 已运行的容器仍使用旧镜像,重启后生效"
119123
MSG_CMD_UPDATE_STARTING=" 启动服务..."
120124
MSG_CMD_UPDATE_DONE="✅ 更新完成!"

openclaw-orbstack-setup.sh

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,8 +296,11 @@ else
296296
warn "$MSG_WARN_SANDBOX_BROWSER_FAIL"
297297
fi
298298

299-
# Save sandbox build hash for staleness detection during updates
300-
vm_exec "cd ~/openclaw && cat Dockerfile.sandbox Dockerfile.sandbox-browser scripts/sandbox-setup.sh scripts/sandbox-common-setup.sh scripts/sandbox-browser-setup.sh 2>/dev/null | sha256sum | cut -d' ' -f1 > ~/.openclaw/.sandbox-build-hash"
299+
# Save per-image sandbox build hashes for staleness detection during updates
300+
vm_exec "cd ~/openclaw && \
301+
cat Dockerfile.sandbox scripts/sandbox-setup.sh 2>/dev/null | sha256sum | cut -c1-64 > ~/.openclaw/.sandbox-hash-base && \
302+
cat Dockerfile.sandbox-common scripts/sandbox-common-setup.sh 2>/dev/null | sha256sum | cut -c1-64 > ~/.openclaw/.sandbox-hash-common && \
303+
cat Dockerfile.sandbox-browser scripts/sandbox-browser-setup.sh 2>/dev/null | sha256sum | cut -c1-64 > ~/.openclaw/.sandbox-hash-browser"
301304

302305
# ============================================================================
303306
# Step 7/8

scripts/commands/_common.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ if [ -f "$HOME/bin/.openclaw-lang" ]; then
3838
source "$HOME/bin/.openclaw-lang"
3939
_OPENCLAW_LANG="${OPENCLAW_LANG:-en}"
4040
fi
41+
# Save per-image sandbox build hash on VM
42+
# Usage: save_sandbox_hash <image_name> <file1> [file2 ...]
43+
save_sandbox_hash() {
44+
local name="$1"; shift
45+
orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && cat $* 2>/dev/null | sha256sum | cut -c1-64 > ~/.openclaw/.sandbox-hash-$name"
46+
}
47+
4148
_LANG_FILE="$OPENCLAW_REPO_DIR/lang/${_OPENCLAW_LANG}.sh"
4249
if [ -f "$_LANG_FILE" ]; then
4350
# shellcheck disable=SC1090

scripts/commands/sandbox-rebuild.sh

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,54 +6,78 @@
66
source "$(dirname "$0")/_common.sh"
77

88
echo "$MSG_CMD_REBUILD_START"
9-
REBUILD_OK=true
9+
BASE_OK=false
10+
COMMON_OK=false
11+
BROWSER_OK=false
1012

1113
echo "$MSG_CMD_REBUILD_BASE"
1214
echo "$MSG_BUILD_PATIENCE"
1315
start_progress
1416
if orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && sg docker -c './scripts/sandbox-setup.sh'" 2>/dev/null; then
1517
stop_progress
18+
BASE_OK=true
1619
echo "$MSG_CMD_REBUILD_BASE_OK"
1720
elif orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && sg docker -c 'docker build -t openclaw-sandbox:bookworm-slim -f Dockerfile.sandbox .'" 2>/dev/null; then
1821
stop_progress
22+
BASE_OK=true
1923
echo "$MSG_CMD_REBUILD_BASE_OK_DF"
2024
else
2125
stop_progress
22-
REBUILD_OK=false
2326
echo "$MSG_CMD_REBUILD_BASE_FAIL"
2427
fi
2528

26-
echo "$MSG_CMD_REBUILD_COMMON"
27-
echo "$MSG_BUILD_PATIENCE"
28-
start_progress
29-
if orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && sg docker -c './scripts/sandbox-common-setup.sh'" 2>/dev/null; then
30-
stop_progress
31-
echo "$MSG_CMD_REBUILD_COMMON_OK"
29+
# Save base hash on success
30+
if [ "$BASE_OK" = true ]; then
31+
save_sandbox_hash base Dockerfile.sandbox scripts/sandbox-setup.sh
32+
fi
33+
34+
# Skip common if base failed (common depends on base)
35+
if [ "$BASE_OK" = true ]; then
36+
echo "$MSG_CMD_REBUILD_COMMON"
37+
echo "$MSG_BUILD_PATIENCE"
38+
start_progress
39+
if orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && sg docker -c './scripts/sandbox-common-setup.sh'" 2>/dev/null; then
40+
stop_progress
41+
COMMON_OK=true
42+
echo "$MSG_CMD_REBUILD_COMMON_OK"
43+
else
44+
stop_progress
45+
echo "$MSG_CMD_REBUILD_COMMON_FAIL"
46+
fi
3247
else
33-
stop_progress
34-
REBUILD_OK=false
3548
echo "$MSG_CMD_REBUILD_COMMON_FAIL"
3649
fi
3750

51+
# Save common hash on success
52+
if [ "$COMMON_OK" = true ]; then
53+
save_sandbox_hash common Dockerfile.sandbox-common scripts/sandbox-common-setup.sh
54+
fi
55+
3856
echo "$MSG_CMD_REBUILD_BROWSER"
3957
echo "$MSG_BUILD_PATIENCE"
4058
start_progress
4159
if orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && sg docker -c './scripts/sandbox-browser-setup.sh'" 2>/dev/null; then
4260
stop_progress
61+
BROWSER_OK=true
4362
echo "$MSG_CMD_REBUILD_BROWSER_OK"
4463
elif orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && sg docker -c 'docker build -t openclaw-sandbox-browser:bookworm-slim -f Dockerfile.sandbox-browser .'" 2>/dev/null; then
4564
stop_progress
65+
BROWSER_OK=true
4666
echo "$MSG_CMD_REBUILD_BROWSER_OK_DF"
4767
else
4868
stop_progress
49-
REBUILD_OK=false
5069
echo "$MSG_CMD_REBUILD_BROWSER_FAIL"
5170
fi
5271

53-
# Save new sandbox build hash only if all builds succeeded
54-
if [ "$REBUILD_OK" = true ]; then
55-
orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && cat Dockerfile.sandbox Dockerfile.sandbox-browser scripts/sandbox-setup.sh scripts/sandbox-common-setup.sh scripts/sandbox-browser-setup.sh 2>/dev/null | sha256sum | cut -d' ' -f1 > ~/.openclaw/.sandbox-build-hash"
56-
else
72+
# Save browser hash on success
73+
if [ "$BROWSER_OK" = true ]; then
74+
save_sandbox_hash browser Dockerfile.sandbox-browser scripts/sandbox-browser-setup.sh
75+
fi
76+
77+
# Clean up old monolithic hash file
78+
orb -m "$OPENCLAW_VM_NAME" bash -lc "rm -f ~/.openclaw/.sandbox-build-hash" 2>/dev/null || true
79+
80+
if [ "$BASE_OK" = false ] || [ "$COMMON_OK" = false ] || [ "$BROWSER_OK" = false ]; then
5781
echo "$MSG_CMD_REBUILD_PARTIAL"
5882
fi
5983

scripts/commands/update.sh

Lines changed: 95 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -103,47 +103,109 @@ orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && pnpm ui:build"
103103
echo "$MSG_CMD_UPDATE_REINSTALL"
104104
orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && sudo npm install -g ."
105105

106-
# Auto-detect sandbox Dockerfile changes
107-
OLD_HASH=$(orb -m "$OPENCLAW_VM_NAME" bash -lc "cat ~/.openclaw/.sandbox-build-hash 2>/dev/null || echo none")
108-
NEW_HASH=$(orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && cat Dockerfile.sandbox Dockerfile.sandbox-browser scripts/sandbox-setup.sh scripts/sandbox-common-setup.sh scripts/sandbox-browser-setup.sh 2>/dev/null | sha256sum | cut -d' ' -f1")
109-
if [ "$OLD_HASH" != "$NEW_HASH" ]; then
110-
SANDBOX=true
111-
echo "$MSG_CMD_UPDATE_SANDBOX_CHANGED"
106+
# --- Migrate old single hash → per-image hashes (no rebuild) ---
107+
orb -m "$OPENCLAW_VM_NAME" bash -lc '
108+
if [ -f ~/.openclaw/.sandbox-build-hash ] && [ ! -f ~/.openclaw/.sandbox-hash-base ]; then
109+
cd ~/openclaw
110+
cat Dockerfile.sandbox scripts/sandbox-setup.sh 2>/dev/null | sha256sum | cut -c1-64 > ~/.openclaw/.sandbox-hash-base
111+
cat Dockerfile.sandbox-common scripts/sandbox-common-setup.sh 2>/dev/null | sha256sum | cut -c1-64 > ~/.openclaw/.sandbox-hash-common
112+
cat Dockerfile.sandbox-browser scripts/sandbox-browser-setup.sh 2>/dev/null | sha256sum | cut -c1-64 > ~/.openclaw/.sandbox-hash-browser
113+
rm -f ~/.openclaw/.sandbox-build-hash
114+
fi
115+
' 2>/dev/null || true
116+
117+
# --- Per-image sandbox hash detection ---
118+
BUILD_BASE=false
119+
BUILD_COMMON=false
120+
BUILD_BROWSER=false
121+
122+
if [ "$SANDBOX" = true ]; then
123+
# --sandbox flag: force rebuild all
124+
BUILD_BASE=true; BUILD_COMMON=true; BUILD_BROWSER=true
125+
else
126+
# Single orb round-trip: read 3 old hashes + calculate 3 new hashes
127+
HASH_DATA=$(orb -m "$OPENCLAW_VM_NAME" bash -lc '
128+
cat ~/.openclaw/.sandbox-hash-base 2>/dev/null || echo none
129+
cat ~/.openclaw/.sandbox-hash-common 2>/dev/null || echo none
130+
cat ~/.openclaw/.sandbox-hash-browser 2>/dev/null || echo none
131+
cd ~/openclaw
132+
cat Dockerfile.sandbox scripts/sandbox-setup.sh 2>/dev/null | sha256sum | cut -c1-64
133+
cat Dockerfile.sandbox-common scripts/sandbox-common-setup.sh 2>/dev/null | sha256sum | cut -c1-64
134+
cat Dockerfile.sandbox-browser scripts/sandbox-browser-setup.sh 2>/dev/null | sha256sum | cut -c1-64
135+
')
136+
# Parse 6 lines
137+
OLD_BASE=$(echo "$HASH_DATA" | sed -n '1p')
138+
OLD_COMMON=$(echo "$HASH_DATA" | sed -n '2p')
139+
OLD_BROWSER=$(echo "$HASH_DATA" | sed -n '3p')
140+
NEW_BASE=$(echo "$HASH_DATA" | sed -n '4p')
141+
NEW_COMMON=$(echo "$HASH_DATA" | sed -n '5p')
142+
NEW_BROWSER=$(echo "$HASH_DATA" | sed -n '6p')
143+
144+
[ "$OLD_BASE" != "$NEW_BASE" ] && BUILD_BASE=true && BUILD_COMMON=true # cascade
145+
[ "$OLD_COMMON" != "$NEW_COMMON" ] && BUILD_COMMON=true
146+
[ "$OLD_BROWSER" != "$NEW_BROWSER" ] && BUILD_BROWSER=true
147+
148+
if [ "$BUILD_BASE" = true ] || [ "$BUILD_COMMON" = true ] || [ "$BUILD_BROWSER" = true ]; then
149+
SANDBOX=true
150+
echo "$MSG_CMD_UPDATE_SANDBOX_CHANGED"
151+
fi
112152
fi
113153

114154
if [ "$SANDBOX" = true ]; then
115155
echo "$MSG_CMD_UPDATE_SANDBOX_REBUILD"
116-
SANDBOX_OK=true
117-
echo "$MSG_CMD_UPDATE_SANDBOX_BASE"
118-
echo "$MSG_BUILD_PATIENCE"
119-
start_progress
120-
if ! orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && sg docker -c './scripts/sandbox-setup.sh'" 2>/dev/null; then
121-
SANDBOX_OK=false
122-
fi
123-
stop_progress
124-
echo "$MSG_CMD_UPDATE_SANDBOX_COMMON"
125-
echo "$MSG_BUILD_PATIENCE"
126-
start_progress
127-
if ! orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && sg docker -c './scripts/sandbox-common-setup.sh'" 2>/dev/null; then
128-
echo "$MSG_CMD_UPDATE_SANDBOX_COMMON_FAIL"
129-
SANDBOX_OK=false
156+
157+
# --- Base ---
158+
if [ "$BUILD_BASE" = true ]; then
159+
echo "$MSG_CMD_UPDATE_SANDBOX_BASE"
160+
echo "$MSG_BUILD_PATIENCE"
161+
start_progress
162+
if orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && sg docker -c './scripts/sandbox-setup.sh'" 2>/dev/null; then
163+
stop_progress
164+
save_sandbox_hash base Dockerfile.sandbox scripts/sandbox-setup.sh
165+
else
166+
stop_progress
167+
BUILD_COMMON=false # cascade: skip common if base failed
168+
fi
169+
else
170+
echo "$MSG_CMD_UPDATE_SANDBOX_BASE_SKIP"
130171
fi
131-
stop_progress
132-
echo "$MSG_CMD_UPDATE_SANDBOX_BROWSER"
133-
echo "$MSG_BUILD_PATIENCE"
134-
start_progress
135-
if ! orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && sg docker -c './scripts/sandbox-browser-setup.sh'" 2>/dev/null; then
136-
echo "$MSG_CMD_UPDATE_SANDBOX_BROWSER_FAIL"
137-
SANDBOX_OK=false
172+
173+
# --- Common ---
174+
if [ "$BUILD_COMMON" = true ]; then
175+
[ "$BUILD_BASE" = true ] && [ "$OLD_COMMON" = "$NEW_COMMON" ] && echo "$MSG_CMD_UPDATE_SANDBOX_COMMON_CASCADE"
176+
echo "$MSG_CMD_UPDATE_SANDBOX_COMMON"
177+
echo "$MSG_BUILD_PATIENCE"
178+
start_progress
179+
if orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && sg docker -c './scripts/sandbox-common-setup.sh'" 2>/dev/null; then
180+
stop_progress
181+
save_sandbox_hash common Dockerfile.sandbox-common scripts/sandbox-common-setup.sh
182+
else
183+
stop_progress
184+
echo "$MSG_CMD_UPDATE_SANDBOX_COMMON_FAIL"
185+
fi
186+
else
187+
echo "$MSG_CMD_UPDATE_SANDBOX_COMMON_SKIP"
138188
fi
139-
stop_progress
140-
echo "$MSG_CMD_UPDATE_SANDBOX_NOTE"
141-
# Save new sandbox build hash only if all builds succeeded
142-
if [ "$SANDBOX_OK" = true ]; then
143-
orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && cat Dockerfile.sandbox Dockerfile.sandbox-browser scripts/sandbox-setup.sh scripts/sandbox-common-setup.sh scripts/sandbox-browser-setup.sh 2>/dev/null | sha256sum | cut -d' ' -f1 > ~/.openclaw/.sandbox-build-hash"
189+
190+
# --- Browser (independent) ---
191+
if [ "$BUILD_BROWSER" = true ]; then
192+
echo "$MSG_CMD_UPDATE_SANDBOX_BROWSER"
193+
echo "$MSG_BUILD_PATIENCE"
194+
start_progress
195+
if orb -m "$OPENCLAW_VM_NAME" bash -lc "cd ~/openclaw && sg docker -c './scripts/sandbox-browser-setup.sh'" 2>/dev/null; then
196+
stop_progress
197+
save_sandbox_hash browser Dockerfile.sandbox-browser scripts/sandbox-browser-setup.sh
198+
else
199+
stop_progress
200+
echo "$MSG_CMD_UPDATE_SANDBOX_BROWSER_FAIL"
201+
fi
144202
else
145-
echo "$MSG_CMD_UPDATE_SANDBOX_PARTIAL"
203+
echo "$MSG_CMD_UPDATE_SANDBOX_BROWSER_SKIP"
146204
fi
205+
206+
echo "$MSG_CMD_UPDATE_SANDBOX_NOTE"
207+
# Clean up old monolithic hash file
208+
orb -m "$OPENCLAW_VM_NAME" bash -lc "rm -f ~/.openclaw/.sandbox-build-hash" 2>/dev/null || true
147209
fi
148210

149211
GATEWAY_STOPPED=false

0 commit comments

Comments
 (0)