Files
.pouch/skills/builder/scripts/verify_deb.sh
T
ace 47bd454fa3 feat(builder): merge deb-publisher + publish-docker-image into contract-driven builder skill
- skills/builder: SKILL.md, README.md, references/contract.md (make/publish
  contract v1), references/registry.md
- scripts/check.py: executable contract checker (make dry-run probes, secret
  scan, push thin-wrapper and script path checks; --build verifies real .deb)
- scripts/upload_deb.sh: migrated from deb-publisher, adds project .env
  auto-load and dirty-worktree publish gate
- scripts/publish_docker.sh: migrated from publish-docker-image publish.sh,
  now env-first (DOCKER_REGISTRY/REPOSITORY/IMAGE_TAG/PLATFORMS), refuses
  floating latest and multi-platform --load
- scripts/verify_deb.sh: metadata/content/sha256 verification with v-prefix
  normalization
- orc: deb+docker stages both route to $builder; routing table, DAGs,
  README, config untouched stage names; tests updated
- ack delivery.md + skiff source-model.md: reference builder
- remove skills/deb-publisher and skills/publish-docker-image
2026-08-24 12:52:53 +08:00

112 lines
3.0 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
Usage:
verify_deb.sh FILE.deb [EXPECTED_VERSION] [EXPECTED_ARCH]
Prints package metadata, key content listing, and SHA-256. When an expected
version and/or architecture is given, mismatches fail with a non-zero exit.
EOF
}
if [[ $# -lt 1 || $# -gt 3 ]]; then
usage >&2
exit 2
fi
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
usage
exit 0
fi
package=$1
expected_version=${2:-}
expected_arch=${3:-}
fail=0
if [[ ! -f "$package" ]]; then
echo "Error: file not found: $package" >&2
exit 2
fi
if [[ ! -s "$package" ]]; then
echo "Error: empty file: $package" >&2
exit 2
fi
if ! command -v dpkg-deb >/dev/null 2>&1; then
echo "Error: dpkg-deb is required." >&2
exit 2
fi
echo "== metadata =="
info=$(dpkg-deb --info "$package") || {
echo "Error: dpkg-deb --info failed; not a valid Debian package." >&2
exit 1
}
printf '%s\n' "$info"
package_name=$(dpkg-deb --field "$package" Package 2>/dev/null || true)
package_version=$(dpkg-deb --field "$package" Version 2>/dev/null || true)
package_arch=$(dpkg-deb --field "$package" Architecture 2>/dev/null || true)
# Debian versions never start with 'v'; git tags usually do. Compare normalized.
expected_version=${expected_version#v}
if [[ -z "$package_name" || -z "$package_version" || -z "$package_arch" ]]; then
echo "FAIL: missing Package/Version/Architecture field." >&2
fail=1
fi
if [[ -n "$expected_version" && "$package_version" != "$expected_version" ]]; then
echo "FAIL: version mismatch: expected $expected_version, got $package_version" >&2
fail=1
fi
if [[ -n "$expected_arch" && "$package_arch" != "$expected_arch" ]]; then
echo "FAIL: architecture mismatch: expected $expected_arch, got $package_arch" >&2
fail=1
fi
# Filename shape per contract: <name>_<version>_<arch>.deb
base=$(basename -- "$package")
if [[ ! "$base" =~ ^[^_]+_[^_]+_[^_]+\.deb$ ]]; then
echo "FAIL: filename does not match <name>_<version>_<arch>.deb: $base" >&2
fail=1
elif [[ -n "$package_version" && ! "$base" == *"${package_version}"* ]]; then
echo "FAIL: filename version does not match package Version ($package_version): $base" >&2
fail=1
fi
echo "== contents (top level + binaries) =="
dpkg-deb --contents "$package" | sed -n '1,40p'
echo "== maintainer scripts permissions (when present) =="
control_dir=$(mktemp -d)
trap 'rm -rf -- "$control_dir"' EXIT
if dpkg-deb --control "$package" "$control_dir" 2>/dev/null; then
found_scripts=false
for script in preinst postinst prerm postrm; do
if [[ -f "$control_dir/$script" ]]; then
found_scripts=true
mode=$(stat -c '%a' "$control_dir/$script")
if [[ $mode =~ .*[2367]$ ]]; then
echo "OK: $script mode $mode"
else
echo "FAIL: $script not executable (mode $mode)" >&2
fail=1
fi
fi
done
if [[ "$found_scripts" == false ]]; then
echo "(no maintainer scripts)"
fi
fi
echo "== sha256 =="
sha256sum "$package"
if ((fail > 0)); then
echo "VERIFY: FAILED" >&2
exit 1
fi
echo "VERIFY: OK"