|
|
#!/usr/bin/env bash
|
|
|
# 为构建出的 deb 注入 postinst:安装时自动写入 apt 源与公钥。
|
|
|
set -euo pipefail
|
|
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
|
|
DIST_ROOT="${DEB_DIST_ROOT:-$REPO_ROOT/dist/linux-deb}"
|
|
|
APT_SOURCE_URL="${APT_SOURCE_URL:-http://80.12.140.29:80/apt}"
|
|
|
APT_SOURCE_SUITE="${APT_SOURCE_SUITE:-v10}"
|
|
|
APT_SOURCE_COMPONENT="${APT_SOURCE_COMPONENT:-main}"
|
|
|
APT_SOURCE_LIST_FILE="${APT_SOURCE_LIST_FILE:-/etc/apt/sources.list.d/zyyun.list}"
|
|
|
APT_KEYRING_PATH="${APT_KEYRING_PATH:-/usr/share/keyrings/zyyun-archive-keyring.gpg}"
|
|
|
APT_BOOTSTRAP_KEY_IN_PKG="${APT_BOOTSTRAP_KEY_IN_PKG:-/usr/share/zyyun/bootstrap/zyyun-archive-keyring.gpg}"
|
|
|
GPG_KEY_ID="${APT_GPG_KEY_ID:-com.jgzy.product}"
|
|
|
AUTO_CREATE_GPG_KEY="${APT_GPG_AUTO_CREATE:-1}"
|
|
|
|
|
|
usage() {
|
|
|
cat <<EOF
|
|
|
用法:
|
|
|
$(basename "$0") [项目名...]
|
|
|
|
|
|
环境变量:
|
|
|
DEB_DIST_ROOT deb 目录(默认: dist/linux-deb)
|
|
|
APT_GPG_KEY_ID 签名 Key(默认: com.jgzy.product)
|
|
|
APT_GPG_AUTO_CREATE 1/0,缺失签名密钥时自动创建(默认: 1)
|
|
|
APT_SOURCE_URL 更新源地址(默认: http://80.12.140.29:80/apt)
|
|
|
APT_SOURCE_SUITE 默认: v10
|
|
|
APT_SOURCE_COMPONENT 默认: main
|
|
|
EOF
|
|
|
}
|
|
|
|
|
|
if (($# > 0)); then
|
|
|
case "$1" in
|
|
|
--help|-h)
|
|
|
usage
|
|
|
exit 0
|
|
|
;;
|
|
|
esac
|
|
|
fi
|
|
|
|
|
|
if [[ ! -d "$DIST_ROOT" ]]; then
|
|
|
echo "错误: deb 产物目录不存在: $DIST_ROOT" >&2
|
|
|
exit 1
|
|
|
fi
|
|
|
|
|
|
if ! command -v gpg >/dev/null 2>&1; then
|
|
|
echo "错误: 未安装 gpg(注入公钥需要)" >&2
|
|
|
exit 1
|
|
|
fi
|
|
|
|
|
|
if ! command -v dpkg-deb >/dev/null 2>&1; then
|
|
|
echo "错误: 未安装 dpkg-deb(deb 重新打包需要)" >&2
|
|
|
exit 1
|
|
|
fi
|
|
|
|
|
|
ensure_signing_key() {
|
|
|
local key="$1"
|
|
|
local quick_gen_cmd=(
|
|
|
gpg --batch --pinentry-mode loopback --passphrase ""
|
|
|
--quick-gen-key "$key" rsa4096 sign 5y
|
|
|
)
|
|
|
|
|
|
if gpg --list-secret-keys "$key" >/dev/null 2>&1; then
|
|
|
return 0
|
|
|
fi
|
|
|
|
|
|
if [[ "$AUTO_CREATE_GPG_KEY" != "1" ]]; then
|
|
|
echo "错误: 未找到签名私钥: $key" >&2
|
|
|
echo "请先执行以下命令创建密钥,或设置 APT_GPG_AUTO_CREATE=1 自动创建:" >&2
|
|
|
echo " ${quick_gen_cmd[*]}" >&2
|
|
|
exit 1
|
|
|
fi
|
|
|
|
|
|
echo "==> gpg key not found, generating: $key"
|
|
|
"${quick_gen_cmd[@]}"
|
|
|
}
|
|
|
|
|
|
PROJECTS=()
|
|
|
if ((${#@} > 0)); then
|
|
|
PROJECTS=("$@")
|
|
|
else
|
|
|
shopt -s nullglob
|
|
|
for p in "$DIST_ROOT"/*; do
|
|
|
[[ -d "$p" ]] || continue
|
|
|
PROJECTS+=( "$(basename "$p")" )
|
|
|
done
|
|
|
shopt -u nullglob
|
|
|
fi
|
|
|
|
|
|
if ((${#PROJECTS[@]} == 0)); then
|
|
|
echo "错误: 未发现可注入项目($DIST_ROOT 为空)" >&2
|
|
|
exit 1
|
|
|
fi
|
|
|
|
|
|
ensure_signing_key "$GPG_KEY_ID"
|
|
|
|
|
|
tmp_key="$(mktemp)"
|
|
|
cleanup() {
|
|
|
rm -f "$tmp_key"
|
|
|
}
|
|
|
trap cleanup EXIT
|
|
|
|
|
|
gpg --export "$GPG_KEY_ID" > "$tmp_key"
|
|
|
|
|
|
inject_one_deb() {
|
|
|
local deb_file="$1"
|
|
|
local tmp_dir
|
|
|
tmp_dir="$(mktemp -d)"
|
|
|
|
|
|
dpkg-deb -R "$deb_file" "$tmp_dir" >/dev/null
|
|
|
|
|
|
mkdir -p "$tmp_dir/DEBIAN"
|
|
|
mkdir -p "$tmp_dir$(dirname "$APT_BOOTSTRAP_KEY_IN_PKG")"
|
|
|
install -m 0644 "$tmp_key" "$tmp_dir$APT_BOOTSTRAP_KEY_IN_PKG"
|
|
|
|
|
|
cat > "$tmp_dir/DEBIAN/postinst" <<EOF
|
|
|
#!/bin/sh
|
|
|
set -e
|
|
|
|
|
|
KEY_SRC="$APT_BOOTSTRAP_KEY_IN_PKG"
|
|
|
KEY_DST="$APT_KEYRING_PATH"
|
|
|
LIST_FILE="$APT_SOURCE_LIST_FILE"
|
|
|
SOURCE_LINE='deb [signed-by=$APT_KEYRING_PATH] $APT_SOURCE_URL $APT_SOURCE_SUITE $APT_SOURCE_COMPONENT'
|
|
|
|
|
|
if [ ! -f "\$KEY_SRC" ]; then
|
|
|
echo "warning: bootstrap key file missing: \$KEY_SRC" >&2
|
|
|
else
|
|
|
install -d "\$(dirname "\$KEY_DST")"
|
|
|
install -m 0644 "\$KEY_SRC" "\$KEY_DST"
|
|
|
fi
|
|
|
|
|
|
install -d "\$(dirname "\$LIST_FILE")"
|
|
|
printf '%s\n' "\$SOURCE_LINE" > "\$LIST_FILE"
|
|
|
|
|
|
if command -v apt-get >/dev/null 2>&1; then
|
|
|
apt-get update || true
|
|
|
elif command -v apt >/dev/null 2>&1; then
|
|
|
apt update || true
|
|
|
fi
|
|
|
|
|
|
exit 0
|
|
|
EOF
|
|
|
|
|
|
chmod 0755 "$tmp_dir/DEBIAN/postinst"
|
|
|
dpkg-deb -b "$tmp_dir" "$deb_file" >/dev/null
|
|
|
rm -rf "$tmp_dir"
|
|
|
}
|
|
|
|
|
|
for project in "${PROJECTS[@]}"; do
|
|
|
for arch in amd64 arm64; do
|
|
|
shopt -s nullglob
|
|
|
debs=( "$DIST_ROOT/$project/$arch"/*.deb )
|
|
|
shopt -u nullglob
|
|
|
if (( ${#debs[@]} == 0 )); then
|
|
|
continue
|
|
|
fi
|
|
|
for deb_file in "${debs[@]}"; do
|
|
|
echo "==> inject bootstrap into $(basename "$deb_file")"
|
|
|
inject_one_deb "$deb_file"
|
|
|
done
|
|
|
done
|
|
|
done
|
|
|
|
|
|
echo "==> deb bootstrap 注入完成"
|
|
|
echo " source: $APT_SOURCE_URL $APT_SOURCE_SUITE $APT_SOURCE_COMPONENT"
|
|
|
echo " keyring: $APT_KEYRING_PATH"
|