Files
Investidor-V2/tools/portal-workflow-activation-apache-reload.ps1
nala 287e991486
tests / ci (push) Waiting to run
oportunidades 7
2026-10-13 11:40:29 +02:00

46 lines
4.1 KiB
PowerShell

# Exact Apache instance graceful reload; no termination, service registration or QA control.
# Apache 2.4.54 uses ap<parent PID>_restart for graceful Windows restarts.
# https://github.com/apache/httpd/blob/2.4.54/server/mpm/winnt/mpm_winnt.c#L144-L242
param([switch]$Apply)
$ErrorActionPreference='Stop'
$taskRoot='C:\laragon\www\portal-investidor'
$taskPrivate=Join-Path $taskRoot 'storage\app\private\investmoz-v2\portal-audit'
$revision='41caea0f900fe0705e84e065a65f9534ff3a585ee34098f860666f522875a3a5'
$apacheRoot='C:\laragon\bin\apache\httpd-2.4.54-win64-VS16'
$exe=Join-Path $apacheRoot 'bin\httpd.exe'
$configuration=Join-Path $apacheRoot 'conf\httpd.conf'
$vhost='C:\laragon\etc\apache2\sites-enabled\portal-investidor.test.conf'
$parent=Get-CimInstance Win32_Process -Filter 'ProcessId=6108'
if(-not $parent -or $parent.ExecutablePath -ne $exe -or $parent.CreationDate.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss') -ne '2026-10-11T10:33:16' -or $parent.CommandLine -notlike '*-f C:/laragon/bin/apache/httpd-2.4.54-win64-VS16/conf/httpd.conf*'){throw 'Exact authorized portal Apache instance differs; no signal sent'}
if(([IO.File]::ReadAllText((Join-Path $apacheRoot 'logs\httpd.pid'))).Trim() -ne '6108'){throw 'Apache PID file differs'}
if((Get-FileHash -LiteralPath $vhost -Algorithm SHA256).Hash.ToLowerInvariant() -ne 'a62c5d000e4313b21c89423303dd277ee7ce98eedd0de94f9d32b4246297f9ec'){throw 'Staged authorized vhost differs'}
$stage=Get-Content -LiteralPath (Join-Path $taskPrivate 'workflow-activation-stage.json') -Raw -Encoding UTF8|ConvertFrom-Json
if($stage.revision -ne $revision -or $stage.authenticated_schema_installed -or $stage.bootstrap_executed){throw 'Unexpected activation stage'}
$before=@(Get-CimInstance Win32_Process -Filter 'Name="httpd.exe"'|Where-Object {$_.ParentProcessId -eq 6108}|Select-Object -ExpandProperty ProcessId)
if($before.Count -ne 1 -or $before[0] -ne 10812){throw 'Exact original child differs; inspect before any signal'}
$phpDirectory='C:\laragon\bin\php\php-8.5.11-Win32-vs17-x64'
$env:PATH=$phpDirectory+';'+$env:PATH
$syntaxProcess=Start-Process -FilePath $exe -ArgumentList @('-d',$apacheRoot,'-f',$configuration,'-t') -WindowStyle Hidden -Wait -PassThru -RedirectStandardOutput (Join-Path $taskPrivate 'workflow-activation-apache-reload-syntax.stdout.log') -RedirectStandardError (Join-Path $taskPrivate 'workflow-activation-apache-reload-syntax.stderr.log')
if($syntaxProcess.ExitCode -ne 0){throw 'Apache syntax invalid; no signal sent'}
$event=[Threading.EventWaitHandle]::OpenExisting('ap6108_restart',[Security.AccessControl.EventWaitHandleRights]::Modify)
$receipt=@{at=[DateTime]::UtcNow.ToString('o');revision=$revision;parent_pid=6108;previous_child=10812;mechanism='Apache own graceful Windows restart event';normal_Laragon_control_did_not_reload_manual_instance=$true;scope='portal Apache only; QA Apache, PostgreSQL, schema, data and keys untouched';signal_sent=$false;syntax_passed=$true;new_child_pid=$null}
try{
if($Apply){
if(-not $event.Set()){throw 'Apache restart event not accepted'}
$receipt.signal_sent=$true
$deadline=[DateTime]::UtcNow.AddSeconds(55)
do{
Start-Sleep -Milliseconds 500
$children=@(Get-CimInstance Win32_Process -Filter 'Name="httpd.exe"'|Where-Object {$_.ParentProcessId -eq 6108 -and $_.ExecutablePath -eq $exe -and $_.ProcessId -ne 10812})
if($children.Count -eq 1 -and -not (Get-Process -Id 10812 -ErrorAction SilentlyContinue)){break}
}while([DateTime]::UtcNow -lt $deadline)
if($children.Count -ne 1 -or (Get-Process -Id 10812 -ErrorAction SilentlyContinue)){throw 'Graceful restart not observed within bounded window; do not terminate processes'}
$receipt.new_child_pid=$children[0].ProcessId
$receipt.result='graceful_reload_observed_pending_web_verification'
}else{$receipt.result='exact_instance_and_own_restart_event_verified_no_signal'}
}finally{
$event.Dispose()
[IO.File]::WriteAllText((Join-Path $taskPrivate $(if($Apply){'workflow-activation-apache-reload.json'}else{'workflow-activation-apache-reload-preparation.json'})),($receipt|ConvertTo-Json -Depth 5),[Text.UTF8Encoding]::new($false))
}
$receipt|ConvertTo-Json -Depth 5