#!/usr/bin/env bashset -euo pipefail ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)VERSION=${1:-}OUT_DIR=${2:-"$ROOT/dist"}REQUESTED_ARCH=${3:-}IDENTIFIER=org.openclaw.gitcrawlEXPECTED_AUTHORITY='Developer ID Application: OpenClaw Foundation (FWJYW4S8P8)'EXPECTED_TEAM_ID=FWJYW4S8P8REQUIREMENT="identifier \"$IDENTIFIER\" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists and certificate leaf[subject.OU] = \"$EXPECTED_TEAM_ID\"" if [[ ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]] || [[ -n "$REQUESTED_ARCH" && "$REQUESTED_ARCH" != amd64 && "$REQUESTED_ARCH" != arm64 ]]; then echo "usage: $0 vX.Y.Z [artifact-directory] [amd64|arm64]" >&2 exit 2fi[[ "$(uname -s)" == Darwin ]] || { echo "macOS release verification must run on macOS" >&2 exit 1} checksums="$OUT_DIR/checksums.txt"[[ -f "$checksums" ]] || { echo "missing checksums: $checksums" >&2 exit 1} WORK_DIR=$(mktemp -d "${TMPDIR:-/tmp}/gitcrawl-release-verify.XXXXXX")trap 'rm -rf "$WORK_DIR"' EXITrelease_version=${VERSION#v}architectures=(amd64 arm64)[[ -z "$REQUESTED_ARCH" ]] || architectures=("$REQUESTED_ARCH") for goarch in "${architectures[@]}"; do archive_name="gitcrawl_${release_version}_darwin_${goarch}.tar.gz" archive="$OUT_DIR/$archive_name" [[ -f "$archive" ]] || { echo "missing release archive: $archive" >&2 exit 1 } checksum_record=$(awk -v name="$archive_name" '$2 == name { print }' "$checksums") [[ "$(printf '%s\n' "$checksum_record" | awk 'NF { count++ } END { print count+0 }')" == 1 ]] || { echo "missing or duplicate checksum record: $archive_name" >&2 exit 1 } read -r expected_hash expected_name extra <<<"$checksum_record" [[ "$expected_hash" =~ ^[[:xdigit:]]{64}$ && "$expected_name" == "$archive_name" && -z "${extra:-}" ]] || { echo "invalid checksum record: $archive_name" >&2 exit 1 } actual_hash=$(shasum -a 256 "$archive" | awk '{print $1}') [[ "$actual_hash" == "$expected_hash" ]] || { echo "checksum mismatch: $archive" >&2 exit 1 } expected_listing=$'CHANGELOG.md\nLICENSE\nREADME.md\ngitcrawl' actual_listing=$(tar -tzf "$archive" | sed -E 's#^\./##' | sed '/^$/d' | LC_ALL=C sort) [[ "$actual_listing" == "$expected_listing" ]] || { echo "unexpected archive contents: $archive" >&2 exit 1 } stage="$WORK_DIR/$goarch" mkdir -p "$stage" tar -xzf "$archive" -C "$stage" binary="$stage/gitcrawl" [[ -x "$binary" ]] || { echo "missing executable in archive: $archive" >&2 exit 1 } codesign --verify --strict -R="$REQUIREMENT" --verbose=2 "$binary" codesign --verify --strict --check-notarization -R=notarized "$binary" signature=$(codesign -dvvv "$binary" 2>&1) grep -Fx "Identifier=$IDENTIFIER" <<<"$signature" >/dev/null grep -Fx "TeamIdentifier=$EXPECTED_TEAM_ID" <<<"$signature" >/dev/null grep -Fx "Authority=$EXPECTED_AUTHORITY" <<<"$signature" >/dev/null expected_arch=$goarch [[ "$goarch" == amd64 ]] && expected_arch=x86_64 lipo -archs "$binary" | tr ' ' '\n' | grep -Fx "$expected_arch" >/dev/null [[ "$("$binary" --version)" == "$release_version" ]]done
#!/usr/bin/env bash
set -euo pipefail
ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
VERSION=${1:-}
OUT_DIR=${2:-"$ROOT/dist"}
REQUESTED_ARCH=${3:-}
IDENTIFIER=org.openclaw.gitcrawl
EXPECTED_AUTHORITY='Developer ID Application: OpenClaw Foundation (FWJYW4S8P8)'
EXPECTED_TEAM_ID=FWJYW4S8P8
REQUIREMENT="identifier \"$IDENTIFIER\" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists and certificate leaf[subject.OU] = \"$EXPECTED_TEAM_ID\""
if [[ ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]] ||
[[ -n "$REQUESTED_ARCH" && "$REQUESTED_ARCH" != amd64 && "$REQUESTED_ARCH" != arm64 ]]; then
echo "usage: $0 vX.Y.Z [artifact-directory] [amd64|arm64]" >&2
exit 2
fi
[[ "$(uname -s)" == Darwin ]] || {
echo "macOS release verification must run on macOS" >&2
exit 1
}
checksums="$OUT_DIR/checksums.txt"
[[ -f "$checksums" ]] || {
echo "missing checksums: $checksums" >&2
exit 1
}
WORK_DIR=$(mktemp -d "${TMPDIR:-/tmp}/gitcrawl-release-verify.XXXXXX")
trap 'rm -rf "$WORK_DIR"' EXIT
release_version=${VERSION#v}
architectures=(amd64 arm64)
[[ -z "$REQUESTED_ARCH" ]] || architectures=("$REQUESTED_ARCH")
for goarch in "${architectures[@]}"; do
archive_name="gitcrawl_${release_version}_darwin_${goarch}.tar.gz"
archive="$OUT_DIR/$archive_name"
[[ -f "$archive" ]] || {
echo "missing release archive: $archive" >&2
exit 1
}
checksum_record=$(awk -v name="$archive_name" '$2 == name { print }' "$checksums")
[[ "$(printf '%s\n' "$checksum_record" | awk 'NF { count++ } END { print count+0 }')" == 1 ]] || {
echo "missing or duplicate checksum record: $archive_name" >&2
exit 1
}
read -r expected_hash expected_name extra <<<"$checksum_record"
[[ "$expected_hash" =~ ^[[:xdigit:]]{64}$ && "$expected_name" == "$archive_name" && -z "${extra:-}" ]] || {
echo "invalid checksum record: $archive_name" >&2
exit 1
}
actual_hash=$(shasum -a 256 "$archive" | awk '{print $1}')
[[ "$actual_hash" == "$expected_hash" ]] || {
echo "checksum mismatch: $archive" >&2
exit 1
}
expected_listing=$'CHANGELOG.md\nLICENSE\nREADME.md\ngitcrawl'
actual_listing=$(tar -tzf "$archive" | sed -E 's#^\./##' | sed '/^$/d' | LC_ALL=C sort)
[[ "$actual_listing" == "$expected_listing" ]] || {
echo "unexpected archive contents: $archive" >&2
exit 1
}
stage="$WORK_DIR/$goarch"
mkdir -p "$stage"
tar -xzf "$archive" -C "$stage"
binary="$stage/gitcrawl"
[[ -x "$binary" ]] || {
echo "missing executable in archive: $archive" >&2
exit 1
}
codesign --verify --strict -R="$REQUIREMENT" --verbose=2 "$binary"
codesign --verify --strict --check-notarization -R=notarized "$binary"
signature=$(codesign -dvvv "$binary" 2>&1)
grep -Fx "Identifier=$IDENTIFIER" <<<"$signature" >/dev/null
grep -Fx "TeamIdentifier=$EXPECTED_TEAM_ID" <<<"$signature" >/dev/null
grep -Fx "Authority=$EXPECTED_AUTHORITY" <<<"$signature" >/dev/null
expected_arch=$goarch
[[ "$goarch" == amd64 ]] && expected_arch=x86_64
lipo -archs "$binary" | tr ' ' '\n' | grep -Fx "$expected_arch" >/dev/null
[[ "$("$binary" --version)" == "$release_version" ]]
done