131 lines
8.0 KiB
PowerShell
131 lines
8.0 KiB
PowerShell
param(
|
|
[string]$ServerHost = "192.168.3.90",
|
|
[string]$SshUser = "root",
|
|
[string]$SshKeyPath = "$HOME\.ssh\water_audit_ed25519",
|
|
[string]$RemoteProjectPath = "/opt/ai-contract-platform",
|
|
[string]$SharedAiRemoteProjectPath = "/opt/shared-ai-platform-java",
|
|
[string]$ComposeFile = "docker-compose.server.yml",
|
|
[string]$FrontendBaseUrl = "http://192.168.3.90:3003",
|
|
[string]$BackendBaseUrl = "http://192.168.3.90:8001",
|
|
[string]$SharedAiBaseUrl = "http://192.168.3.90:18011",
|
|
[string]$ArtifactRoot = ""
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
$repoRoot = Resolve-Path (Join-Path $PSScriptRoot "..")
|
|
$timestamp = Get-Date -Format "yyyy-MM-ddTHH-mm-ss-fff"
|
|
if ([string]::IsNullOrWhiteSpace($ArtifactRoot)) {
|
|
$ArtifactRoot = Join-Path $repoRoot "project-docs\qa-artifacts\shared-ai-platform-ops-check"
|
|
}
|
|
$artifactDir = Join-Path $ArtifactRoot $timestamp
|
|
$summaryJson = Join-Path $artifactDir "shared-ai-platform-ops-check-summary.json"
|
|
$summaryMd = Join-Path $artifactDir "shared-ai-platform-ops-check-summary.md"
|
|
New-Item -ItemType Directory -Force -Path $artifactDir | Out-Null
|
|
|
|
$checks = New-Object System.Collections.Generic.List[object]
|
|
|
|
function Add-Check {
|
|
param([string]$Key,[string]$Label,[ValidateSet("pass","fail","warn","skip")][string]$Status,[string]$Detail,[bool]$Required=$true,[hashtable]$Meta=@{})
|
|
$checks.Add([ordered]@{ key=$Key; label=$Label; status=$Status; required=$Required; detail=$Detail; meta=$Meta }) | Out-Null
|
|
}
|
|
|
|
function Save-Json {
|
|
param([string]$Path,[object]$Value)
|
|
$Value | ConvertTo-Json -Depth 12 | Set-Content -Encoding UTF8 -Path $Path
|
|
}
|
|
|
|
function Invoke-Remote {
|
|
param([string]$Name,[string]$Command)
|
|
$target = "${SshUser}@${ServerHost}"
|
|
$logPath = Join-Path $artifactDir "$Name.log"
|
|
$args = @("-i",$SshKeyPath,"-o","BatchMode=yes","-o","StrictHostKeyChecking=accept-new","-o","ConnectTimeout=10",$target,$Command)
|
|
$previousErrorActionPreference = $ErrorActionPreference
|
|
$ErrorActionPreference = "Continue"
|
|
try {
|
|
$output = & ssh @args 2>&1
|
|
$exitCode = $LASTEXITCODE
|
|
} finally {
|
|
$ErrorActionPreference = $previousErrorActionPreference
|
|
}
|
|
($output -join [Environment]::NewLine) | Set-Content -Encoding UTF8 -Path $logPath
|
|
return [ordered]@{ exit_code=$exitCode; output=($output -join [Environment]::NewLine); log=$logPath }
|
|
}
|
|
|
|
if (-not (Test-Path "$HOME\.Codex\skills\gstack\bin")) { Add-Check -Key "gstack" -Label "gstack preflight" -Status "fail" -Detail "gstack is missing" } else { Add-Check -Key "gstack" -Label "gstack preflight" -Status "pass" -Detail "GSTACK_OK" }
|
|
if (-not (Test-Path $SshKeyPath)) { Add-Check -Key "ssh_key" -Label "SSH key" -Status "fail" -Detail "SSH key not found: $SshKeyPath" } else { Add-Check -Key "ssh_key" -Label "SSH key" -Status "pass" -Detail "SSH key exists" }
|
|
|
|
$composeProbe = Invoke-Remote -Name "01-compose-ps" -Command "cd $SharedAiRemoteProjectPath && docker compose -f $ComposeFile ps shared-ai-platform-java"
|
|
if ($composeProbe.exit_code -eq 0 -and $composeProbe.output -match 'shared-ai-platform-java' -and $composeProbe.output -match 'Up') {
|
|
Add-Check -Key "compose_ps" -Label "shared-ai compose ps" -Status "pass" -Detail "shared-ai-platform-java is visible and running" -Meta @{ log = $composeProbe.log }
|
|
} else {
|
|
Add-Check -Key "compose_ps" -Label "shared-ai compose ps" -Status "fail" -Detail "shared-ai-platform-java is not visible as an Up service" -Meta @{ log = $composeProbe.log }
|
|
}
|
|
|
|
$sharedHealth = Invoke-Remote -Name "02-shared-health" -Command "curl -fsS http://127.0.0.1:18011/health"
|
|
if ($sharedHealth.exit_code -eq 0 -and $sharedHealth.output -match 'status') { Add-Check -Key "shared_health" -Label "shared-ai /health" -Status "pass" -Detail "shared-ai health responded" -Meta @{ log = $sharedHealth.log } } else { Add-Check -Key "shared_health" -Label "shared-ai /health" -Status "fail" -Detail "shared-ai health probe failed" -Meta @{ log = $sharedHealth.log } }
|
|
|
|
$providerStatus = Invoke-Remote -Name "03-provider-status" -Command "curl -fsS http://127.0.0.1:18011/api/v0.2/system/platform-readiness"
|
|
if ($providerStatus.exit_code -eq 0 -and $providerStatus.output -match 'openai_compatible' -and $providerStatus.output -match 'provider_openai_compatible_enabled\"\s*:\s*true') {
|
|
Add-Check -Key "provider_status" -Label "platform-readiness" -Status "pass" -Detail "platform-readiness confirms openai_compatible is enabled" -Meta @{ log = $providerStatus.log }
|
|
} else {
|
|
Add-Check -Key "provider_status" -Label "platform-readiness" -Status "fail" -Detail "platform-readiness probe failed or openai_compatible is not enabled" -Meta @{ log = $providerStatus.log }
|
|
}
|
|
|
|
$backendHealth = Invoke-Remote -Name "04-backend-health" -Command "curl -fsS http://127.0.0.1:8001/health"
|
|
if ($backendHealth.exit_code -eq 0 -and $backendHealth.output -match 'status') { Add-Check -Key "backend_health" -Label "backend /health" -Status "pass" -Detail "backend health responded" -Meta @{ log = $backendHealth.log } } else { Add-Check -Key "backend_health" -Label "backend /health" -Status "fail" -Detail "backend health probe failed" -Meta @{ log = $backendHealth.log } }
|
|
|
|
$reviewSmokeScript = @"
|
|
set -eu
|
|
cd '$RemoteProjectPath'
|
|
docker compose -f $ComposeFile exec -T backend python - <<'PY'
|
|
import json
|
|
from app.services.review_service import ReviewService
|
|
|
|
service = ReviewService(db=None)
|
|
class StubRepository:
|
|
def __init__(self): self.items={}
|
|
def create(self, obj): self.items[obj.id]=obj; return obj
|
|
def update(self, obj): self.items[obj.id]=obj; return obj
|
|
def get_by_id(self, review_id, tenant_id=None, user_id=None): return self.items.get(review_id)
|
|
service.repository = StubRepository()
|
|
class StubRuleRepo:
|
|
def list_active_for_contract_type(self, tenant_id, contract_type): return []
|
|
service.review_rule_repository = StubRuleRepo()
|
|
class StubReviewResultRepository:
|
|
def __init__(self): self.items={}
|
|
def create(self, obj): self.items[obj.review_task_id]=obj; return obj
|
|
def update(self, obj): self.items[obj.review_task_id]=obj; return obj
|
|
def get_by_review_task_id(self, review_task_id): return self.items.get(review_task_id)
|
|
service.review_result_repository = StubReviewResultRepository()
|
|
class StubFileService: pass
|
|
service.file_service = StubFileService()
|
|
created = service.create_review_task(
|
|
tenant_id='tenant-demo-001',
|
|
user_id='user-admin',
|
|
review_as='party_a',
|
|
contract_type='procurement',
|
|
text='This agreement includes auto-renewal, limitation of liability, payment milestones, confidentiality obligations, and liquidated damages. Please produce a structured legal review result in Chinese.',
|
|
file_name='inline.txt',
|
|
)
|
|
result = service.get_review_result({'id':'user-admin','tenant_id':'tenant-demo-001'}, created['id'])
|
|
assert result['risk_summary']['overall'] != 'low'
|
|
assert result['recommendation'] in {'manual_review', 'proceed_with_revision', 'proceed'}
|
|
print(json.dumps({'created': created, 'result': result}, ensure_ascii=False))
|
|
PY
|
|
"@
|
|
$reviewSmoke = Invoke-Remote -Name "05-review-smoke" -Command $reviewSmokeScript
|
|
if ($reviewSmoke.exit_code -eq 0) { Add-Check -Key "review_smoke" -Label "review smoke" -Status "pass" -Detail "backend can execute review flow against shared-ai-platform" -Meta @{ log = $reviewSmoke.log } } else { Add-Check -Key "review_smoke" -Label "review smoke" -Status "fail" -Detail "backend review smoke failed" -Meta @{ log = $reviewSmoke.log } }
|
|
|
|
$failedRequired = @($checks | Where-Object { $_.required -and $_.status -eq "fail" })
|
|
$overallStatus = if ($failedRequired.Count -gt 0) { "FAIL" } else { "PASS" }
|
|
$summary = [ordered]@{ name="shared-ai-platform-ops-check"; status=$overallStatus; generated_at=(Get-Date).ToUniversalTime().ToString("o"); artifact_dir=$artifactDir; checks=$checks }
|
|
Save-Json -Path $summaryJson -Value $summary
|
|
$markdown = @("# Shared AI Platform Ops Check","","- Status: $overallStatus","- Generated at: $($summary.generated_at)","","## Checks")
|
|
foreach ($check in $checks) { $markdown += "- [$($check.status)] $($check.label): $($check.detail)" }
|
|
$markdown | Set-Content -Encoding UTF8 -Path $summaryMd
|
|
Write-Output $artifactDir
|
|
if ($overallStatus -ne "PASS") {
|
|
exit 2
|
|
}
|