G7 증명과 G8 clean-head 승격 준비
This commit is contained in:
parent
94c681d450
commit
5221f79e3f
52 changed files with 6876 additions and 506 deletions
|
|
@ -5,22 +5,121 @@
|
|||
# start-public-runtime.ps1(-SkipWebRestart) 로 필요한 프로세스만 복구한다.
|
||||
# 멱등: 어느 단계든 이미 살아있으면 건드리지 않는다. 수동으로 여러 번 실행해도 안전.
|
||||
#
|
||||
# 등록(로그온 시 자동 실행, 숨김 창):
|
||||
# powershell -NoProfile -ExecutionPolicy Bypass -File scripts\register-boot-task.ps1
|
||||
# 또는 수동:
|
||||
# powershell -NoProfile -ExecutionPolicy Bypass -File scripts\boot-public-runtime.ps1
|
||||
# 등록(로그온 시 자동 실행, 숨김 창)은 register-boot-task.ps1가 생성하는
|
||||
# commit/tree/script SHA pin 인자를 사용한다. 핀 없는 직접 실행은 fail-closed한다.
|
||||
|
||||
param(
|
||||
[string]$Workspace = "D:\workspace\vignette",
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$StableSourceRoot,
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidatePattern("^[0-9a-fA-F]{40}$")]
|
||||
[string]$ExpectedSourceCommit,
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidatePattern("^[0-9a-fA-F]{40}$")]
|
||||
[string]$ExpectedSourceTree,
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidatePattern("^[0-9a-fA-F]{64}$")]
|
||||
[string]$ExpectedBootScriptSha256,
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidatePattern("^[0-9a-fA-F]{64}$")]
|
||||
[string]$ExpectedStartScriptSha256,
|
||||
[string]$DockerDesktop = "C:\Program Files\Docker\Docker\Docker Desktop.exe",
|
||||
[int]$DaemonTimeoutSec = 360,
|
||||
[int]$DbTimeoutSec = 90,
|
||||
[int]$DbPort = 55432,
|
||||
[int]$ApiPort = 8001,
|
||||
[string]$BootLog = "D:\workspace\vignette\boot-public-runtime.log"
|
||||
[string]$BootLog = ""
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Continue" # 부트 스크립트는 끝까지 로깅하고 종료한다.
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$resolvedSourceRoot = (Resolve-Path -LiteralPath $StableSourceRoot).Path
|
||||
$expectedBootScript = Join-Path $resolvedSourceRoot "scripts\boot-public-runtime.ps1"
|
||||
$startScript = Join-Path $resolvedSourceRoot "scripts\start-public-runtime.ps1"
|
||||
|
||||
function Invoke-GitText {
|
||||
param([string[]]$Arguments)
|
||||
|
||||
$value = & git.exe -C $resolvedSourceRoot @Arguments
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Stable source Git command failed (exit=$LASTEXITCODE): git $($Arguments -join ' ')"
|
||||
}
|
||||
return (@($value) -join [Environment]::NewLine).Trim()
|
||||
}
|
||||
|
||||
function Assert-StableSourceProvenance {
|
||||
foreach ($requiredScript in @($expectedBootScript, $startScript)) {
|
||||
if (-not (Test-Path -LiteralPath $requiredScript -PathType Leaf)) {
|
||||
throw "Pinned public runtime script not found at $requiredScript"
|
||||
}
|
||||
}
|
||||
|
||||
$runningBootScript = (Resolve-Path -LiteralPath $PSCommandPath).Path
|
||||
if (-not [string]::Equals(
|
||||
$runningBootScript,
|
||||
(Resolve-Path -LiteralPath $expectedBootScript).Path,
|
||||
[System.StringComparison]::OrdinalIgnoreCase
|
||||
)) {
|
||||
throw "Boot recovery is not executing from the pinned stable source root"
|
||||
}
|
||||
|
||||
$gitRoot = Invoke-GitText -Arguments @("rev-parse", "--show-toplevel")
|
||||
$resolvedGitRoot = (Resolve-Path -LiteralPath $gitRoot).Path
|
||||
if (-not [string]::Equals(
|
||||
$resolvedGitRoot,
|
||||
$resolvedSourceRoot,
|
||||
[System.StringComparison]::OrdinalIgnoreCase
|
||||
)) {
|
||||
throw "Stable source root does not match its Git toplevel"
|
||||
}
|
||||
|
||||
$symbolicHead = & git.exe -C $resolvedSourceRoot symbolic-ref --quiet HEAD
|
||||
$symbolicHeadExit = $LASTEXITCODE
|
||||
if ($symbolicHeadExit -eq 0) {
|
||||
throw "Stable source must be a detached HEAD, not branch $symbolicHead"
|
||||
}
|
||||
if ($symbolicHeadExit -ne 1) {
|
||||
throw "Could not prove detached HEAD (git exit=$symbolicHeadExit)"
|
||||
}
|
||||
|
||||
$actualCommit = Invoke-GitText -Arguments @("rev-parse", "--verify", "HEAD")
|
||||
$actualTree = Invoke-GitText -Arguments @("rev-parse", "--verify", "HEAD^{tree}")
|
||||
if ($actualCommit -ne $ExpectedSourceCommit.ToLowerInvariant()) {
|
||||
throw "Stable source commit drift: expected=$ExpectedSourceCommit actual=$actualCommit"
|
||||
}
|
||||
if ($actualTree -ne $ExpectedSourceTree.ToLowerInvariant()) {
|
||||
throw "Stable source tree drift: expected=$ExpectedSourceTree actual=$actualTree"
|
||||
}
|
||||
|
||||
$dirty = Invoke-GitText -Arguments @("status", "--porcelain=v1", "--untracked-files=normal")
|
||||
if ($dirty) {
|
||||
throw "Stable source is not clean; refusing boot recovery"
|
||||
}
|
||||
foreach ($relativePath in @(
|
||||
"scripts/boot-public-runtime.ps1",
|
||||
"scripts/start-public-runtime.ps1"
|
||||
)) {
|
||||
Invoke-GitText -Arguments @("ls-files", "--error-unmatch", "--", $relativePath) | Out-Null
|
||||
}
|
||||
|
||||
$actualBootScriptSha256 = (Get-FileHash -LiteralPath $expectedBootScript -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||
$actualStartScriptSha256 = (Get-FileHash -LiteralPath $startScript -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||
if ($actualBootScriptSha256 -ne $ExpectedBootScriptSha256.ToLowerInvariant()) {
|
||||
throw "Pinned boot script SHA256 drift"
|
||||
}
|
||||
if ($actualStartScriptSha256 -ne $ExpectedStartScriptSha256.ToLowerInvariant()) {
|
||||
throw "Pinned start script SHA256 drift"
|
||||
}
|
||||
}
|
||||
|
||||
# Docker/DB/process mutation보다 먼저 stable source를 매 실행 재검증한다.
|
||||
Assert-StableSourceProvenance
|
||||
|
||||
if (!$BootLog) {
|
||||
$BootLog = Join-Path $resolvedSourceRoot "boot-public-runtime.log"
|
||||
}
|
||||
|
||||
$ErrorActionPreference = "Continue" # provenance 이후 부트 복구는 끝까지 로깅한다.
|
||||
|
||||
function Write-BootLog([string]$Message) {
|
||||
$line = "[{0}] {1}" -f (Get-Date -Format "yyyy-MM-dd HH:mm:ss"), $Message
|
||||
|
|
@ -121,13 +220,10 @@ Write-BootLog "postgres 127.0.0.1:$DbPort up"
|
|||
if ((Test-ApiControlPlaneHealthy) -and (Test-EngineHealthy)) {
|
||||
Write-BootLog "control plane and engine already healthy; skipping runtime restart"
|
||||
} else {
|
||||
$pub = Join-Path $Workspace "scripts\start-public-runtime.ps1"
|
||||
if (-not (Test-Path -LiteralPath $pub)) {
|
||||
Write-BootLog "ERROR: start-public-runtime.ps1 not found at $pub"
|
||||
exit 1
|
||||
}
|
||||
Write-BootLog "running start-public-runtime.ps1 -SkipWebRestart"
|
||||
$out = & powershell.exe -NoProfile -ExecutionPolicy Bypass -File $pub -SkipWebRestart 2>&1
|
||||
$out = & powershell.exe -NoProfile -ExecutionPolicy Bypass -File $startScript `
|
||||
-Workspace $resolvedSourceRoot `
|
||||
-SkipWebRestart 2>&1
|
||||
$out | ForEach-Object { Write-BootLog (" pub> " + $_) }
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-BootLog "ERROR: start-public-runtime.ps1 exit $LASTEXITCODE"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue