You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

207 lines
5.7 KiB
Bash

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/env bash
# 从 dist/linux-deb 产物生成可部署的 APT 仓库目录repo/)。
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
DIST_ROOT="$REPO_ROOT/dist/linux-deb"
OUTPUT_REPO_DIR="$REPO_ROOT/dist/repo"
SUITE="${APT_REPO_SUITE:-v10}"
COMPONENT="${APT_REPO_COMPONENT:-main}"
ARCHES="${APT_REPO_ARCHES:-amd64 arm64}"
GPG_KEY_ID="${APT_GPG_KEY_ID:-com.jgzy.product}"
AUTO_CREATE_GPG_KEY="${APT_GPG_AUTO_CREATE:-1}"
PUBLIC_KEY_ASC_NAME="${APT_PUBLIC_KEY_ASC_NAME:-zyyun-archive-keyring.asc}"
PUBLIC_KEY_GPG_NAME="${APT_PUBLIC_KEY_GPG_NAME:-zyyun-archive-keyring.gpg}"
usage() {
cat <<EOF
用法:
$(basename "$0") [--output-dir <dir>] [--suite <name>] [--component <name>] [项目名...]
环境变量:
APT_GPG_KEY_ID GPG 签名 Key ID默认: com.jgzy.product
APT_GPG_AUTO_CREATE 1/0。密钥不存在时自动执行 quick-gen-key默认: 1
APT_REPO_SUITE 仓库 suite默认: v10
APT_REPO_COMPONENT 仓库 component默认: main
APT_REPO_ARCHES 仓库架构(默认: "amd64 arm64"
EOF
}
PROJECTS=()
while (($# > 0)); do
case "$1" in
--output-dir)
OUTPUT_REPO_DIR="${2:-}"
shift 2
;;
--suite)
SUITE="${2:-}"
shift 2
;;
--component)
COMPONENT="${2:-}"
shift 2
;;
--help|-h)
usage
exit 0
;;
--)
shift
break
;;
-*)
echo "错误: 未知参数 $1" >&2
exit 1
;;
*)
PROJECTS+=("$1")
shift
;;
esac
done
if (($# > 0)); then
PROJECTS+=("$@")
fi
if [[ ! -d "$DIST_ROOT" ]]; then
echo "错误: 未找到 deb 产物目录 $DIST_ROOT" >&2
echo "请先执行 scripts/docker/run-build.sh 或 scripts/build-linux-deb-all.sh" >&2
exit 1
fi
if ! command -v apt-ftparchive >/dev/null 2>&1; then
echo "错误: 未安装 apt-ftparchive请安装 apt-utils" >&2
exit 1
fi
if ! command -v gpg >/dev/null 2>&1; then
echo "错误: 未安装 gpg签名与公钥导出需要" >&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[@]}"
}
rm -rf "$OUTPUT_REPO_DIR"
mkdir -p "$OUTPUT_REPO_DIR/pool/$COMPONENT" "$OUTPUT_REPO_DIR/dists/$SUITE/$COMPONENT"
copy_project_debs() {
local project="$1"
local initial="${project:0:1}"
local src_dir="$DIST_ROOT/$project"
local dst_dir="$OUTPUT_REPO_DIR/pool/$COMPONENT/$initial/$project"
if [[ ! -d "$src_dir" ]]; then
echo "警告: 未找到项目产物目录 $src_dir,跳过" >&2
return 0
fi
mkdir -p "$dst_dir"
shopt -s nullglob
local files=( "$src_dir"/amd64/*.deb "$src_dir"/arm64/*.deb )
shopt -u nullglob
if (( ${#files[@]} == 0 )); then
echo "警告: $src_dir 下没有 .deb 文件,跳过" >&2
return 0
fi
cp -v "${files[@]}" "$dst_dir/"
}
if ((${#PROJECTS[@]} == 0)); then
shopt -s nullglob
for project_path in "$DIST_ROOT"/*; do
[[ -d "$project_path" ]] || continue
PROJECTS+=( "$(basename "$project_path")" )
done
shopt -u nullglob
fi
if ((${#PROJECTS[@]} == 0)); then
echo "错误: 未发现任何可发布项目($DIST_ROOT 为空)" >&2
exit 1
fi
ensure_signing_key "$GPG_KEY_ID"
for project in "${PROJECTS[@]}"; do
copy_project_debs "$project"
done
# 为每个架构生成独立 Packages按文件名后缀筛选
for arch in $ARCHES; do
out_dir="$OUTPUT_REPO_DIR/dists/$SUITE/$COMPONENT/binary-$arch"
mkdir -p "$out_dir"
tmp_pool="$OUTPUT_REPO_DIR/.tmp-pool-$arch"
rm -rf "$tmp_pool"
mkdir -p "$tmp_pool"
shopt -s globstar nullglob
arch_files=( "$OUTPUT_REPO_DIR"/pool/$COMPONENT/**/*.deb )
shopt -u globstar nullglob
for deb_file in "${arch_files[@]}"; do
base="$(basename "$deb_file")"
# 兼容 xxx_amd64.deb / xxx_arm64.deb 命名
if [[ "$base" == *"_${arch}.deb" ]]; then
rel="${deb_file#$OUTPUT_REPO_DIR/pool/$COMPONENT/}"
mkdir -p "$tmp_pool/$(dirname "$rel")"
cp -f "$deb_file" "$tmp_pool/$rel"
fi
done
apt-ftparchive packages "$tmp_pool" > "$out_dir/Packages"
gzip -kf "$out_dir/Packages"
rm -rf "$tmp_pool"
done
apt-ftparchive \
-o APT::FTPArchive::Release::Suite="$SUITE" \
-o APT::FTPArchive::Release::Codename="$SUITE" \
-o APT::FTPArchive::Release::Components="$COMPONENT" \
-o APT::FTPArchive::Release::Architectures="$ARCHES" \
release "$OUTPUT_REPO_DIR/dists/$SUITE" > "$OUTPUT_REPO_DIR/dists/$SUITE/Release"
gpg --default-key "$GPG_KEY_ID" -abs \
-o "$OUTPUT_REPO_DIR/dists/$SUITE/Release.gpg" \
"$OUTPUT_REPO_DIR/dists/$SUITE/Release"
gpg --default-key "$GPG_KEY_ID" --clearsign \
-o "$OUTPUT_REPO_DIR/dists/$SUITE/InRelease" \
"$OUTPUT_REPO_DIR/dists/$SUITE/Release"
gpg --armor --export "$GPG_KEY_ID" > "$OUTPUT_REPO_DIR/$PUBLIC_KEY_ASC_NAME"
gpg --export "$GPG_KEY_ID" > "$OUTPUT_REPO_DIR/$PUBLIC_KEY_GPG_NAME"
SIGN_HINT="已签名KEY: $GPG_KEY_ID"
echo ""
echo "==> APT 仓库目录生成完成"
echo " 输出目录: $OUTPUT_REPO_DIR"
echo " Suite: $SUITE, Component: $COMPONENT, Architectures: $ARCHES"
echo " 签名状态: $SIGN_HINT"
echo " 公钥文件: $OUTPUT_REPO_DIR/$PUBLIC_KEY_ASC_NAME"
echo " $OUTPUT_REPO_DIR/$PUBLIC_KEY_GPG_NAME"
echo " 可直接将 dist/repo 打包上传到仓库机。"