xyc
4 天以前 c83480ec468accd3fd86ec778a53973d7b6b68a4
pack-deploy.ps1
@@ -9,7 +9,9 @@
       执行 mvn clean package;无论成败都还原开发机真实配置
    2) 解压 jar 检查内置 application.yml:必须全是占位符(禁止 sk- 密钥 / 明文口令),不合格直接中止
    3) npm run build 重建前端 dist(可 -SkipFrontend)
    4) 组装完整部署包:backend(jar + application.yml + 启动脚本 + docs + web) / frontend/dist / db / README
    4) 组装完整部署包:backend(jar + application.yml + 启动脚本 + 服务包装器 + docs + web) / frontend/dist / db / README
       Windows 服务包装器 WinSW:优先用 deploy-templates\tools\winsw.exe 缓存(校验 SHA-256),
       缺失时自动下载 v2.12.0 x64 到该缓存目录;随包输出为 backend\trafficAudit.exe
    5) 对组装后的整包再扫一遍明文密钥
  修订背景(2026-10-03):2026-10-02 手工产出的包缺 application.yml / docs / db / 启动脚本,
@@ -20,7 +22,8 @@
param(
  [string]$OutRoot = '',
  [switch]$SkipFrontend,
  [switch]$SkipBackend      # 复用已存在的 jar(不重编译、不动源码配置),仅用于补全/重组发布包
  [switch]$SkipBackend,     # 复用已存在的 jar(不重编译、不动源码配置),仅用于补全/重组发布包
  [switch]$SkipServiceWrapper   # 不把 WinSW 服务包装器打进包(即不提供“注册成 Windows 服务”的开机自启)
)
$ErrorActionPreference = 'Stop'
@@ -117,6 +120,40 @@
}
if (-not (Test-Path $webDist)) { throw "未找到前端产物:$webDist(去掉 -SkipFrontend 重新构建)" }
# ---------- WinSW(Windows 服务包装器)准备:本地缓存优先,缺失时从官方发布页下载并校验 SHA-256 ----------
# WinSW v2.12.0 官方产物未做 Authenticode 签名,所以以固定 SHA-256 作为完整性校验。
$winswUrl    = 'https://github.com/winsw/winsw/releases/download/v2.12.0/WinSW-x64.exe'
$winswSha256 = '05B82D46AD331CC16BDC00DE5C6332C1EF818DF8CEEFCD49C726553209B3A0DA'
$winswSrc    = Join-Path $tplDir 'tools\winsw.exe'
function Test-WinswCache {
  param([string]$Path)
  if (-not (Test-Path -LiteralPath $Path)) { return $false }
  $hash = (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash
  if ($hash -ne $winswSha256) {
    Write-Host ('      警告:WinSW 缓存 SHA-256 不匹配,将重新下载(期望 {0}...,实际 {1}...)' -f $winswSha256.Substring(0, 12), $hash.Substring(0, 12))
    return $false
  }
  return $true
}
if ($SkipServiceWrapper) {
  Write-Host '      已按 -SkipServiceWrapper 跳过:包内不含 Windows 服务方式开机自启'
} else {
  if (-not (Test-WinswCache $winswSrc)) {
    New-Item -ItemType Directory -Force -Path (Split-Path -Parent $winswSrc) | Out-Null
    Write-Host '      下载 WinSW v2.12.0 x64 ...'
    try {
      [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
      Invoke-WebRequest -Uri $winswUrl -OutFile $winswSrc -UseBasicParsing
    } catch {
      throw ("下载 WinSW 失败:{0}。`n请手动下载 {1} 存为 {2} 后重试,或用 -SkipServiceWrapper 跳过。" -f $_.Exception.Message, $winswUrl, $winswSrc)
    }
    if (-not (Test-WinswCache $winswSrc)) { throw "WinSW 校验失败,已中止打包:$winswSrc" }
  }
  Write-Host ('      WinSW 就绪(SHA-256 已校验):{0:N1} MB' -f ((Get-Item -LiteralPath $winswSrc).Length / 1MB))
}
# ---------- [4/5] 组装完整部署目录 ----------
Write-Host '[4/5] 组装部署目录...'
$stamp = Get-Date -Format 'yyyyMMdd'
@@ -129,6 +166,15 @@
Copy-Item (Join-Path $tplDir 'backend\application.yml') (Join-Path $dest 'backend') -Force
Copy-Item (Join-Path $tplDir 'backend\start-backend.cmd') (Join-Path $dest 'backend') -Force
Copy-Item (Join-Path $tplDir 'backend\start-backend.sh') (Join-Path $dest 'backend') -Force
Copy-Item (Join-Path $tplDir 'backend\start-backend-service.cmd') (Join-Path $dest 'backend') -Force
Copy-Item (Join-Path $tplDir 'backend\install-autostart.ps1') (Join-Path $dest 'backend') -Force
if (-not $SkipServiceWrapper) {
  # WinSW 要求配置文件名与 exe 同名:trafficAudit.exe 读同目录的 trafficAudit.xml
  Copy-Item -LiteralPath $winswSrc (Join-Path $dest 'backend\trafficAudit.exe') -Force
  Copy-Item (Join-Path $tplDir 'backend\trafficAudit.xml') (Join-Path $dest 'backend') -Force
  Copy-Item (Join-Path $tplDir 'backend\install-service.ps1') (Join-Path $dest 'backend') -Force
  Copy-Item (Join-Path $tplDir 'backend\install-service.cmd') (Join-Path $dest 'backend') -Force
}
Copy-Item $webDist (Join-Path $dest 'frontend') -Recurse -Force
Copy-Item (Join-Path $tplDir 'frontend\nginx.conf.example') (Join-Path $dest 'frontend') -Force
Copy-Item (Join-Path $tplDir 'db\*.sql') (Join-Path $dest 'db') -Force