|
|
#!/usr/bin/env bash
|
|
|
# 双容器打包:分别在容器内构建 amd64 与 arm64(均支持自动发现项目)。
|
|
|
set -euo pipefail
|
|
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
|
IMAGE_TAG="${IMAGE_TAG:-tauri-linux-deb:20.04}"
|
|
|
RUN_MODE="${RUN_MODE:-docker}" # docker: dual-container all; hybrid: host amd64 + docker arm64
|
|
|
GENERATE_APT_REPO="${GENERATE_APT_REPO:-1}"
|
|
|
VERIFY_APT_REPO="${VERIFY_APT_REPO:-1}"
|
|
|
INJECT_DEB_BOOTSTRAP="${INJECT_DEB_BOOTSTRAP:-1}"
|
|
|
APT_GPG_KEY_ID="${APT_GPG_KEY_ID:-com.jgzy.product}"
|
|
|
APT_GPG_AUTO_CREATE="${APT_GPG_AUTO_CREATE:-1}"
|
|
|
UBUNTU_MIRROR="${UBUNTU_MIRROR:-http://mirrors.aliyun.com/ubuntu}"
|
|
|
UBUNTU_PORTS_MIRROR="${UBUNTU_PORTS_MIRROR:-http://mirrors.aliyun.com/ubuntu-ports}"
|
|
|
CARGO_REGISTRY_MIRROR="${CARGO_REGISTRY_MIRROR:-https://rsproxy.cn/index/}"
|
|
|
CARGO_NET_RETRY="${CARGO_NET_RETRY:-8}"
|
|
|
CARGO_HTTP_TIMEOUT="${CARGO_HTTP_TIMEOUT:-120}"
|
|
|
CARGO_HTTP_MULTIPLEXING="${CARGO_HTTP_MULTIPLEXING:-false}"
|
|
|
ALLOW_RUNTIME_APT_FIX="${ALLOW_RUNTIME_APT_FIX:-1}"
|
|
|
PROJECT_ARGS=()
|
|
|
|
|
|
while (($# > 0)); do
|
|
|
case "$1" in
|
|
|
--docker-only)
|
|
|
RUN_MODE="docker"
|
|
|
shift
|
|
|
;;
|
|
|
--hybrid)
|
|
|
RUN_MODE="hybrid"
|
|
|
shift
|
|
|
;;
|
|
|
--help|-h)
|
|
|
cat <<EOF
|
|
|
用法:
|
|
|
$(basename "$0") [--docker-only|--hybrid] [项目名...]
|
|
|
|
|
|
说明:
|
|
|
--docker-only 双容器模式:容器内分别构建 amd64 + arm64(默认)
|
|
|
--hybrid 宿主机构建 amd64,容器构建 arm64
|
|
|
|
|
|
环境变量:
|
|
|
INJECT_DEB_BOOTSTRAP=1/0 是否注入 deb 安装初始化(默认 1)
|
|
|
GENERATE_APT_REPO=1/0 是否在打包结束后生成 dist/repo(默认 1)
|
|
|
VERIFY_APT_REPO=1/0 生成仓库后执行完整性自检(默认 1)
|
|
|
APT_GPG_KEY_ID=<KEYID> 生成仓库时使用的签名 Key(默认 com.jgzy.product)
|
|
|
APT_GPG_AUTO_CREATE=1/0 缺少签名密钥时自动创建(默认 1)
|
|
|
UBUNTU_MIRROR=<url> 容器内 amd64 apt 源(默认阿里镜像)
|
|
|
UBUNTU_PORTS_MIRROR=<url> 容器内 arm64 apt 源(默认阿里镜像)
|
|
|
CARGO_REGISTRY_MIRROR=<url> Cargo 稀疏索引镜像(默认 rsproxy)
|
|
|
CARGO_NET_RETRY=<n> Cargo 网络重试次数(默认 8)
|
|
|
CARGO_HTTP_TIMEOUT=<s> Cargo 单请求超时秒数(默认 120)
|
|
|
CARGO_HTTP_MULTIPLEXING=true/false Cargo HTTP/2 复用(默认 false)
|
|
|
ALLOW_RUNTIME_APT_FIX=1/0 运行时缺依赖时是否允许 apt 联网补齐(默认 1)
|
|
|
EOF
|
|
|
exit 0
|
|
|
;;
|
|
|
--)
|
|
|
shift
|
|
|
break
|
|
|
;;
|
|
|
-*)
|
|
|
echo "错误: 未知参数 $1" >&2
|
|
|
exit 1
|
|
|
;;
|
|
|
*)
|
|
|
PROJECT_ARGS+=("$1")
|
|
|
shift
|
|
|
;;
|
|
|
esac
|
|
|
done
|
|
|
|
|
|
if (($# > 0)); then
|
|
|
PROJECT_ARGS+=("$@")
|
|
|
fi
|
|
|
|
|
|
cd "$REPO_ROOT"
|
|
|
|
|
|
if ((${#PROJECT_ARGS[@]} == 0)); then
|
|
|
mapfile -t SELECTED_PROJECTS < <(bash "$REPO_ROOT/scripts/build-linux-deb-all.sh" --list-projects)
|
|
|
else
|
|
|
SELECTED_PROJECTS=("${PROJECT_ARGS[@]}")
|
|
|
fi
|
|
|
|
|
|
# 防御性过滤空行,避免出现未知项目 ""
|
|
|
FILTERED_PROJECTS=()
|
|
|
for d in "${SELECTED_PROJECTS[@]}"; do
|
|
|
if [[ -n "$d" ]]; then
|
|
|
FILTERED_PROJECTS+=("$d")
|
|
|
fi
|
|
|
done
|
|
|
SELECTED_PROJECTS=("${FILTERED_PROJECTS[@]}")
|
|
|
|
|
|
if ((${#SELECTED_PROJECTS[@]} == 0)); then
|
|
|
echo "错误: 没有可构建项目" >&2
|
|
|
exit 1
|
|
|
fi
|
|
|
|
|
|
if [[ "$RUN_MODE" == "hybrid" ]]; then
|
|
|
echo "==> host npm ci (${SELECTED_PROJECTS[*]})"
|
|
|
for d in "${SELECTED_PROJECTS[@]}"; do
|
|
|
if [[ ! -f "$REPO_ROOT/$d/package.json" ]]; then
|
|
|
echo "错误: 缺少 $REPO_ROOT/$d/package.json" >&2
|
|
|
exit 1
|
|
|
fi
|
|
|
(cd "$REPO_ROOT/$d" && npm ci)
|
|
|
done
|
|
|
|
|
|
echo "==> host build amd64 (${SELECTED_PROJECTS[*]})"
|
|
|
bash "$REPO_ROOT/scripts/build-linux-deb-all.sh" --arch amd64 "${SELECTED_PROJECTS[@]}"
|
|
|
fi
|
|
|
|
|
|
echo "==> docker build --platform linux/amd64 -f scripts/docker/Dockerfile -t $IMAGE_TAG $REPO_ROOT"
|
|
|
docker build --platform linux/amd64 \
|
|
|
--build-arg UBUNTU_MIRROR="$UBUNTU_MIRROR" \
|
|
|
--build-arg UBUNTU_PORTS_MIRROR="$UBUNTU_PORTS_MIRROR" \
|
|
|
-f scripts/docker/Dockerfile -t "$IMAGE_TAG" "$REPO_ROOT"
|
|
|
|
|
|
if [[ "$RUN_MODE" == "docker" ]]; then
|
|
|
echo "==> docker run #1 (amd64: npm ci + build-linux-deb-all.sh)"
|
|
|
docker run --rm \
|
|
|
--platform linux/amd64 \
|
|
|
-v "$REPO_ROOT:/work" \
|
|
|
-w /work \
|
|
|
-e RUSTUP_HOME=/opt/rustup \
|
|
|
-e CARGO_HOME=/opt/cargo \
|
|
|
-e BUILD_ARCH=amd64 \
|
|
|
-e NPM_REGISTRY="${NPM_REGISTRY:-https://registry.npmjs.org/}" \
|
|
|
-e CLEAN_TAURI_TARGET="${CLEAN_TAURI_TARGET:-1}" \
|
|
|
-e CARGO_REGISTRY_MIRROR="$CARGO_REGISTRY_MIRROR" \
|
|
|
-e CARGO_NET_RETRY="$CARGO_NET_RETRY" \
|
|
|
-e CARGO_HTTP_TIMEOUT="$CARGO_HTTP_TIMEOUT" \
|
|
|
-e CARGO_HTTP_MULTIPLEXING="$CARGO_HTTP_MULTIPLEXING" \
|
|
|
-e ALLOW_RUNTIME_APT_FIX="$ALLOW_RUNTIME_APT_FIX" \
|
|
|
"$IMAGE_TAG" \
|
|
|
bash /work/scripts/docker/container-entry.sh "${SELECTED_PROJECTS[@]}"
|
|
|
|
|
|
echo "==> docker run #2 (arm64: npm ci + build-linux-deb-all.sh)"
|
|
|
docker run --rm \
|
|
|
--platform linux/amd64 \
|
|
|
-v "$REPO_ROOT:/work" \
|
|
|
-w /work \
|
|
|
-e RUSTUP_HOME=/opt/rustup \
|
|
|
-e CARGO_HOME=/opt/cargo \
|
|
|
-e BUILD_ARCH=arm64 \
|
|
|
-e NPM_REGISTRY="${NPM_REGISTRY:-https://registry.npmjs.org/}" \
|
|
|
-e CLEAN_TAURI_TARGET="${CLEAN_TAURI_TARGET:-1}" \
|
|
|
-e CARGO_REGISTRY_MIRROR="$CARGO_REGISTRY_MIRROR" \
|
|
|
-e CARGO_NET_RETRY="$CARGO_NET_RETRY" \
|
|
|
-e CARGO_HTTP_TIMEOUT="$CARGO_HTTP_TIMEOUT" \
|
|
|
-e CARGO_HTTP_MULTIPLEXING="$CARGO_HTTP_MULTIPLEXING" \
|
|
|
-e ALLOW_RUNTIME_APT_FIX="$ALLOW_RUNTIME_APT_FIX" \
|
|
|
"$IMAGE_TAG" \
|
|
|
bash /work/scripts/docker/container-entry.sh "${SELECTED_PROJECTS[@]}"
|
|
|
else
|
|
|
echo "==> docker run (arm64: npm ci + build-linux-deb-all.sh)"
|
|
|
docker run --rm \
|
|
|
--platform linux/amd64 \
|
|
|
-v "$REPO_ROOT:/work" \
|
|
|
-w /work \
|
|
|
-e RUSTUP_HOME=/opt/rustup \
|
|
|
-e CARGO_HOME=/opt/cargo \
|
|
|
-e BUILD_ARCH=arm64 \
|
|
|
-e NPM_REGISTRY="${NPM_REGISTRY:-https://registry.npmjs.org/}" \
|
|
|
-e CLEAN_TAURI_TARGET="${CLEAN_TAURI_TARGET:-1}" \
|
|
|
-e CARGO_REGISTRY_MIRROR="$CARGO_REGISTRY_MIRROR" \
|
|
|
-e CARGO_NET_RETRY="$CARGO_NET_RETRY" \
|
|
|
-e CARGO_HTTP_TIMEOUT="$CARGO_HTTP_TIMEOUT" \
|
|
|
-e CARGO_HTTP_MULTIPLEXING="$CARGO_HTTP_MULTIPLEXING" \
|
|
|
-e ALLOW_RUNTIME_APT_FIX="$ALLOW_RUNTIME_APT_FIX" \
|
|
|
"$IMAGE_TAG" \
|
|
|
bash /work/scripts/docker/container-entry.sh "${SELECTED_PROJECTS[@]}"
|
|
|
fi
|
|
|
|
|
|
normalize_artifact_ownership() {
|
|
|
if ! command -v docker >/dev/null 2>&1; then
|
|
|
return 0
|
|
|
fi
|
|
|
if ! command -v id >/dev/null 2>&1; then
|
|
|
return 0
|
|
|
fi
|
|
|
|
|
|
local uid gid
|
|
|
uid="$(id -u 2>/dev/null || true)"
|
|
|
gid="$(id -g 2>/dev/null || true)"
|
|
|
if [[ -z "$uid" || -z "$gid" ]]; then
|
|
|
return 0
|
|
|
fi
|
|
|
|
|
|
# 容器内构建产物可能由 root 写入,回收为当前用户避免后续注入/重打包失败。
|
|
|
docker run --rm \
|
|
|
--platform linux/amd64 \
|
|
|
-v "$REPO_ROOT:/work" \
|
|
|
-w /work \
|
|
|
"$IMAGE_TAG" \
|
|
|
bash -lc "mkdir -p /work/dist /work/dist/linux-deb /work/dist/repo && chown -R $uid:$gid /work/dist 2>/dev/null || true"
|
|
|
}
|
|
|
|
|
|
echo "==> normalize artifact ownership for host user"
|
|
|
normalize_artifact_ownership
|
|
|
|
|
|
if [[ "$INJECT_DEB_BOOTSTRAP" == "1" ]]; then
|
|
|
echo "==> inject deb bootstrap (postinst + keyring)"
|
|
|
APT_GPG_KEY_ID="$APT_GPG_KEY_ID" APT_GPG_AUTO_CREATE="$APT_GPG_AUTO_CREATE" \
|
|
|
bash "$REPO_ROOT/scripts/inject-deb-bootstrap.sh" "${SELECTED_PROJECTS[@]}"
|
|
|
fi
|
|
|
|
|
|
if [[ "$GENERATE_APT_REPO" == "1" ]]; then
|
|
|
echo "==> generate apt repo (dist/repo)"
|
|
|
APT_GPG_KEY_ID="$APT_GPG_KEY_ID" APT_GPG_AUTO_CREATE="$APT_GPG_AUTO_CREATE" \
|
|
|
bash "$REPO_ROOT/scripts/build-apt-repo.sh" "${SELECTED_PROJECTS[@]}"
|
|
|
|
|
|
if [[ "$VERIFY_APT_REPO" == "1" ]]; then
|
|
|
echo "==> verify apt repo (dist/repo)"
|
|
|
bash "$REPO_ROOT/scripts/verify-apt-repo.sh"
|
|
|
fi
|
|
|
fi
|