dfe5636290
Get-BlockingProcess возвращает скаляр, когда bin занят ровно одним процессом MCP, и .Count под Set-StrictMode роняет скрипт вместо диагностики. Та же ловушка, что описана для лаунчера, — теперь результат заворачивается в @().
105 lines
5.6 KiB
PowerShell
105 lines
5.6 KiB
PowerShell
#requires -Version 7.0
|
||
<#
|
||
.SYNOPSIS
|
||
Сборка MCP-сервера для dev-цикла: с диагностикой блокировки bin живыми сессиями.
|
||
|
||
.DESCRIPTION
|
||
Три режима, по возрастанию стоимости:
|
||
|
||
-Check компиляция мимо bin (сервер можно не останавливать) — «оно вообще собирается?»
|
||
(по умолчанию) полная сборка в bin + юнит-тесты — новый бинарь для теневого запуска
|
||
-NoTest то же без юнит-тестов
|
||
|
||
Каталог bin занят, пока хотя бы одна сессия MCP запущена ПРЯМО из него (см. .mcp.json).
|
||
С tools/dev/launch-dev-mcp.ps1 сервер работает из теневой копии, и bin свободен всегда.
|
||
|
||
.EXAMPLE
|
||
pwsh -NoProfile -File tools/dev/rebuild-mcp.ps1 -Check
|
||
.EXAMPLE
|
||
pwsh -NoProfile -File tools/dev/rebuild-mcp.ps1
|
||
#>
|
||
[CmdletBinding()]
|
||
param(
|
||
[switch] $Check,
|
||
[switch] $NoTest
|
||
)
|
||
|
||
Set-StrictMode -Version Latest
|
||
$ErrorActionPreference = 'Stop'
|
||
|
||
$repo = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
|
||
$binDir = Join-Path $repo 'src\Kompas.Mcp.Host\bin\x64\Release\net8.0-windows'
|
||
|
||
function Get-BlockingProcess {
|
||
param([Parameter(Mandatory)] [string] $Directory)
|
||
|
||
$target = $Directory.TrimEnd('\').ToLowerInvariant()
|
||
$found = @()
|
||
foreach ($p in (Get-Process -Name 'kompas-mcp' -ErrorAction SilentlyContinue)) {
|
||
try {
|
||
if (-not $p.Path) { continue }
|
||
if ((Split-Path -Parent $p.Path).TrimEnd('\').ToLowerInvariant() -eq $target) { $found += $p }
|
||
}
|
||
catch {
|
||
# .Path недоступен (чужой пользователь / процесс уже умер) — считать такой
|
||
# процесс блокирующим нельзя, но и молчать нехорошо: сборка ниже всё равно
|
||
# покажет настоящего держателя файла в тексте MSB3027.
|
||
Write-Verbose "не удалось прочитать путь процесса $($p.Id): $($_.Exception.Message)"
|
||
}
|
||
}
|
||
return $found
|
||
}
|
||
|
||
if ($Check) {
|
||
# Стабильный (не случайный) каталог — чтобы работала инкрементальная сборка.
|
||
# Перенаправляем ТОЛЬКО BaseOutputPath: если увести ещё и BaseIntermediateOutputPath,
|
||
# старый obj\ в дереве остаётся видимым для glob'а и даёт CS0579 «Повторяющийся
|
||
# атрибут» на сгенерированном AssemblyInfo. Обратная сторона — obj\ остаётся общим
|
||
# с обычной сборкой, поэтому два параллельных прогона топчут инкрементальный кэш
|
||
# друг друга (безопасно, но лишняя перекомпиляция).
|
||
$stamp = [System.BitConverter]::ToString(
|
||
[System.Security.Cryptography.SHA256]::HashData(
|
||
[System.Text.Encoding]::UTF8.GetBytes($repo.ToLowerInvariant()))[0..3]).Replace('-', '')
|
||
$out = Join-Path ([System.IO.Path]::GetTempPath()) "kompas-mcp-check\$stamp\"
|
||
|
||
Write-Host "Проверка компиляции (bin не трогаем, выход → $out)" -ForegroundColor Cyan
|
||
dotnet build -c Release -p:BaseOutputPath=$out
|
||
exit $LASTEXITCODE
|
||
}
|
||
|
||
# @() обязательно: единственный найденный процесс вернулся бы скаляром, и .Count под
|
||
# Set-StrictMode падает — та же ловушка, что в лаунчере с Get-ChildItem.
|
||
$blocking = @(Get-BlockingProcess -Directory $binDir)
|
||
if ($blocking.Count -gt 0) {
|
||
Write-Host 'Сборка невозможна: bin занят живыми сессиями MCP.' -ForegroundColor Red
|
||
foreach ($p in $blocking) {
|
||
Write-Host (" PID {0}, запущен {1}" -f $p.Id, $p.StartTime.ToString('HH:mm:ss'))
|
||
}
|
||
Write-Host ''
|
||
Write-Host 'Варианты:' -ForegroundColor Yellow
|
||
Write-Host ' 1. Перевести .mcp.json на tools/dev/launch-dev-mcp.ps1 (теневой запуск) — тогда'
|
||
Write-Host ' bin свободен всегда, и эта ситуация больше не повторится.'
|
||
Write-Host ' 2. Закрыть все сессии Claude Code с этим MCP и повторить.'
|
||
Write-Host ' 3. Разовая проверка компиляции без остановки сервера: -Check'
|
||
exit 2
|
||
}
|
||
|
||
Write-Host 'Сборка (Release)…' -ForegroundColor Cyan
|
||
dotnet build -c Release
|
||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||
|
||
if (-not $NoTest) {
|
||
Write-Host 'Юнит-тесты…' -ForegroundColor Cyan
|
||
dotnet test --filter 'Category=Unit' --nologo
|
||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||
}
|
||
|
||
Import-Module (Join-Path $PSScriptRoot 'KompasMcpDev.psm1') -Force
|
||
$fp = Get-KompasMcpBuildFingerprint -Directory $binDir
|
||
|
||
Write-Host ''
|
||
Write-Host "Готово. Отпечаток сборки: $fp" -ForegroundColor Green
|
||
Write-Host 'Сервер подхватит её при следующем запуске процесса MCP:'
|
||
Write-Host ' /mcp → переподключить kompas (если клиент умеет), иначе — перезапуск сессии.'
|
||
Write-Host 'После переподключения: kompas_status покажет живое соединение; эскизы по id теряются.'
|