port pi-devbox v1.1.4–v1.1.6 hardening; bump opencode 1.17.7→1.17.8
Functional (not verbatim) port of the build-provenance, CI-hardening, SSH and shell fixes from the sibling pi-devbox repo, adapted to opencode-devbox's companions and two-variant (base/omos) shape. Defaults unchanged → canonical CI build stays byte-identical apart from the opencode bump and the (cache-free) provenance layer. Fixed: - SSH read-only ~/.ssh ControlPath: setup-lan-access.sh now renders the writable ~/.ssh-local/config sidecar (ControlPath redirect + Include) on EVERY host OS instead of exit 0-ing on native Linux; jump-specific blocks gated behind new NEED_JUMP flag. dssh/dscp + ControlMaster now survive a read-only ~/.ssh on native-Linux hosts. (pi-devbox v1.1.5) - bash history loss in nested/tmux shells: DEVBOX_HIST_SET no longer exported so each shell re-installs its own history -a flush. (pi-devbox v1.1.4) Added: - build provenance: OCI labels + /etc/opencode-devbox/build-manifest.json written from ground truth (opencode --version, installed omos version, /opt/mempalace-toolkit HEAD); wired into build-variant-* and smoke-* jobs; smoke-test.sh asserts manifest + label. (pi-devbox v1.1.6) - scripts/check-base-hash.sh CI guard: fails if a Dockerfile.base ARG *_REF is not folded into the base_tag hash. (pi-devbox v1.1.6) - overridable MEMPALACE_TOOLKIT_REPO build-arg in Dockerfile.base. (v1.1.6) Changed: - resolve-versions: fail-loud validation (SHA / semver) that aborts the release instead of silently falling back to floating main; adds shell: bash (set -o pipefail is illegal under the runner default dash). (pi-devbox v1.1.6) Bumped: - opencode-ai 1.17.7 → 1.17.8 (current npm latest stable). Deferred (needs a decision): opencode.json merge-on-recreate — see CHANGELOG.
This commit is contained in:
Executable
+43
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bash
|
||||
# check-base-hash.sh — guard the base-rebuild invariant.
|
||||
#
|
||||
# Every floating `ARG *_REF` consumed by Dockerfile.base MUST be folded
|
||||
# into the base_tag hash in the docker-publish workflow. Otherwise a
|
||||
# ref-only change to that dependency does not change the base hash, the
|
||||
# Docker Hub probe finds the old base tag, and the base is NOT rebuilt —
|
||||
# the dependency fix silently fails to land. This is the v1.1.2-class
|
||||
# staleness footgun (then it was mempalace-toolkit; this guard stops the
|
||||
# next one before it ships).
|
||||
#
|
||||
# Runs in CI (base-decide job) and locally: bash scripts/check-base-hash.sh
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
WF=".gitea/workflows/docker-publish-split.yml"
|
||||
DF="Dockerfile.base"
|
||||
|
||||
# Extract the hash-compute block: the `HASH=$( … ) | sha256sum | cut`
|
||||
# brace-group in the "Compute base tag" step. This lives in a separate
|
||||
# file from the workflow, so scanning $WF here is free of the self-match
|
||||
# hazard an inline workflow step would have.
|
||||
block=$(awk '/HASH=\$\(/{f=1} f{print} f && /cut -c1-12/{exit}' "$WF")
|
||||
if [ -z "$block" ]; then
|
||||
echo "::error::could not locate the HASH=\$( … ) | sha256sum block in $WF"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
refs=$(grep -oE '^ARG [A-Z0-9_]+_REF' "$DF" | awk '{print $2}' | sort -u)
|
||||
fail=0
|
||||
for r in $refs; do
|
||||
lc=$(printf '%s' "$r" | tr '[:upper:]' '[:lower:]')
|
||||
if ! printf '%s' "$block" | grep -q "outputs.$lc"; then
|
||||
echo "::error::Dockerfile.base declares '$r' but it is NOT folded into the base_tag hash in $WF."
|
||||
echo "::error::Add echo \"\${{ needs.resolve-versions.outputs.$lc }}\" inside the HASH=\$( … ) | sha256sum block, or a $r-only change will silently fail to rebuild the base."
|
||||
fail=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$fail" = 0 ]; then
|
||||
echo "OK: all Dockerfile.base *_REF args are folded into base_tag (${refs:-none})."
|
||||
fi
|
||||
exit $fail
|
||||
@@ -197,6 +197,34 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "-- Build provenance (manifest + OCI labels) --"
|
||||
run "/etc/opencode-devbox/build-manifest.json present" \
|
||||
"test -f /etc/opencode-devbox/build-manifest.json"
|
||||
run_expect "manifest records opencode component" \
|
||||
"cat /etc/opencode-devbox/build-manifest.json" '"opencode"'
|
||||
run_expect "manifest records opencode_version" \
|
||||
"cat /etc/opencode-devbox/build-manifest.json" '"opencode_version"'
|
||||
run_expect "manifest records mempalace-toolkit component" \
|
||||
"cat /etc/opencode-devbox/build-manifest.json" '"mempalace-toolkit"'
|
||||
# Every resolved component must be a real value, never the 'unknown'
|
||||
# sentinel that rev()/version lookups emit on failure. (oh-my-opencode-slim
|
||||
# is JSON null in the base variant — that is expected, not 'unknown'.)
|
||||
run "manifest has no unresolved ('unknown') components" \
|
||||
"! grep -q '\"unknown\"' /etc/opencode-devbox/build-manifest.json"
|
||||
if [ "$VARIANT" = "omos" ]; then
|
||||
run "manifest omos component is resolved (not null) in omos variant" \
|
||||
"! grep -q '\"oh-my-opencode-slim\": null' /etc/opencode-devbox/build-manifest.json"
|
||||
fi
|
||||
# OCI labels live in the image config, not the container fs — inspect them
|
||||
# from the host docker rather than via `docker run`.
|
||||
LBL=$(docker inspect --format '{{ index .Config.Labels "se.jordbo.opencode-devbox.opencode-version" }}' "$IMAGE" 2>/dev/null || true)
|
||||
if [ -n "$LBL" ] && [ "$LBL" != "<no value>" ]; then
|
||||
pass "OCI label se.jordbo.opencode-devbox.opencode-version=$LBL"
|
||||
else
|
||||
fail "OCI label se.jordbo.opencode-devbox.opencode-version missing or empty"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "-- Entrypoint behaviour --"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user