Files
saasshop/scripts/build_oneclick_bundle.sh
2026-03-18 12:04:09 +08:00

173 lines
4.8 KiB
Bash
Executable File
Raw 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
set -euo pipefail
# 构建“一键部署包”(代码 + vendor + 加密数据库快照)
# 目标:下载压缩包 → 解压 → 运行 install.sh → 即可恢复到最新数据并可访问。
#
# 依赖git / tar / gzip
# 可选composer仅当需要现装 vendor
#
# 用法:
# bash scripts/build_oneclick_bundle.sh
# 输出:
# /app/working/dist/saasshop_bundle_<timestamp>.tar.gz
# /app/working/dist/saasshop_bundle_latest.tar.gz
REPO_DIR=$(cd "$(dirname "$0")/.." && pwd)
cd "$REPO_DIR"
DIST_DIR="/app/working/dist"
mkdir -p "$DIST_DIR"
DATA_REPO_SSH=""
if [[ -f /app/working.secret/saasshop_data_repo_ssh ]]; then
DATA_REPO_SSH=$(cat /app/working.secret/saasshop_data_repo_ssh)
fi
if [[ "$DATA_REPO_SSH" == "" ]]; then
echo "缺少数据仓地址:/app/working.secret/saasshop_data_repo_ssh"
exit 31
fi
STAMP=$(date +%Y%m%d_%H%M%S)
BUNDLE_ROOT=$(mktemp -d)
trap 'rm -rf "$BUNDLE_ROOT" || true' EXIT
APP_DIR="$BUNDLE_ROOT/saasshop"
mkdir -p "$APP_DIR"
# 1) 打包代码(不带 .git
echo "[bundle] copying app files ..."
# 使用 tar 管道复制(比 cp -a 更容易排除)
tar \
--exclude=".git" \
--exclude="node_modules" \
--exclude="storage/logs" \
--exclude="storage/framework/cache" \
--exclude="storage/framework/sessions" \
--exclude="storage/framework/views" \
--exclude="storage/app/private" \
--exclude=".env" \
-cf - . | (cd "$APP_DIR" && tar -xf -)
# 2) 确保 vendor 存在(无构建链/傻瓜部署,优先直接随包携带)
if [[ ! -d "$APP_DIR/vendor" ]]; then
echo "[bundle] vendor 不存在,尝试 composer install --no-dev ..."
if command -v composer >/dev/null 2>&1; then
(cd "$APP_DIR" && composer install --no-dev --prefer-dist --no-interaction)
else
echo "[bundle] composer 不存在且 vendor 缺失,无法构建傻瓜包"
exit 32
fi
fi
# 3) 拉取数据仓最新快照
echo "[bundle] fetching latest encrypted snapshot from data repo ..."
DATA_TMP="$BUNDLE_ROOT/data_repo"
git clone "$DATA_REPO_SSH" "$DATA_TMP" >/dev/null
if [[ ! -f "$DATA_TMP/snapshots/latest.sql.gz.enc" ]]; then
echo "数据仓缺少 snapshots/latest.sql.gz.enc"
exit 33
fi
mkdir -p "$APP_DIR/bundle/snapshots"
cp -f "$DATA_TMP/snapshots/latest.sql.gz.enc" "$APP_DIR/bundle/snapshots/latest.sql.gz.enc"
if [[ -f "$DATA_TMP/snapshots/manifest.json" ]]; then
cp -f "$DATA_TMP/snapshots/manifest.json" "$APP_DIR/bundle/snapshots/manifest.json"
fi
# 4) 写入 install.sh真正一键入口
cat > "$APP_DIR/install.sh" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
# SaaSShop 一键部署脚本(随 bundle 一起发放)
# 用法:
# export SAASSHOP_DB_SNAPSHOT_KEY='解密密钥'
# bash install.sh
#
# 你也可以先准备好 .env推荐脚本会优先读取项目根目录 .env。
APP_DIR=$(cd "$(dirname "$0")" && pwd)
cd "$APP_DIR"
if [[ ! -f .env ]]; then
if [[ -f .env.example ]]; then
cp .env.example .env
echo "[install] 已生成 .env来自 .env.example请按需修改 DB_* / APP_URL 等配置。"
else
echo "[install] 缺少 .env 与 .env.example无法继续"
exit 41
fi
fi
# 读取 .env仅用于 DB 连接)
set -a
# shellcheck disable=SC1091
source .env
set +a
DB_HOST=${DB_HOST:-127.0.0.1}
DB_PORT=${DB_PORT:-3306}
DB_DATABASE=${DB_DATABASE:-appdb}
DB_USERNAME=${DB_USERNAME:-appuser}
DB_PASSWORD=${DB_PASSWORD:-}
if [[ "${SAASSHOP_DB_SNAPSHOT_KEY:-}" == "" ]]; then
echo "[install] 缺少 SAASSHOP_DB_SNAPSHOT_KEY无法解密并恢复完整数据。"
echo "[install] 请先export SAASSHOP_DB_SNAPSHOT_KEY='...密钥...'"
exit 42
fi
# 权限准备
mkdir -p storage bootstrap/cache
chmod -R ug+rwX storage bootstrap/cache || true
# APP_KEY
if ! grep -q '^APP_KEY=' .env || [[ "${APP_KEY:-}" == "" ]]; then
echo "[install] 生成 APP_KEY ..."
php artisan key:generate --force
fi
echo "[install] 导入最新数据库快照 ..."
ENC_FILE="bundle/snapshots/latest.sql.gz.enc"
if [[ ! -f "$ENC_FILE" ]]; then
echo "[install] 缺少快照文件:$ENC_FILE"
exit 43
fi
TMP_DIR=$(mktemp -d)
trap 'rm -rf "$TMP_DIR" || true' EXIT
SQL_GZ="$TMP_DIR/latest.sql.gz"
openssl enc -d -aes-256-cbc -pbkdf2 \
-pass env:SAASSHOP_DB_SNAPSHOT_KEY \
-in "$ENC_FILE" -out "$SQL_GZ"
gzip -dc "$SQL_GZ" | mysql \
--host="$DB_HOST" --port="$DB_PORT" \
--user="$DB_USERNAME" --password="$DB_PASSWORD"
echo "[install] 清理缓存 ..."
php artisan optimize:clear
echo "[done] 部署完成。接下来:配置 nginx 指向 public/,即可访问。"
EOF
chmod +x "$APP_DIR/install.sh"
# 5) 打包
OUT_FILE="$DIST_DIR/saasshop_bundle_${STAMP}.tar.gz"
LATEST_FILE="$DIST_DIR/saasshop_bundle_latest.tar.gz"
echo "[bundle] creating tar.gz ..."
(
cd "$BUNDLE_ROOT"
tar -czf "$OUT_FILE" saasshop
)
cp -f "$OUT_FILE" "$LATEST_FILE"
echo "[bundle] output: $OUT_FILE"
echo "[bundle] latest: $LATEST_FILE"