Files
qiming/qimingclaw/scripts/sign-macos-resource-bins.sh

118 lines
4.3 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
#
# sign-macos-resource-bins.sh — 在 macOS 上对即将被打进 App 的第三方二进制做 codesign
#
# 背景:
# Electron 打包时会把 resources 中的文件拷贝到 .app/Contents/Resources/
# 但不会对这些可执行文件做签名。Apple 公证要求包内所有可执行文件必须:
# - 使用有效的 Developer ID 证书签名
# - 包含安全时间戳 (--timestamp)
# - 启用硬化运行时 (--options runtime)
# 因此需在 electron-builder 打包之前,对 resources 下的 node 与 uv/uvx
# 预先签名这样打进包后即可通过公证。node 与 uv 均不省略,一并签名。)
#
# 用法:
# 在项目根目录执行: ./scripts/sign-macos-resource-bins.sh
# 需设置环境变量 APPLE_SIGNING_IDENTITY例如:
# export APPLE_SIGNING_IDENTITY="Developer ID Application: Your Name (TEAM_ID)"
# make electron-bundle
#
# 仅在 macOS 上执行;非 macOS 或未设置 APPLE_SIGNING_IDENTITY 时直接退出 0。
#
set -euo pipefail
# 仅 macOS 需要此步骤
if [ "$(uname -s)" != "Darwin" ]; then
exit 0
fi
# 明确说明本步骤会对哪些资源签名
echo "==> [sign-macos-resource-bins] 将对 node、uv/uvx 做 codesign供 macOS 公证)"
# 未配置签名身份时跳过(例如 CI 未配置或非发布构建)
if [ -z "${APPLE_SIGNING_IDENTITY:-}" ]; then
echo "==> [sign-macos-resource-bins] 未设置 APPLE_SIGNING_IDENTITY跳过对 node/uv 的签名"
exit 0
fi
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
ELECTRON_RESOURCES="${PROJECT_ROOT}/crates/agent-electron-client/resources"
# node-runtime 为 V8/Node需 JIT 权限,否则 macOS 上会 SIGTRAP
NODE_RUNTIME_ENTITLEMENTS="${ELECTRON_RESOURCES}/node.entitlements"
# 使用一致的 identity 对单个二进制签名Developer ID + 时间戳 + 硬化运行时
sign_one() {
local bin_path="$1"
if [ ! -f "$bin_path" ]; then
return 0
fi
# 若已是同 identity 签名则可能跳过;--force 确保使用当前 identity 重签
codesign --force --timestamp --options runtime -s "${APPLE_SIGNING_IDENTITY}" -- "$bin_path"
echo " signed: $bin_path"
}
# 对 node-runtime 使用带 JIT entitlement 的签名(仅 macOS Mach-O
sign_node_runtime_with_jit() {
local bin_path="$1"
if [ ! -f "$bin_path" ]; then
return 0
fi
if ! file "$bin_path" | grep -q "Mach-O"; then
return 0
fi
codesign --force --timestamp --options runtime \
--entitlements "${NODE_RUNTIME_ENTITLEMENTS}" \
-s "${APPLE_SIGNING_IDENTITY}" -- "$bin_path"
echo " signed (with JIT entitlement): $bin_path"
}
echo "==> [sign-macos-resource-bins] 使用 identity: ${APPLE_SIGNING_IDENTITY}"
# 1. 签名 resources/uv/bin 下的 uv、uvx公证报错即为此二者
UV_BIN_DIR="${ELECTRON_RESOURCES}/uv/bin"
if [ -d "${UV_BIN_DIR}" ]; then
echo "==> [sign-macos-resource-bins] 签名 uv 资源 (uv, uvx)..."
for name in uv uvx; do
[ -f "${UV_BIN_DIR}/${name}" ] && sign_one "${UV_BIN_DIR}/${name}"
done
else
echo "==> [sign-macos-resource-bins] 未找到 ${UV_BIN_DIR},跳过 uv 签名"
fi
# 2. 签名 resources/node/bin 下的可执行文件
# 注意node 是 V8/Node.js 运行时,需要 JIT 权限
NODE_BIN_DIR="${ELECTRON_RESOURCES}/node/bin"
if [ -d "${NODE_BIN_DIR}" ]; then
echo "==> [sign-macos-resource-bins] 签名 node 资源 (带 JIT entitlement)..."
for f in "${NODE_BIN_DIR}"/*; do
if [ -f "$f" ] && [ -x "$f" ]; then
# 排除脚本或非 Mach-O如 .sh仅签名可执行二进制
if file "$f" | grep -q "Mach-O"; then
# node 是 V8 运行时,需要 JIT 权限
sign_node_runtime_with_jit "$f"
fi
fi
done
else
echo "==> [sign-macos-resource-bins] 未找到 ${NODE_BIN_DIR},跳过 node 签名"
fi
# 3. 签名 resources/lanproxy/bin 下的 lanproxy
LANPROXY_BIN_DIR="${ELECTRON_RESOURCES}/lanproxy/bin"
if [ -d "${LANPROXY_BIN_DIR}" ]; then
echo "==> [sign-macos-resource-bins] 签名 lanproxy 资源..."
for f in "${LANPROXY_BIN_DIR}"/*; do
if [ -f "$f" ] && [ -x "$f" ]; then
if file "$f" | grep -q "Mach-O"; then
sign_one "$f"
fi
fi
done
else
echo "==> [sign-macos-resource-bins] 未找到 ${LANPROXY_BIN_DIR},跳过 lanproxy 签名"
fi
echo "==> [sign-macos-resource-bins] node / uv / lanproxy 资源签名完成"