更新 devlop 脚本以统一端口配置,优化项目结构;修正合并脚本中的路径引用,确保正确合并 newapp 构建产物至 miniprogram 目录。
This commit is contained in:
@@ -4,8 +4,8 @@
|
||||
Soul 创业派对 - 统一部署脚本(支持两种模式)
|
||||
|
||||
模式一 devlop(默认):dist 切换方式
|
||||
本地 pnpm build → 打包 zip → 上传解压到 dist2 → 宝塔暂停 → dist→dist1, dist2→dist → 重启
|
||||
用法: python scripts/devlop.py [--no-build]
|
||||
本地 pnpm build → 打包 zip → 上传解压到 dist2 → 在 dist2 执行 pnpm install 并等待完成 → 再切换目录、重启
|
||||
用法: python scripts/TestDevlop.py [--no-build]
|
||||
|
||||
模式二 deploy:直接覆盖方式
|
||||
本地打包 tar.gz → SSH 上传解压到项目目录 → 宝塔 API 重启
|
||||
@@ -16,7 +16,8 @@ Soul 创业派对 - 统一部署脚本(支持两种模式)
|
||||
DEPLOY_PROJECT_PATH # deploy 模式项目路径,默认 /www/wwwroot/soulTest
|
||||
DEVOP_BASE_PATH # devlop 模式目录,默认 /www/wwwroot/auto-devlop/soulTest
|
||||
BAOTA_PANEL_URL / BAOTA_API_KEY / DEPLOY_PM2_APP
|
||||
DEPLOY_PORT / DEPLOY_NODE_VERSION / DEPLOY_NODE_PATH
|
||||
DEPLOY_PORT # 应用端口,统一由此读取,默认 30066(见 DEFAULT_DEPLOY_PORT)
|
||||
DEPLOY_NODE_VERSION / DEPLOY_NODE_PATH
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
@@ -52,6 +53,12 @@ except ImportError:
|
||||
|
||||
# ==================== 配置 ====================
|
||||
|
||||
# 端口统一从环境变量 DEPLOY_PORT 读取,未设置时使用此默认值
|
||||
DEPLOY_PM2_APP = "testsoul"
|
||||
DEFAULT_DEPLOY_PORT = 30066
|
||||
DEPLOY_PROJECT_PATH = "/www/wwwroot/soulTest"
|
||||
DEPLOY_SITE_URL = "https://soulTest.quwanzhi.com"
|
||||
|
||||
def get_cfg():
|
||||
"""获取基础部署配置(deploy 模式与 devlop 共用 SSH/宝塔)"""
|
||||
return {
|
||||
@@ -59,12 +66,12 @@ def get_cfg():
|
||||
"user": os.environ.get("DEPLOY_USER", "root"),
|
||||
"password": os.environ.get("DEPLOY_PASSWORD", "Zhiqun1984"),
|
||||
"ssh_key": os.environ.get("DEPLOY_SSH_KEY", ""),
|
||||
"project_path": os.environ.get("DEPLOY_PROJECT_PATH", "/www/wwwroot/soulTest"),
|
||||
"project_path": os.environ.get("DEPLOY_PROJECT_PATH", DEPLOY_PROJECT_PATH),
|
||||
"panel_url": os.environ.get("BAOTA_PANEL_URL", "https://42.194.232.22:9988"),
|
||||
"api_key": os.environ.get("BAOTA_API_KEY", "hsAWqFSi0GOCrunhmYdkxy92tBXfqYjd"),
|
||||
"pm2_name": os.environ.get("DEPLOY_PM2_APP", "soulTest"),
|
||||
"site_url": os.environ.get("DEPLOY_SITE_URL", "https://soulTest.quwanzhi.com"),
|
||||
"port": int(os.environ.get("DEPLOY_PORT", "30066")),
|
||||
"pm2_name": os.environ.get("DEPLOY_PM2_APP", DEPLOY_PM2_APP),
|
||||
"site_url": os.environ.get("DEPLOY_SITE_URL", DEPLOY_SITE_URL),
|
||||
"port": int(os.environ.get("DEPLOY_PORT", str(DEFAULT_DEPLOY_PORT))),
|
||||
"node_version": os.environ.get("DEPLOY_NODE_VERSION", "v22.14.0"),
|
||||
"node_path": os.environ.get("DEPLOY_NODE_PATH", "/www/server/nodejs/v22.14.0/bin"),
|
||||
}
|
||||
@@ -152,7 +159,9 @@ def restart_node_project(panel_url, api_key, pm2_name):
|
||||
return False
|
||||
|
||||
|
||||
def add_or_update_node_project(panel_url, api_key, pm2_name, project_path, port=30006, node_path=None):
|
||||
def add_or_update_node_project(panel_url, api_key, pm2_name, project_path, port=None, node_path=None):
|
||||
if port is None:
|
||||
port = int(os.environ.get("DEPLOY_PORT", str(DEFAULT_DEPLOY_PORT)))
|
||||
port_env = "PORT=%d " % port
|
||||
run_cmd = port_env + ("%s/node server.js" % node_path if node_path else "node server.js")
|
||||
payload = {"name": pm2_name, "path": project_path, "run_cmd": run_cmd, "port": str(port)}
|
||||
@@ -402,7 +411,7 @@ def deploy_via_baota_api(cfg):
|
||||
panel_url, api_key, pm2_name = cfg["panel_url"], cfg["api_key"], cfg["pm2_name"]
|
||||
project_path = cfg["project_path"]
|
||||
node_path = cfg.get("node_path", "/www/server/nodejs/v22.14.0/bin")
|
||||
port = cfg.get("port", 30006)
|
||||
port = cfg["port"]
|
||||
|
||||
if not get_node_project_status(panel_url, api_key, pm2_name):
|
||||
add_or_update_node_project(panel_url, api_key, pm2_name, project_path, port, node_path)
|
||||
@@ -482,11 +491,12 @@ def pack_standalone_zip(root):
|
||||
server_js = os.path.join(staging, "server.js")
|
||||
if os.path.isfile(server_js):
|
||||
try:
|
||||
deploy_port = int(os.environ.get("DEPLOY_PORT", str(DEFAULT_DEPLOY_PORT)))
|
||||
with open(server_js, "r", encoding="utf-8") as f:
|
||||
c = f.read()
|
||||
if "|| 3000" in c:
|
||||
with open(server_js, "w", encoding="utf-8") as f:
|
||||
f.write(c.replace("|| 3000", "|| 30006"))
|
||||
f.write(c.replace("|| 3000", "|| %d" % deploy_port))
|
||||
except Exception:
|
||||
pass
|
||||
zip_path = os.path.join(tempfile.gettempdir(), "soul_devlop.zip")
|
||||
@@ -577,8 +587,9 @@ def upload_zip_and_extract_to_dist2(cfg, zip_path):
|
||||
|
||||
|
||||
def run_pnpm_install_in_dist2(cfg):
|
||||
"""服务器 dist2 内执行 pnpm install(devlop 模式)"""
|
||||
print("[4/7] 服务器 dist2 内执行 pnpm install ...")
|
||||
"""服务器 dist2 内执行 pnpm install,阻塞等待完成后再返回(改目录前必须完成)"""
|
||||
print("[4/7] 服务器 dist2 内执行 pnpm install(等待完成后再切换目录)...")
|
||||
sys.stdout.flush()
|
||||
client = paramiko.SSHClient()
|
||||
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
try:
|
||||
@@ -596,7 +607,7 @@ def run_pnpm_install_in_dist2(cfg):
|
||||
err = stderr.read().decode("utf-8", errors="replace").strip()
|
||||
if stdout.channel.recv_exit_status() != 0:
|
||||
return False, "pnpm install 失败\n" + (err or out)
|
||||
print(" [成功] pnpm install 完成")
|
||||
print(" [成功] dist2 内 pnpm install 已执行完成,可安全切换目录")
|
||||
return True, None
|
||||
except Exception as e:
|
||||
return False, str(e)
|
||||
@@ -673,10 +684,12 @@ def main():
|
||||
os.remove(zip_path)
|
||||
except Exception:
|
||||
pass
|
||||
# 必须在 dist2 内 pnpm install 执行完成后再切换目录
|
||||
ok, err = run_pnpm_install_in_dist2(cfg)
|
||||
if not ok:
|
||||
print(" [失败] %s" % (err or "pnpm install 失败"))
|
||||
return 1
|
||||
# install 已完成,再执行 dist→dist1、dist2→dist 切换
|
||||
if not remote_swap_dist_and_restart(cfg):
|
||||
return 1
|
||||
print("")
|
||||
|
||||
@@ -1,23 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Soul 创业派对 - 统一部署脚本(支持两种模式)
|
||||
|
||||
模式一 devlop(默认):dist 切换方式
|
||||
本地 pnpm build → 打包 zip → 上传解压到 dist2 → 宝塔暂停 → dist→dist1, dist2→dist → 重启
|
||||
用法: python scripts/devlop.py [--no-build]
|
||||
|
||||
模式二 deploy:直接覆盖方式
|
||||
本地打包 tar.gz → SSH 上传解压到项目目录 → 宝塔 API 重启
|
||||
用法: python scripts/devlop.py --mode deploy [--no-build] [--no-upload] [--no-api]
|
||||
|
||||
环境变量(可选):
|
||||
DEPLOY_HOST / DEPLOY_USER / DEPLOY_PASSWORD / DEPLOY_SSH_KEY
|
||||
DEPLOY_PROJECT_PATH # deploy 模式项目路径,默认 /www/wwwroot/soul
|
||||
DEVOP_BASE_PATH # devlop 模式目录,默认 /www/wwwroot/auto-devlop/soul
|
||||
BAOTA_PANEL_URL / BAOTA_API_KEY / DEPLOY_PM2_APP
|
||||
DEPLOY_PORT / DEPLOY_NODE_VERSION / DEPLOY_NODE_PATH
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
@@ -52,6 +34,12 @@ except ImportError:
|
||||
|
||||
# ==================== 配置 ====================
|
||||
|
||||
# 端口统一从环境变量 DEPLOY_PORT 读取,未设置时使用此默认值
|
||||
DEPLOY_PM2_APP = "soul"
|
||||
DEFAULT_DEPLOY_PORT = 30006
|
||||
DEPLOY_PROJECT_PATH = "/www/wwwroot/soul"
|
||||
DEPLOY_SITE_URL = "https://soul.quwanzhi.com"
|
||||
|
||||
def get_cfg():
|
||||
"""获取基础部署配置(deploy 模式与 devlop 共用 SSH/宝塔)"""
|
||||
return {
|
||||
@@ -59,12 +47,12 @@ def get_cfg():
|
||||
"user": os.environ.get("DEPLOY_USER", "root"),
|
||||
"password": os.environ.get("DEPLOY_PASSWORD", "Zhiqun1984"),
|
||||
"ssh_key": os.environ.get("DEPLOY_SSH_KEY", ""),
|
||||
"project_path": os.environ.get("DEPLOY_PROJECT_PATH", "/www/wwwroot/soul"),
|
||||
"project_path": os.environ.get("DEPLOY_PROJECT_PATH", DEPLOY_PROJECT_PATH),
|
||||
"panel_url": os.environ.get("BAOTA_PANEL_URL", "https://42.194.232.22:9988"),
|
||||
"api_key": os.environ.get("BAOTA_API_KEY", "hsAWqFSi0GOCrunhmYdkxy92tBXfqYjd"),
|
||||
"pm2_name": os.environ.get("DEPLOY_PM2_APP", "soul"),
|
||||
"site_url": os.environ.get("DEPLOY_SITE_URL", "https://soul.quwanzhi.com"),
|
||||
"port": int(os.environ.get("DEPLOY_PORT", "30006")),
|
||||
"pm2_name": os.environ.get("DEPLOY_PM2_APP", DEPLOY_PM2_APP),
|
||||
"site_url": os.environ.get("DEPLOY_SITE_URL", DEPLOY_SITE_URL),
|
||||
"port": int(os.environ.get("DEPLOY_PORT", str(DEFAULT_DEPLOY_PORT))),
|
||||
"node_version": os.environ.get("DEPLOY_NODE_VERSION", "v22.14.0"),
|
||||
"node_path": os.environ.get("DEPLOY_NODE_PATH", "/www/server/nodejs/v22.14.0/bin"),
|
||||
}
|
||||
@@ -73,7 +61,7 @@ def get_cfg():
|
||||
def get_cfg_devlop():
|
||||
"""devlop 模式配置:在基础配置上增加 base_path / dist / dist2"""
|
||||
cfg = get_cfg().copy()
|
||||
cfg["base_path"] = os.environ.get("DEVOP_BASE_PATH", "/www/wwwroot/auto-devlop/soul")
|
||||
cfg["base_path"] = os.environ.get("DEVOP_BASE_PATH", "/www/wwwroot/auto-devlop/soulTest")
|
||||
cfg["dist_path"] = cfg["base_path"] + "/dist"
|
||||
cfg["dist2_path"] = cfg["base_path"] + "/dist2"
|
||||
return cfg
|
||||
@@ -152,7 +140,9 @@ def restart_node_project(panel_url, api_key, pm2_name):
|
||||
return False
|
||||
|
||||
|
||||
def add_or_update_node_project(panel_url, api_key, pm2_name, project_path, port=30006, node_path=None):
|
||||
def add_or_update_node_project(panel_url, api_key, pm2_name, project_path, port=None, node_path=None):
|
||||
if port is None:
|
||||
port = int(os.environ.get("DEPLOY_PORT", str(DEFAULT_DEPLOY_PORT)))
|
||||
port_env = "PORT=%d " % port
|
||||
run_cmd = port_env + ("%s/node server.js" % node_path if node_path else "node server.js")
|
||||
payload = {"name": pm2_name, "path": project_path, "run_cmd": run_cmd, "port": str(port)}
|
||||
@@ -364,8 +354,8 @@ def upload_and_extract(cfg, tarball_path):
|
||||
else:
|
||||
client.connect(cfg["host"], username=cfg["user"], password=cfg["password"], timeout=15)
|
||||
sftp = client.open_sftp()
|
||||
remote_tar = "/tmp/soul_deploy.tar.gz"
|
||||
remote_script = "/tmp/soul_deploy_extract.sh"
|
||||
remote_tar = "/tmp/soulTest_deploy.tar.gz"
|
||||
remote_script = "/tmp/soulTest_deploy_extract.sh"
|
||||
sftp.put(tarball_path, remote_tar)
|
||||
node_path = cfg.get("node_path", "/www/server/nodejs/v22.14.0/bin")
|
||||
project_path = cfg["project_path"]
|
||||
@@ -402,7 +392,7 @@ def deploy_via_baota_api(cfg):
|
||||
panel_url, api_key, pm2_name = cfg["panel_url"], cfg["api_key"], cfg["pm2_name"]
|
||||
project_path = cfg["project_path"]
|
||||
node_path = cfg.get("node_path", "/www/server/nodejs/v22.14.0/bin")
|
||||
port = cfg.get("port", 30006)
|
||||
port = cfg["port"]
|
||||
|
||||
if not get_node_project_status(panel_url, api_key, pm2_name):
|
||||
add_or_update_node_project(panel_url, api_key, pm2_name, project_path, port, node_path)
|
||||
@@ -482,11 +472,12 @@ def pack_standalone_zip(root):
|
||||
server_js = os.path.join(staging, "server.js")
|
||||
if os.path.isfile(server_js):
|
||||
try:
|
||||
deploy_port = int(os.environ.get("DEPLOY_PORT", str(DEFAULT_DEPLOY_PORT)))
|
||||
with open(server_js, "r", encoding="utf-8") as f:
|
||||
c = f.read()
|
||||
if "|| 3000" in c:
|
||||
with open(server_js, "w", encoding="utf-8") as f:
|
||||
f.write(c.replace("|| 3000", "|| 30006"))
|
||||
f.write(c.replace("|| 3000", "|| %d" % deploy_port))
|
||||
except Exception:
|
||||
pass
|
||||
zip_path = os.path.join(tempfile.gettempdir(), "soul_devlop.zip")
|
||||
@@ -532,7 +523,7 @@ def upload_zip_and_extract_to_dist2(cfg, zip_path):
|
||||
client.connect(cfg["host"], username=cfg["user"], password=cfg["password"], timeout=30, banner_timeout=30)
|
||||
print(" [OK] SSH 已连接,正在上传 zip(%.1f MB)..." % zip_size_mb)
|
||||
sys.stdout.flush()
|
||||
remote_zip = cfg["base_path"].rstrip("/") + "/soul_devlop.zip"
|
||||
remote_zip = cfg["base_path"].rstrip("/") + "/soulTest_devlop.zip"
|
||||
sftp = client.open_sftp()
|
||||
# 上传进度:每 5MB 打印一次
|
||||
chunk_mb = 5.0
|
||||
@@ -577,8 +568,9 @@ def upload_zip_and_extract_to_dist2(cfg, zip_path):
|
||||
|
||||
|
||||
def run_pnpm_install_in_dist2(cfg):
|
||||
"""服务器 dist2 内执行 pnpm install(devlop 模式)"""
|
||||
print("[4/7] 服务器 dist2 内执行 pnpm install ...")
|
||||
"""服务器 dist2 内执行 pnpm install,阻塞等待完成后再返回(改目录前必须完成)"""
|
||||
print("[4/7] 服务器 dist2 内执行 pnpm install(等待完成后再切换目录)...")
|
||||
sys.stdout.flush()
|
||||
client = paramiko.SSHClient()
|
||||
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
try:
|
||||
@@ -596,7 +588,7 @@ def run_pnpm_install_in_dist2(cfg):
|
||||
err = stderr.read().decode("utf-8", errors="replace").strip()
|
||||
if stdout.channel.recv_exit_status() != 0:
|
||||
return False, "pnpm install 失败\n" + (err or out)
|
||||
print(" [成功] pnpm install 完成")
|
||||
print(" [成功] dist2 内 pnpm install 已执行完成,可安全切换目录")
|
||||
return True, None
|
||||
except Exception as e:
|
||||
return False, str(e)
|
||||
@@ -673,10 +665,12 @@ def main():
|
||||
os.remove(zip_path)
|
||||
except Exception:
|
||||
pass
|
||||
# 必须在 dist2 内 pnpm install 执行完成后再切换目录
|
||||
ok, err = run_pnpm_install_in_dist2(cfg)
|
||||
if not ok:
|
||||
print(" [失败] %s" % (err or "pnpm install 失败"))
|
||||
return 1
|
||||
# install 已完成,再执行 dist→dist1、dist2→dist 切换
|
||||
if not remote_swap_dist_and_restart(cfg):
|
||||
return 1
|
||||
print("")
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/**
|
||||
* 将 newpp 构建产物 dist/mp 合并到项目根 miniprogram/
|
||||
* 保留 miniprogram 壳:custom-tab-bar、project.config.json、sitemap.json、app.js 的 globalData/request 等需手动合并
|
||||
* 将 newapp 构建产物 dist/mp 合并到项目根 miniprogram/
|
||||
* 保留 miniprogram 壳:custom-tab-bar、project.config.json、sitemap.json、app.js(不覆盖壳的 app.js)
|
||||
* 用法:node scripts/merge-kbone-to-miniprogram.js
|
||||
*/
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const root = path.resolve(__dirname, '..')
|
||||
const distMp = path.join(root, 'newpp', 'dist', 'mp')
|
||||
const distMp = path.join(root, 'newapp', 'dist', 'mp')
|
||||
const miniprogram = path.join(root, 'miniprogram')
|
||||
|
||||
if (!fs.existsSync(distMp)) {
|
||||
console.error('未找到 newpp/dist/mp,请先在 newpp 目录执行: npm run build:mp')
|
||||
console.error('未找到 newapp/dist/mp,请先在 newapp 目录执行: npm run build:mp')
|
||||
process.exit(1)
|
||||
}
|
||||
if (!fs.existsSync(miniprogram)) {
|
||||
@@ -34,7 +34,7 @@ function copyDir(src, dest) {
|
||||
}
|
||||
|
||||
// 要保留的 miniprogram 文件/目录(合并前备份,合并后覆盖回去)
|
||||
const keep = ['custom-tab-bar', 'project.config.json', 'sitemap.json']
|
||||
const keep = ['custom-tab-bar', 'project.config.json', 'sitemap.json', 'app.js']
|
||||
const backupDir = path.join(root, '.miniprogram-backup')
|
||||
if (!fs.existsSync(backupDir)) fs.mkdirSync(backupDir, { recursive: true })
|
||||
|
||||
@@ -82,5 +82,4 @@ for (const name of keep) {
|
||||
}
|
||||
}
|
||||
|
||||
console.log('已合并 newpp/dist/mp -> miniprogram/,并保留 custom-tab-bar、project.config.json、sitemap.json')
|
||||
console.log('请手动合并 app.js 的 globalData、request、loadFeatureConfig 等逻辑到 kbone 生成的 app.js')
|
||||
console.log('已合并 newapp/dist/mp -> miniprogram/,并保留 custom-tab-bar、project.config.json、sitemap.json、app.js')
|
||||
|
||||
Reference in New Issue
Block a user