Sync upstream and build images / sync-and-build (push) Successful in 2m4s
Operating model change, at the operator's request: the deployment follows the newest release candidate rather than a hand-pinned version. - :latest is now published, as a manifest copy (identical digest) of the newest build of the newest RC version. It is the ONLY tag that moves; every <version>[-rN] tag stays immutable for anyone who wants to pin. - Freshness (pnpm / base image / recipe hash) now applies to the current version derived from the registry, not to a Dockerfile constant, so an image fix reaches the deployed line automatically. The `revise` dispatch input rebuilds any older versions with the current recipe on demand. - Smoke test now runs on a fresh named volume (root-owned, like a new Unraid appdata dir) and asserts pid 1 is uid 1000 - the ownership fix is exercised on every build, not just locally. - Releases: `latest` gets no release; the "pinned deployment" callout is gone (the README and the alias are the source of truth now). - 0.1.1-rc.2 is deprecated; its -r2/-r49/-r52 revisions were removed (images, tags, releases). The original tag remains as history. - README/template: :latest in the Repository field, auto-update warning, versions table and upgrade procedure rewritten for the new model. Forensic workflow's trusted default -> :latest. inspect-deployment default container name -> Deepseek. Co-Authored-By: Claude Fable 5 <[email protected]>
101 lines
5.1 KiB
YAML
101 lines
5.1 KiB
YAML
name: Validate suspect image
|
|
|
|
# Manual-only forensic comparison of a third-party deepseek-harness image
|
|
# already present on the runner host's docker daemon against the trusted image
|
|
# built by this repository. The suspect image is NEVER executed: `docker
|
|
# create` only materializes a container's filesystem, and every inspection
|
|
# happens on exported tar content.
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
suspect:
|
|
description: Suspect image reference (must already be present locally)
|
|
default: runzhliu/deepseek-harness:0.1.1-rc.2
|
|
trusted:
|
|
description: Trusted image reference
|
|
default: gitea.milesward.dev/mward4/deepseek-harness:latest
|
|
|
|
jobs:
|
|
validate:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Locate suspect image (never pulled, never run)
|
|
run: |
|
|
set -eu
|
|
SUSPECT="${{ inputs.suspect || 'runzhliu/deepseek-harness:0.1.1-rc.2' }}"
|
|
if ! docker image inspect "$SUSPECT" > /tmp/suspect-inspect.json 2>/dev/null; then
|
|
echo "::error::suspect image $SUSPECT is not present on this daemon"
|
|
docker images | grep -i deepseek || true
|
|
exit 1
|
|
fi
|
|
echo "== suspect config (entrypoint/cmd/env/user) =="
|
|
docker image inspect --format \
|
|
'Entrypoint={{json .Config.Entrypoint}} Cmd={{json .Config.Cmd}} User={{json .Config.User}} Env={{json .Config.Env}} Labels={{json .Config.Labels}}' \
|
|
"$SUSPECT"
|
|
echo "== suspect digests =="
|
|
docker image inspect --format '{{json .RepoDigests}} id={{.Id}}' "$SUSPECT"
|
|
echo "== containers using the suspect image on this host =="
|
|
docker ps -a --filter "ancestor=$SUSPECT" --format '{{.ID}} {{.Names}} {{.Status}} {{.Ports}}' || true
|
|
|
|
- name: Export both filesystems
|
|
run: |
|
|
set -eu
|
|
SUSPECT="${{ inputs.suspect || 'runzhliu/deepseek-harness:0.1.1-rc.2' }}"
|
|
TRUSTED="${{ inputs.trusted || 'gitea.milesward.dev/mward4/deepseek-harness:latest' }}"
|
|
docker pull -q "$TRUSTED"
|
|
mkdir -p /tmp/suspect /tmp/trusted
|
|
s=$(docker create "$SUSPECT")
|
|
t=$(docker create "$TRUSTED")
|
|
docker export "$s" | tar -x -C /tmp/suspect
|
|
docker export "$t" | tar -x -C /tmp/trusted
|
|
docker rm "$s" "$t" > /dev/null
|
|
|
|
- name: Compare installed dsh package against trusted build
|
|
run: |
|
|
set -eu
|
|
echo "== dsh install locations in suspect =="
|
|
find /tmp/suspect -maxdepth 6 -type d -name dsh -path '*@deepseek-ai*' | tee /tmp/suspect-dsh-dirs
|
|
SDIR=$(head -1 /tmp/suspect-dsh-dirs || true)
|
|
TDIR=/tmp/trusted/usr/local/lib/node_modules/@deepseek-ai/dsh
|
|
if [ -z "${SDIR}" ]; then
|
|
echo "::warning::no @deepseek-ai/dsh install found in suspect image"
|
|
else
|
|
echo "== package.json versions =="
|
|
grep -E '"(name|version)"' "$SDIR/package.json" "$TDIR/package.json" | head -8
|
|
echo "== dsh's OWN code (node_modules excluded) =="
|
|
if diff -r --exclude=node_modules "$SDIR" "$TDIR" > /tmp/dsh-own-diff.txt 2>&1; then
|
|
echo "IDENTICAL: suspect's dsh code matches the official npm release byte-for-byte"
|
|
else
|
|
echo "DSH CODE DIFFERENCES FOUND:"
|
|
cat /tmp/dsh-own-diff.txt
|
|
fi
|
|
echo "== dependency tree (node_modules) summary =="
|
|
if diff -r "$SDIR/node_modules" "$TDIR/node_modules" > /tmp/dsh-dep-diff.txt 2>&1; then
|
|
echo "dependencies identical"
|
|
else
|
|
echo "$(grep -c '^diff -r\|^Only in' /tmp/dsh-dep-diff.txt) differing/unique dependency files"
|
|
echo "-- packages with version changes --"
|
|
grep -A0 'package.json$' /tmp/dsh-dep-diff.txt | sed 's|.*node_modules/||; s|/package.json.*||' | sort -u | head -30
|
|
fi
|
|
fi
|
|
|
|
- name: Scan suspect for tampering red flags
|
|
run: |
|
|
set -eu
|
|
cd /tmp/suspect
|
|
echo "== world-reachable startup hooks =="
|
|
ls -la etc/cron* etc/init.d 2>/dev/null || true
|
|
find . -maxdepth 3 -name "*.sh" -newer usr/local 2>/dev/null | head || true
|
|
echo "== 0.0.0.0 safety check still present? =="
|
|
grep -rl "intentionally not supported yet for safety" \
|
|
usr/local/lib/node_modules 2>/dev/null \
|
|
&& echo "OK: upstream 0.0.0.0 refusal intact" \
|
|
|| echo "SUSPICIOUS: upstream 0.0.0.0 safety refusal NOT found (patched out?)"
|
|
echo "== network callouts baked into image config =="
|
|
grep -rEo "https?://[a-zA-Z0-9./_-]+" usr/local/lib/node_modules/@deepseek-ai/dsh/package.json 2>/dev/null | sort -u | head
|
|
echo "== extra npm packages not in trusted image =="
|
|
(cd /tmp/suspect && find usr -maxdepth 5 -type d -path '*node_modules/*' ! -path '*node_modules/*/node_modules*' 2>/dev/null | sort) > /tmp/s.pkgs || true
|
|
(cd /tmp/trusted && find usr -maxdepth 5 -type d -path '*node_modules/*' ! -path '*node_modules/*/node_modules*' 2>/dev/null | sort) > /tmp/t.pkgs || true
|
|
diff /tmp/s.pkgs /tmp/t.pkgs | head -40 || true
|