mirror of
https://github.com/GSManagerXZ/GameServerManager.git
synced 2026-09-06 16:09:44 +08:00
build: architecture-specific Linux packaging, Docker and installer
This commit is contained in:
41
.github/workflows/build.yml
vendored
41
.github/workflows/build.yml
vendored
@@ -59,6 +59,15 @@ jobs:
|
||||
needs: resolve_version
|
||||
if: github.event.inputs.build_linux == 'true' || github.event_name == 'push' || github.event_name == 'release'
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: x64
|
||||
package_command: npm run package:linux:x64
|
||||
artifact_name: gsm3-management-panel-linux-x64-build
|
||||
- arch: arm64
|
||||
package_command: npm run package:linux:arm64
|
||||
artifact_name: gsm3-management-panel-linux-arm64-build
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Node.js for build
|
||||
@@ -72,17 +81,17 @@ jobs:
|
||||
npm install
|
||||
cd client && npm install
|
||||
cd ../server && npm install
|
||||
- name: Build package
|
||||
run: npm run package:linux
|
||||
- name: Build Linux ${{ matrix.arch }} package
|
||||
run: ${{ matrix.package_command }}
|
||||
env:
|
||||
CI: true
|
||||
NODE_ENV: production
|
||||
APP_VERSION: ${{ needs.resolve_version.outputs.version }}
|
||||
VITE_APP_VERSION: ${{ needs.resolve_version.outputs.version }}
|
||||
- name: Upload artifacts
|
||||
- name: Upload Linux ${{ matrix.arch }} artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: gsm3-management-panel-linux-build
|
||||
name: ${{ matrix.artifact_name }}
|
||||
path: dist/package/
|
||||
retention-days: 30
|
||||
|
||||
@@ -205,29 +214,33 @@ jobs:
|
||||
needs: [resolve_version, build_linux, build_windows]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download Linux artifact
|
||||
- name: Download Linux x64 artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: gsm3-management-panel-linux-build
|
||||
path: linux-build/
|
||||
name: gsm3-management-panel-linux-x64-build
|
||||
path: linux-x64-build/
|
||||
- name: Download Linux arm64 artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: gsm3-management-panel-linux-arm64-build
|
||||
path: linux-arm64-build/
|
||||
- name: Download Windows artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: gsm3-management-panel-windows-build
|
||||
path: windows-build/
|
||||
- name: Create Linux tar.gz
|
||||
run: |
|
||||
cd linux-build
|
||||
tar -czf ../gsm3-management-panel-linux-v${{ needs.resolve_version.outputs.version }}.tar.gz *
|
||||
- name: Create Windows zip
|
||||
- name: Create platform archives
|
||||
run: |
|
||||
tar -czf gsm3-management-panel-linux-x64-v${{ needs.resolve_version.outputs.version }}.tar.gz -C linux-x64-build .
|
||||
tar -czf gsm3-management-panel-linux-arm64-v${{ needs.resolve_version.outputs.version }}.tar.gz -C linux-arm64-build .
|
||||
cd windows-build
|
||||
zip -r ../gsm3-management-panel-windows-v${{ needs.resolve_version.outputs.version }}.zip *
|
||||
zip -r ../gsm3-management-panel-windows-v${{ needs.resolve_version.outputs.version }}.zip .
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
files: |
|
||||
gsm3-management-panel-linux-v${{ needs.resolve_version.outputs.version }}.tar.gz
|
||||
gsm3-management-panel-linux-x64-v${{ needs.resolve_version.outputs.version }}.tar.gz
|
||||
gsm3-management-panel-linux-arm64-v${{ needs.resolve_version.outputs.version }}.tar.gz
|
||||
gsm3-management-panel-windows-v${{ needs.resolve_version.outputs.version }}.zip
|
||||
generate_release_notes: true
|
||||
draft: false
|
||||
|
||||
25
Dockerfile
25
Dockerfile
@@ -228,11 +228,11 @@ RUN if [ "$TARGETARCH" = "arm64" ]; then \
|
||||
npm config set fetch-retry-maxtimeout 120000 && \
|
||||
npm config set fetch-timeout 300000 && \
|
||||
npm run install:all && \
|
||||
npm run package:linux:no-zip; \
|
||||
npm run package:linux:arm64:no-zip; \
|
||||
else \
|
||||
echo "AMD64架构构建,使用标准配置..." && \
|
||||
npm run install:all && \
|
||||
npm run package:linux:no-zip; \
|
||||
npm run package:linux:x64:no-zip; \
|
||||
fi
|
||||
|
||||
# ---------- 运行阶段(最终镜像) ----------
|
||||
@@ -297,18 +297,17 @@ RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
||||
chmod 755 /root/server/data/lib/${BINARY_7Z} && \
|
||||
echo "7z 下载完成: ${BINARY_7Z}"
|
||||
|
||||
# 下载 PTY 二进制文件(从 GitHub Releases latest,构建时预置)
|
||||
# 通过打包产物中的固定资产 CLI 校验并预置当前架构的 PTY
|
||||
RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
||||
PTY_NAME="pty_linux_x64"; \
|
||||
elif [ "$TARGETARCH" = "arm64" ]; then \
|
||||
PTY_NAME="pty_linux_arm64"; \
|
||||
fi && \
|
||||
echo "正在下载 PTY (${PTY_NAME})..." && \
|
||||
wget -t 3 --retry-connrefused --waitretry=2 --read-timeout=30 --timeout=15 \
|
||||
-O /root/server/data/lib/${PTY_NAME} \
|
||||
"https://github.com/MCSManager/PTY/releases/download/latest/${PTY_NAME}" && \
|
||||
chmod 755 /root/server/data/lib/${PTY_NAME} && \
|
||||
echo "PTY 下载完成: ${PTY_NAME}"
|
||||
PTY_ASSET="linux-x64"; \
|
||||
elif [ "$TARGETARCH" = "arm64" ]; then \
|
||||
PTY_ASSET="linux-arm64"; \
|
||||
else \
|
||||
echo "不支持的 PTY 架构: $TARGETARCH" >&2; exit 1; \
|
||||
fi && \
|
||||
node /root/server/utils/ptyAssetCli.js ensure \
|
||||
--asset "$PTY_ASSET" \
|
||||
--target-dir /root/server/data/lib
|
||||
# 拷贝 Python 依赖清单并安装
|
||||
COPY --from=builder /app/server/src/Python/requirements.txt /tmp/requirements.txt
|
||||
# 安装Python依赖并配置最终权限
|
||||
|
||||
@@ -105,10 +105,27 @@ mkdir -pv "$install_path"
|
||||
cd "$install_path"
|
||||
|
||||
if test "$install_type" = "1"; then
|
||||
ARCH=$(uname -m)
|
||||
case "$ARCH" in
|
||||
x86_64|amd64)
|
||||
ARCHIVE_NAME="gsm3-management-panel-linux-x64.tar.gz"
|
||||
PTY_ASSET="linux-x64"
|
||||
;;
|
||||
aarch64|arm64)
|
||||
ARCHIVE_NAME="gsm3-management-panel-linux-arm64.tar.gz"
|
||||
PTY_ASSET="linux-arm64"
|
||||
;;
|
||||
*)
|
||||
echo -e "\x1b[31m不支持的系统架构: $ARCH\x1b[0m"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
DOWNLOAD_URL="https://ghfast.top/https://github.com/GSManagerXZ/GameServerManager/releases/latest/download/$ARCHIVE_NAME"
|
||||
|
||||
if command -v curl &>/dev/null;then
|
||||
curl -Lo gsm3.tgz https://ghfast.top/https://github.com/GSManagerXZ/GameServerManager/releases/latest/download/gsm3-management-panel-linux.tar.gz
|
||||
curl -Lo gsm3.tgz "$DOWNLOAD_URL"
|
||||
elif command -v wget &>/dev/null; then
|
||||
wget -O gsm3.tgz https://ghfast.top/https://github.com/GSManagerXZ/GameServerManager/releases/latest/download/gsm3-management-panel-linux.tar.gz
|
||||
wget -O gsm3.tgz "$DOWNLOAD_URL"
|
||||
else
|
||||
echo -e "\x1b[31m错误:既没有安装curl也没有安装wget,无法下载gsm3程序,请安装这俩其中一个工具后再次执行该脚本!"
|
||||
exit 1
|
||||
@@ -123,51 +140,16 @@ if test "$install_type" = "1"; then
|
||||
rm -rf gsm3.tgz
|
||||
chmod 755 "$install_path/node/bin/node" "$install_path/start.sh" 2>/dev/null || true
|
||||
|
||||
# 验证并修复PTY二进制文件
|
||||
ARCH=$(uname -m)
|
||||
if [ "$ARCH" = "x86_64" ]; then
|
||||
PTY_NAME="pty_linux_x64"
|
||||
elif [ "$ARCH" = "aarch64" ]; then
|
||||
PTY_NAME="pty_linux_arm64"
|
||||
# 通过打包产物中的固定资产 CLI 校验或修复 PTY
|
||||
mkdir -p "$install_path/data/lib"
|
||||
echo -e "\x1b[33m正在校验固定 PTY 资产...\x1b[0m"
|
||||
if "$install_path/node/bin/node" \
|
||||
"$install_path/server/utils/ptyAssetCli.js" ensure \
|
||||
--asset "$PTY_ASSET" \
|
||||
--target-dir "$install_path/data/lib"; then
|
||||
echo -e "\x1b[32mPTY 资产校验完成\x1b[0m"
|
||||
else
|
||||
PTY_NAME=""
|
||||
fi
|
||||
|
||||
if [ -n "$PTY_NAME" ]; then
|
||||
PTY_FILE="$install_path/data/lib/$PTY_NAME"
|
||||
PTY_VALID=false
|
||||
|
||||
# 检查PTY文件是否存在且为有效的ELF二进制文件
|
||||
if [ -f "$PTY_FILE" ]; then
|
||||
if file "$PTY_FILE" 2>/dev/null | grep -q "ELF"; then
|
||||
PTY_VALID=true
|
||||
else
|
||||
echo -e "\x1b[33mPTY文件无效(非ELF二进制),将重新下载...\x1b[0m"
|
||||
rm -f "$PTY_FILE"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$PTY_VALID" = "false" ]; then
|
||||
echo -e "\x1b[33m正在下载PTY二进制文件...\x1b[0m"
|
||||
mkdir -p "$install_path/data/lib"
|
||||
PTY_URL="https://github.com/MCSManager/PTY/releases/download/latest/$PTY_NAME"
|
||||
if command -v curl &>/dev/null; then
|
||||
curl -Lo "$PTY_FILE" "$PTY_URL"
|
||||
elif command -v wget &>/dev/null; then
|
||||
wget -O "$PTY_FILE" "$PTY_URL"
|
||||
fi
|
||||
if [ -f "$PTY_FILE" ] && file "$PTY_FILE" 2>/dev/null | grep -q "ELF"; then
|
||||
echo -e "\x1b[32mPTY下载完成\x1b[0m"
|
||||
else
|
||||
echo -e "\x1b[33mPTY下载失败,终端功能将在服务启动时自动重试下载\x1b[0m"
|
||||
rm -f "$PTY_FILE" 2>/dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
# 设置可执行权限
|
||||
if [ -f "$PTY_FILE" ]; then
|
||||
chmod 755 "$PTY_FILE"
|
||||
fi
|
||||
echo -e "\x1b[33mPTY 资产校验或下载失败;在运行时校验成功前,终端创建功能将保持不可用\x1b[0m"
|
||||
fi
|
||||
|
||||
# 设置其他lib文件权限
|
||||
|
||||
@@ -12,10 +12,14 @@
|
||||
"build:client": "cd client && npm run build",
|
||||
"package": "npm run build && node scripts/package.js",
|
||||
"package:create": "node scripts/package.js",
|
||||
"package:linux": "npm run build && node scripts/package.js --target=linux",
|
||||
"package:linux": "npm run package:linux:x64",
|
||||
"package:linux:x64": "npm run build && node scripts/package.js --target=linux-x64",
|
||||
"package:linux:arm64": "npm run build && node scripts/package.js --target=linux-arm64",
|
||||
"package:windows": "npm run build && node scripts/package.js --target=windows",
|
||||
"package:no-zip": "npm run build && node scripts/package.js --no-zip",
|
||||
"package:linux:no-zip": "npm run build && node scripts/package.js --target=linux --no-zip",
|
||||
"package:linux:no-zip": "npm run package:linux:x64:no-zip",
|
||||
"package:linux:x64:no-zip": "npm run build && node scripts/package.js --target=linux-x64 --no-zip",
|
||||
"package:linux:arm64:no-zip": "npm run build && node scripts/package.js --target=linux-arm64 --no-zip",
|
||||
"package:windows:no-zip": "npm run build && node scripts/package.js --target=windows --no-zip",
|
||||
"start": "cd server && npm start",
|
||||
"start:prod": "cd dist && node index.js",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const fs = require('fs-extra')
|
||||
const path = require('path')
|
||||
const archiver = require('archiver')
|
||||
const { execSync } = require('child_process')
|
||||
const { execFileSync, execSync } = require('child_process')
|
||||
const https = require('https')
|
||||
const { pipeline } = require('stream')
|
||||
const { promisify } = require('util')
|
||||
@@ -16,9 +16,23 @@ const packageDir = path.join(distDir, 'package')
|
||||
|
||||
// 获取命令行参数
|
||||
const args = process.argv.slice(2)
|
||||
const buildTarget = args.find(arg => arg.startsWith('--target='))?.split('=')[1]
|
||||
const requestedBuildTarget = args.find(arg => arg.startsWith('--target='))?.split('=')[1]
|
||||
const skipZip = args.includes('--no-zip') || args.includes('--skip-zip')
|
||||
const outputFile = buildTarget
|
||||
|
||||
function resolveBuildTarget(target) {
|
||||
if (!target || target === 'windows' || target === 'linux-x64' || target === 'linux-arm64') {
|
||||
return target
|
||||
}
|
||||
if (target === 'linux') {
|
||||
if (process.arch === 'x64') return 'linux-x64'
|
||||
if (process.arch === 'arm64') return 'linux-arm64'
|
||||
throw new Error(`不支持当前架构的 Linux 打包: ${process.arch}`)
|
||||
}
|
||||
throw new Error(`不支持的打包目标: ${target}`)
|
||||
}
|
||||
|
||||
const buildTarget = resolveBuildTarget(requestedBuildTarget)
|
||||
const outputFile = buildTarget
|
||||
? path.join(distDir, `${packageName}-${buildTarget}-v${version}.zip`)
|
||||
: path.join(distDir, `${packageName}-v${version}.zip`)
|
||||
|
||||
@@ -27,21 +41,14 @@ const nodeVersion = '22.17.0'
|
||||
// Zip-Tools GitHub 下载配置(始终使用最新版本)
|
||||
const ZIP_TOOLS_GITHUB_URL = 'https://github.com/MCSManager/Zip-Tools/releases/latest/download/'
|
||||
|
||||
// PTY GitHub 下载配置(tag 名为 latest)
|
||||
const PTY_GITHUB_URL = 'https://github.com/MCSManager/PTY/releases/download/latest/'
|
||||
|
||||
/**
|
||||
* 获取目标平台对应的 Zip-Tools 二进制文件名列表
|
||||
* 打包时下载所有该平台支持的架构版本
|
||||
* 获取目标包对应的 Zip-Tools 二进制文件名列表
|
||||
*/
|
||||
function getZipToolsBinaries(platform) {
|
||||
if (platform === 'linux') {
|
||||
return ['file_zip_linux_x64', 'file_zip_linux_arm64']
|
||||
} else if (platform === 'windows') {
|
||||
// GitHub Releases 上 Zip-Tools 只有 win32_x64 版本
|
||||
return ['file_zip_win32_x64.exe']
|
||||
}
|
||||
// 未指定平台时下载所有版本
|
||||
function getZipToolsBinaries(target) {
|
||||
if (target === 'linux-x64') return ['file_zip_linux_x64']
|
||||
if (target === 'linux-arm64') return ['file_zip_linux_arm64']
|
||||
if (target === 'windows') return ['file_zip_win32_x64.exe']
|
||||
// 未指定目标时下载所有版本
|
||||
return [
|
||||
'file_zip_linux_x64',
|
||||
'file_zip_linux_arm64',
|
||||
@@ -52,16 +59,13 @@ function getZipToolsBinaries(platform) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取目标平台对应的 7z 二进制文件名列表
|
||||
* 打包时下载所有该平台支持的架构版本
|
||||
* 获取目标包对应的 7z 二进制文件名列表
|
||||
*/
|
||||
function get7zBinaries(platform) {
|
||||
if (platform === 'linux') {
|
||||
return ['7z_linux_x64', '7z_linux_arm64']
|
||||
} else if (platform === 'windows') {
|
||||
return ['7z_win32_x64.exe', '7z_win32_arm64.exe']
|
||||
}
|
||||
// 未指定平台时下载所有版本
|
||||
function get7zBinaries(target) {
|
||||
if (target === 'linux-x64') return ['7z_linux_x64']
|
||||
if (target === 'linux-arm64') return ['7z_linux_arm64']
|
||||
if (target === 'windows') return ['7z_win32_x64.exe', '7z_win32_arm64.exe']
|
||||
// 未指定目标时下载所有版本
|
||||
return [
|
||||
'7z_linux_x64', '7z_linux_arm64', '7z_linux_386', '7z_linux_arm',
|
||||
'7z_win32_x64.exe', '7z_win32_arm64.exe',
|
||||
@@ -213,79 +217,51 @@ async function download7z(platform) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取目标平台对应的 PTY 二进制文件名列表
|
||||
* 打包时下载所有该平台支持的架构版本
|
||||
* 获取目标包对应的固定 PTY 资产键列表
|
||||
*/
|
||||
function getPtyBinaries(platform) {
|
||||
if (platform === 'linux') {
|
||||
return ['pty_linux_x64', 'pty_linux_arm64']
|
||||
} else if (platform === 'windows') {
|
||||
return ['pty_win32_x64.exe']
|
||||
}
|
||||
// 未指定平台时下载所有版本
|
||||
return [
|
||||
'pty_linux_x64',
|
||||
'pty_linux_arm64',
|
||||
'pty_win32_x64.exe',
|
||||
]
|
||||
function getPtyAssetKeys(target) {
|
||||
if (target === 'linux-x64') return ['linux-x64']
|
||||
if (target === 'linux-arm64') return ['linux-arm64']
|
||||
if (target === 'windows') return ['win32-x64']
|
||||
return ['linux-x64', 'linux-arm64', 'win32-x64']
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载 PTY 二进制文件到打包目录的 data/lib/
|
||||
* 从 GitHub Releases 下载,确保打包产物内置 PTY
|
||||
* 通过服务端固定资产 CLI 校验或下载 PTY 到打包目录
|
||||
*/
|
||||
async function downloadPty(platform) {
|
||||
const binaries = getPtyBinaries(platform)
|
||||
async function ensurePtyAssets(target) {
|
||||
const libDir = path.join(packageDir, 'data', 'lib')
|
||||
await fs.ensureDir(libDir)
|
||||
|
||||
console.log('📥 正在从 GitHub 下载 PTY (latest)...')
|
||||
let hasSuccess = false
|
||||
|
||||
for (const binaryName of binaries) {
|
||||
const url = `${PTY_GITHUB_URL}${binaryName}`
|
||||
const destPath = path.join(libDir, binaryName)
|
||||
|
||||
console.log(` 下载: ${binaryName}`)
|
||||
try {
|
||||
await downloadFile(url, destPath)
|
||||
// 非 Windows 二进制文件设置可执行权限
|
||||
if (!binaryName.endsWith('.exe')) {
|
||||
try {
|
||||
execSync(`chmod +x "${destPath}"`)
|
||||
} catch (e) {
|
||||
// Windows 构建环境无法 chmod,忽略
|
||||
}
|
||||
}
|
||||
console.log(` ✅ ${binaryName} 下载完成`)
|
||||
hasSuccess = true
|
||||
} catch (err) {
|
||||
console.error(` ⚠️ ${binaryName} 下载失败(跳过): ${err.message}`)
|
||||
}
|
||||
console.log('📥 正在校验固定 PTY 资产...')
|
||||
for (const assetKey of getPtyAssetKeys(target)) {
|
||||
execFileSync(process.execPath, [
|
||||
path.join(packageDir, 'server', 'utils', 'ptyAssetCli.js'),
|
||||
'ensure',
|
||||
'--asset', assetKey,
|
||||
'--target-dir', libDir
|
||||
], { stdio: 'inherit' })
|
||||
}
|
||||
|
||||
if (!hasSuccess) {
|
||||
throw new Error('所有 PTY 文件下载均失败')
|
||||
}
|
||||
console.log('✅ PTY 下载完成')
|
||||
console.log('✅ PTY 资产校验完成')
|
||||
}
|
||||
|
||||
async function downloadNodejs(platform) {
|
||||
async function downloadNodejs(target) {
|
||||
const nodeUrls = {
|
||||
linux: `https://nodejs.org/dist/v${nodeVersion}/node-v${nodeVersion}-linux-x64.tar.xz`,
|
||||
'linux-x64': `https://nodejs.org/dist/v${nodeVersion}/node-v${nodeVersion}-linux-x64.tar.xz`,
|
||||
'linux-arm64': `https://nodejs.org/dist/v${nodeVersion}/node-v${nodeVersion}-linux-arm64.tar.xz`,
|
||||
windows: `https://nodejs.org/download/release/latest-v22.x/win-x64/node.exe`
|
||||
}
|
||||
|
||||
const url = nodeUrls[platform]
|
||||
|
||||
const url = nodeUrls[target]
|
||||
if (!url) {
|
||||
throw new Error(`不支持的平台: ${platform}`)
|
||||
throw new Error(`不支持的 Node.js 打包目标: ${target}`)
|
||||
}
|
||||
|
||||
|
||||
const fileName = url.split('/').pop()
|
||||
const filePath = path.join(__dirname, '..', fileName)
|
||||
|
||||
console.log(`📥 正在下载 Node.js ${nodeVersion} for ${platform}...`)
|
||||
|
||||
|
||||
console.log(`📥 正在下载 Node.js ${nodeVersion} for ${target}...`)
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const file = fs.createWriteStream(filePath)
|
||||
https.get(url, (response) => {
|
||||
@@ -293,7 +269,7 @@ async function downloadNodejs(platform) {
|
||||
reject(new Error(`下载失败: ${response.statusCode}`))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
response.pipe(file)
|
||||
file.on('finish', () => {
|
||||
file.close()
|
||||
@@ -308,33 +284,36 @@ async function downloadNodejs(platform) {
|
||||
}
|
||||
|
||||
// 解压和部署Node.js
|
||||
async function deployNodejs(platform, downloadedFile) {
|
||||
async function deployNodejs(target, downloadedFile) {
|
||||
const projectRoot = path.join(__dirname, '..')
|
||||
|
||||
if (platform === 'linux') {
|
||||
|
||||
if (target === 'linux-x64' || target === 'linux-arm64') {
|
||||
console.log('📦 正在解压 Linux Node.js...')
|
||||
// 解压到临时目录
|
||||
execSync(`tar -xf "${downloadedFile}"`, { cwd: projectRoot })
|
||||
|
||||
// 重命名为node文件夹
|
||||
const extractedDir = path.join(projectRoot, `node-v${nodeVersion}-linux-x64`)
|
||||
|
||||
const extractedDirNames = {
|
||||
'linux-x64': `node-v${nodeVersion}-linux-x64`,
|
||||
'linux-arm64': `node-v${nodeVersion}-linux-arm64`
|
||||
}
|
||||
const extractedDir = path.join(projectRoot, extractedDirNames[target])
|
||||
const targetDir = path.join(packageDir, 'node')
|
||||
|
||||
|
||||
if (await fs.pathExists(extractedDir)) {
|
||||
await fs.move(extractedDir, targetDir)
|
||||
console.log('✅ Linux Node.js 部署到项目根目录/node')
|
||||
} else {
|
||||
throw new Error('Linux Node.js 解压失败')
|
||||
}
|
||||
} else if (platform === 'windows') {
|
||||
} else if (target === 'windows') {
|
||||
console.log('📦 正在部署 Windows Node.js...')
|
||||
// 复制node.exe到打包根目录(start.bat不再cd server,cwd为根目录)
|
||||
const targetFile = path.join(packageDir, 'node.exe')
|
||||
|
||||
|
||||
await fs.copy(downloadedFile, targetFile)
|
||||
console.log('✅ Windows Node.js 部署到打包根目录/node.exe')
|
||||
}
|
||||
|
||||
|
||||
// 清理下载的文件
|
||||
await fs.remove(downloadedFile)
|
||||
}
|
||||
@@ -360,7 +339,7 @@ async function createPackage() {
|
||||
path.join(packageDir, 'server', 'package.json')
|
||||
)
|
||||
|
||||
// PTY 文件不再从本地复制,改为从 GitHub 下载到 data/lib/ 目录
|
||||
// PTY 文件不从本地复制,待生产依赖安装后由固定资产 CLI 写入 data/lib/
|
||||
|
||||
// 复制环境变量配置文件
|
||||
await fs.copy(
|
||||
@@ -425,6 +404,9 @@ async function createPackage() {
|
||||
console.error('❌ 服务端依赖安装失败:', error)
|
||||
throw error
|
||||
}
|
||||
|
||||
// 服务端构建文件和生产依赖就绪后,通过固定清单校验或下载 PTY
|
||||
await ensurePtyAssets(buildTarget)
|
||||
|
||||
console.log('🎨 复制前端文件...')
|
||||
// 复制前端构建文件
|
||||
@@ -457,14 +439,6 @@ async function createPackage() {
|
||||
console.log(' 用户启动时会自动从镜像站下载')
|
||||
}
|
||||
|
||||
// 下载 PTY 二进制文件(从 GitHub Releases)
|
||||
try {
|
||||
await downloadPty(buildTarget)
|
||||
} catch (error) {
|
||||
console.error('⚠️ PTY 下载失败,打包产物中将不包含 PTY:', error.message)
|
||||
console.log(' 用户启动时会自动从镜像站下载')
|
||||
}
|
||||
|
||||
console.log('📝 创建启动脚本...')
|
||||
// 根据目标平台创建启动脚本
|
||||
if (buildTarget === 'windows') {
|
||||
@@ -473,7 +447,7 @@ async function createPackage() {
|
||||
path.join(__dirname, 'start.bat'),
|
||||
path.join(packageDir, 'start.bat')
|
||||
)
|
||||
} else if (buildTarget === 'linux') {
|
||||
} else if (buildTarget === 'linux-x64' || buildTarget === 'linux-arm64') {
|
||||
const startShScript = `#!/bin/bash
|
||||
echo "正在启动GSM3管理面板..."
|
||||
# PTY 文件已迁移到 data/lib/ 目录,启动时由服务端自动检测
|
||||
|
||||
Reference in New Issue
Block a user