Skip to content

Commit d1fc501

Browse files
committed
fix(sandbox): correct image digest comparison and variable ordering
The remote digest check used --format "{{.Manifest.Digest}}" which silently falls back to pretty-printed output for multi-arch OCI image indexes, causing the pull to always re-trigger. Hash the raw manifest bytes with sha256sum to match how registries compute digests. Also guard local digest retrieval with "|| true" so set -e / pipefail does not kill the script when the image is not yet cached locally, and hoist the WORKSPACE_NAME derivation above the volume flags block where it is first referenced.
1 parent a9129d2 commit d1fc501

1 file changed

Lines changed: 19 additions & 8 deletions

File tree

bin/opencode-sandbox

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,12 @@ build_image() {
155155
pull_image() {
156156
local remote_digest local_digest
157157

158-
remote_digest="$(docker buildx imagetools inspect "$GHCR_IMAGE" \
159-
--format '{{.Manifest.Digest}}' 2>/dev/null)"
158+
# Compute the remote manifest digest. For multi-arch OCI image indexes the
159+
# --format '{{.Manifest.Digest}}' template silently falls back to the full
160+
# pretty-printed output, so we hash the raw manifest bytes ourselves — this
161+
# is exactly how registries compute digests per the OCI spec.
162+
remote_digest="$(docker buildx imagetools inspect "$GHCR_IMAGE" --raw 2>/dev/null \
163+
| sha256sum | awk '{print "sha256:"$1}')"
160164

161165
if [[ -z "$remote_digest" ]]; then
162166
# Registry unreachable — fall back to local if it exists, else let
@@ -170,8 +174,11 @@ pull_image() {
170174
return
171175
fi
172176

177+
# Retrieve the local image digest. The `|| true` guard prevents `set -e`
178+
# from killing the script when the image is not cached locally (docker
179+
# image inspect exits non-zero and pipefail propagates the failure).
173180
local_digest="$(docker image inspect "$GHCR_IMAGE" \
174-
--format '{{index .RepoDigests 0}}' 2>/dev/null | cut -d@ -f2)"
181+
--format '{{index .RepoDigests 0}}' 2>/dev/null | cut -d@ -f2 || true)"
175182

176183
if [[ -n "$local_digest" && "$local_digest" == "$remote_digest" ]]; then
177184
info "Already up to date (${remote_digest})"
@@ -269,6 +276,15 @@ for ref in "${REF_DIRS[@]+"${REF_DIRS[@]}"}"; do
269276
VOLUME_FLAGS+=(-v "${ref_abs}:/reference/${ref_name}:ro")
270277
done
271278

279+
# ---------------------------------------------------------------------------
280+
# Derive workspace name (used for both volume naming and container naming)
281+
# ---------------------------------------------------------------------------
282+
283+
# Sanitize to Docker's allowed charset: [a-zA-Z0-9_.-], must start alphanum.
284+
# Strip trailing dashes produced by tr replacing the trailing newline, and
285+
# avoid doubling the prefix when the workspace folder is named identically.
286+
WORKSPACE_NAME="$(basename "$WORKSPACE" | tr -c 'a-zA-Z0-9_.-' '-' | sed 's/^[^a-zA-Z0-9]/x/; s/-*$//')"
287+
272288
# Persistent state volume (theme, model selection, prompt history)
273289
VOLUME_FLAGS+=(-v "opencode-state:/home/opencode/.local/state/opencode")
274290

@@ -280,12 +296,7 @@ VOLUME_FLAGS+=(-v "opencode-data-${WORKSPACE_NAME}:/home/opencode/.local/share/o
280296
# Run
281297
# ---------------------------------------------------------------------------
282298

283-
# Use the workspace directory name as part of the container name for clarity.
284-
# Sanitize to Docker's allowed charset: [a-zA-Z0-9_.-], must start alphanum.
285-
# Strip trailing dashes produced by tr replacing the trailing newline, and
286-
# avoid doubling the prefix when the workspace folder is named identically.
287299
# Append the shell PID to guarantee uniqueness across concurrent invocations.
288-
WORKSPACE_NAME="$(basename "$WORKSPACE" | tr -c 'a-zA-Z0-9_.-' '-' | sed 's/^[^a-zA-Z0-9]/x/; s/-*$//')"
289300
if [[ -z "$WORKSPACE_NAME" || "$WORKSPACE_NAME" == "$CONTAINER_PREFIX" ]]; then
290301
CONTAINER_NAME="${CONTAINER_PREFIX}-$$"
291302
else

0 commit comments

Comments
 (0)