Files
wz1531 d083d8524b 补回 swagger(Swashbuckle 6.6.2 + XML 注释)、socket.html 入库、固化本机构建与服务器替换脚本
- Directory.Build.props: 生成 XML 注释供 Swagger 展示中文说明
- AdminHost/FishGameHost: 接入 Swashbuckle,路由 adminswagger / roomswagger
- 后台前端 config.js 改为同源相对地址,适配反向代理
- socket.html(SignalR 协议文档)纳入仓库
- deploy/: 本机构建(容器内编译,规避杀软)、服务器替换脚本、Nginx 配置
2026-10-18 17:28:45 +08:00

158 lines
7.4 KiB
PowerShell
Raw Permalink 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.
<#
本机构建镜像并导出 tar(编译在 Docker 容器内进行)
------------------------------------------------------------------
适用场景:服务器无法访问 mcr.microsoft.com;且本机杀软(如火绒)
会拦截/删除编译产物(AdminApi.dll 等)。
编译与镜像构建全部在容器内完成,Windows 杀软无法拦截中间产物。
用法:
# 1) 全量构建(7 个服务)
powershell -ExecutionPolicy Bypass -File deploy\build-local.ps1 -PublicHost game.xxx.com
# 2) 只构建/打包指定服务(多个逗号分隔)
powershell -ExecutionPolicy Bypass -File deploy\build-local.ps1 -PublicHost game.xxx.com -Services admin,fishgame
# 3) 按「改动的子项目」自动推导需要重建的服务(推荐,避免漏编)
powershell -ExecutionPolicy Bypass -File deploy\build-local.ps1 -PublicHost game.xxx.com -ForProject FishGameService
产物:deploy\dist\ 下的 tar(只含本次构建的镜像)
#>
param(
[string]$PublicHost = "CHANGE_ME",
[string]$Tag = (Get-Date -Format "yyyyMMdd-HHmm"),
[string[]]$Services = @(),
[string]$ForProject = "",
[switch]$DryRun
)
$ErrorActionPreference = "Stop"
$Root = Split-Path -Parent $PSScriptRoot
$Deploy = Join-Path $Root "deploy"
$Dist = Join-Path $Deploy "dist"
function Info($m) { Write-Host "[本地构建] $m" -ForegroundColor Green }
function Warn($m) { Write-Host "[警告] $m" -ForegroundColor Yellow }
# ---------- 服务定义:服务名 -> 项目文件 / 入口 dll / Host 项目名 ----------
$serviceMap = [ordered]@{
gateway = @{ proj = "Gateway/Gateway.csproj"; dll = "Gateway.dll"; host = "Gateway" }
admin = @{ proj = "AdminSrc/AdminHost/AdminHost.csproj"; dll = "AdminHost.dll"; host = "AdminHost" }
user = @{ proj = "UserSrc/UserHost/UserHost.csproj"; dll = "UserHost.dll"; host = "UserHost" }
customer = @{ proj = "CustomerSrc/CustomerHost/CustomerHost.csproj"; dll = "CustomerHost.dll"; host = "CustomerHost" }
chess = @{ proj = "ChessGameHost/ChessGameHost.csproj"; dll = "ChessGameHost.dll"; host = "ChessGameHost" }
fishroom = @{ proj = "FishGameSrc/FishRoomHost/FishRoomHost.csproj"; dll = "FishRoomHost.dll"; host = "FishRoomHost" }
fishgame = @{ proj = "FishGameSrc/FishGameHost/FishGameHost.csproj"; dll = "FishGameHost.dll"; host = "FishGameHost" }
}
# ---------- 依赖图:改动某项目 -> 需要重建的服务 ----------
function Get-AffectedServices([string]$changedProject) {
$refs = @{}
Get-ChildItem -Path $Root -Recurse -Filter *.csproj -ErrorAction SilentlyContinue | ForEach-Object {
$txt = [IO.File]::ReadAllText($_.FullName)
$deps = @()
foreach ($m in [regex]::Matches($txt, 'ProjectReference\s+Include="([^"]+)"')) {
$deps += [IO.Path]::GetFileNameWithoutExtension($m.Groups[1].Value)
}
$refs[$_.BaseName] = $deps
}
$result = @()
foreach ($name in $serviceMap.Keys) {
$hostName = $serviceMap[$name].host
if ($hostName -eq $changedProject) { $result += $name; continue }
$seen = New-Object System.Collections.Generic.HashSet[string]
$stack = New-Object System.Collections.Stack
foreach ($d in @($refs[$hostName])) { if ($d) { [void]$stack.Push($d) } }
while ($stack.Count -gt 0) {
$cur = $stack.Pop()
if (-not $seen.Add($cur)) { continue }
foreach ($d in @($refs[$cur])) { if ($d) { [void]$stack.Push($d) } }
}
if ($seen.Contains($changedProject)) { $result += $name }
}
return $result
}
# ---------- 1) 决定要构建哪些服务 ----------
if ($ForProject) {
$targets = @(Get-AffectedServices $ForProject)
if ($targets.Count -eq 0) {
throw "没有任何 Host 引用项目 '$ForProject'(项目名不带 .csproj)。请检查拼写。"
}
Info ("按项目 '$ForProject' 推导出需重建的服务: " + ($targets -join ', '))
} elseif ($Services.Count -gt 0) {
$svcList = @()
foreach ($s in $Services) { $svcList += ($s -split ',') }
$svcList = @($svcList | ForEach-Object { $_.Trim() } | Where-Object { $_ })
foreach ($s in $svcList) {
if (-not $serviceMap.Contains($s)) { throw "未知服务名 '$s'。可选: $($serviceMap.Keys -join ', ')" }
}
$targets = @($svcList)
Info ("指定构建服务: " + ($targets -join ', '))
} else {
$targets = @($serviceMap.Keys)
Info "全量构建 7 个服务"
}
if ($DryRun) {
Info ("[DryRun] 将构建的服务: " + ($targets -join ', '))
exit 0
}
# ---------- 2) 前置校验 + 准备基础镜像(经镜像站拉取并打回官方 tag)----------
if (-not (Get-Command docker -ErrorAction SilentlyContinue)) { throw "未找到 docker,请先安装并启动 Docker Desktop" }
$prevEap = $ErrorActionPreference
$ErrorActionPreference = "Continue"
docker info 2>&1 | Out-Null
$dockerOk = ($LASTEXITCODE -eq 0)
$ErrorActionPreference = $prevEap
if (-not $dockerOk) { throw "Docker 引擎未就绪,请先启动 Docker Desktop 并等托盘图标变绿" }
if ($PublicHost -eq "CHANGE_ME") {
Warn "未指定 -PublicHost,捕鱼对局层地址会被写成 CHANGE_ME,客户端将连不上"
}
$baseImages = [ordered]@{
"mcr.microsoft.com/dotnet/sdk:8.0" = "mcr.m.daocloud.io/dotnet/sdk:8.0"
"mcr.microsoft.com/dotnet/aspnet:8.0" = "mcr.m.daocloud.io/dotnet/aspnet:8.0"
}
foreach ($official in $baseImages.Keys) {
docker image inspect $official *> $null
if ($LASTEXITCODE -ne 0) {
Info "本地缺少 $official,经镜像站拉取 ..."
docker pull $baseImages[$official]
if ($LASTEXITCODE -ne 0) { throw "拉取 $official 失败" }
docker tag $baseImages[$official] $official
}
}
# ---------- 3) 构建镜像(编译在容器内)----------
foreach ($name in $targets) {
$s = $serviceMap[$name]
Info "构建镜像 0524$name ..."
docker build -f (Join-Path $Deploy "Dockerfile.build") `
--build-arg "PROJECT=$($s.proj)" `
--build-arg "SVC_NAME=$name" `
--build-arg "APP_DLL=$($s.dll)" `
--build-arg "PUBLIC_HOST=$PublicHost" `
-t "0524$name" $Root
if ($LASTEXITCODE -ne 0) { throw "构建 0524$name 失败" }
}
# ---------- 4) 导出 tar(只含本次构建的镜像)----------
New-Item -ItemType Directory -Path $Dist -Force | Out-Null
$isAll = ($targets.Count -eq $serviceMap.Count)
$suffix = if ($isAll) { "" } else { "-" + ($targets -join "-") }
$tar = Join-Path $Dist "buyu-images$suffix-$Tag.tar"
$tags = @($targets | ForEach-Object { "0524$_" })
Info ("导出镜像到 $tar ...(含: " + ($tags -join ', ') + ")")
docker save -o $tar @tags
if ($LASTEXITCODE -ne 0) { throw "导出镜像失败" }
$sizeMB = [math]::Round((Get-Item $tar).Length / 1MB, 1)
Write-Host ""
Info "完成!镜像包: $tar ($sizeMB MB)"
Write-Host "下一步 —— 在本机上传到服务器:" -ForegroundColor Cyan
Write-Host " ssh root@<服务器IP> `"mkdir -p /opt/buyu/deploy/dist`"" -ForegroundColor Cyan
Write-Host " scp `"$tar`" root@<服务器IP>:/opt/buyu/deploy/dist/" -ForegroundColor Cyan
Write-Host "再登录服务器执行(只重启本次涉及的服务):" -ForegroundColor Cyan
Write-Host " cd /opt/buyu" -ForegroundColor Cyan
Write-Host (" bash deploy/load-and-up.sh deploy/dist/" + (Split-Path $tar -Leaf) + " " + ($targets -join ' ')) -ForegroundColor Cyan