-
-
Notifications
You must be signed in to change notification settings - Fork 0
Fix self-hosted help-bot deploy reconciliation #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -34,47 +34,105 @@ jobs: | |||||||||||||||||||||||||||||||||||||
| - name: Build | ||||||||||||||||||||||||||||||||||||||
| run: yarn build | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - name: Copy config and dist | ||||||||||||||||||||||||||||||||||||||
| - name: Sync live tree | ||||||||||||||||||||||||||||||||||||||
| shell: powershell | ||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||
| Copy-Item -Path "config.json" -Destination "C:\game-ci\help-bot\config.json" -Force | ||||||||||||||||||||||||||||||||||||||
| Copy-Item -Path "dist\*" -Destination "C:\game-ci\help-bot\dist\" -Recurse -Force | ||||||||||||||||||||||||||||||||||||||
| $ErrorActionPreference = 'Stop' | ||||||||||||||||||||||||||||||||||||||
| $deployRoot = 'C:\game-ci\help-bot' | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - name: Restart help-bot (kill node so NSSM auto-restarts with new code) | ||||||||||||||||||||||||||||||||||||||
| New-Item -ItemType Directory -Force -Path $deployRoot | Out-Null | ||||||||||||||||||||||||||||||||||||||
| New-Item -ItemType Directory -Force -Path (Join-Path $deployRoot 'dist') | Out-Null | ||||||||||||||||||||||||||||||||||||||
| New-Item -ItemType Directory -Force -Path (Join-Path $deployRoot 'src') | Out-Null | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| robocopy "src" "$deployRoot\src" /MIR /R:2 /W:2 /NFL /NDL /NJH /NJS /NP | ||||||||||||||||||||||||||||||||||||||
| if ($LASTEXITCODE -gt 7) { throw "robocopy src failed with exit code $LASTEXITCODE" } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| robocopy "dist" "$deployRoot\dist" /MIR /R:2 /W:2 /NFL /NDL /NJH /NJS /NP | ||||||||||||||||||||||||||||||||||||||
| if ($LASTEXITCODE -gt 7) { throw "robocopy dist failed with exit code $LASTEXITCODE" } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| foreach ($file in @('package.json', 'yarn.lock', 'tsconfig.json', 'config.json', 'startup.ps1')) { | ||||||||||||||||||||||||||||||||||||||
| Copy-Item -Path $file -Destination (Join-Path $deployRoot $file) -Force | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - name: Repair live install | ||||||||||||||||||||||||||||||||||||||
| shell: powershell | ||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||
| # Get the NSSM child PID for our service | ||||||||||||||||||||||||||||||||||||||
| $nssmPid = (Get-WmiObject Win32_Service -Filter "Name='gameci-help-bot'").ProcessId | ||||||||||||||||||||||||||||||||||||||
| if ($nssmPid -and $nssmPid -ne 0) { | ||||||||||||||||||||||||||||||||||||||
| # Find child node.exe processes of the NSSM wrapper | ||||||||||||||||||||||||||||||||||||||
| $children = Get-WmiObject Win32_Process | Where-Object { $_.ParentProcessId -eq $nssmPid } | ||||||||||||||||||||||||||||||||||||||
| foreach ($child in $children) { | ||||||||||||||||||||||||||||||||||||||
| Write-Host "Killing child process $($child.ProcessId) ($($child.Name))" | ||||||||||||||||||||||||||||||||||||||
| Stop-Process -Id $child.ProcessId -Force -ErrorAction SilentlyContinue | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| # NSSM will auto-restart the child process | ||||||||||||||||||||||||||||||||||||||
| Start-Sleep -Seconds 3 | ||||||||||||||||||||||||||||||||||||||
| $ErrorActionPreference = 'Stop' | ||||||||||||||||||||||||||||||||||||||
| $deployRoot = 'C:\game-ci\help-bot' | ||||||||||||||||||||||||||||||||||||||
| Push-Location $deployRoot | ||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||
| yarn install --frozen-lockfile | ||||||||||||||||||||||||||||||||||||||
| yarn build | ||||||||||||||||||||||||||||||||||||||
| } finally { | ||||||||||||||||||||||||||||||||||||||
| Pop-Location | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - name: Reconcile NSSM service | ||||||||||||||||||||||||||||||||||||||
| shell: powershell | ||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||
| $ErrorActionPreference = 'Stop' | ||||||||||||||||||||||||||||||||||||||
| $serviceName = 'gameci-help-bot' | ||||||||||||||||||||||||||||||||||||||
| $deployRoot = 'C:\game-ci\help-bot' | ||||||||||||||||||||||||||||||||||||||
| $startupScript = Join-Path $deployRoot 'startup.ps1' | ||||||||||||||||||||||||||||||||||||||
| $powershellPath = (Get-Command powershell).Source | ||||||||||||||||||||||||||||||||||||||
| $logFile = Join-Path $deployRoot 'logs\service.log' | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| New-Item -ItemType Directory -Force -Path (Join-Path $deployRoot 'logs') | Out-Null | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| $service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue | ||||||||||||||||||||||||||||||||||||||
| if (-not $service) { | ||||||||||||||||||||||||||||||||||||||
| Write-Host "Installing missing NSSM service" | ||||||||||||||||||||||||||||||||||||||
| nssm install $serviceName $powershellPath "-ExecutionPolicy" "Bypass" "-File" $startupScript | ||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||
| Write-Host "Service not running or PID not found, attempting service start" | ||||||||||||||||||||||||||||||||||||||
| try { Start-Service -Name 'gameci-help-bot' -ErrorAction Stop } catch { | ||||||||||||||||||||||||||||||||||||||
| Write-Host "Cannot start service: $_" | ||||||||||||||||||||||||||||||||||||||
| Write-Host "Reconfiguring existing NSSM service" | ||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||
| nssm stop $serviceName | ||||||||||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||||||||||
| Write-Host "Service stop before reconfigure returned: $_" | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| nssm set $serviceName Application $powershellPath | ||||||||||||||||||||||||||||||||||||||
| nssm set $serviceName AppParameters "-ExecutionPolicy Bypass -File `"$startupScript`"" | ||||||||||||||||||||||||||||||||||||||
| nssm set $serviceName AppDirectory $deployRoot | ||||||||||||||||||||||||||||||||||||||
| nssm set $serviceName AppStdout $logFile | ||||||||||||||||||||||||||||||||||||||
| nssm set $serviceName AppStderr $logFile | ||||||||||||||||||||||||||||||||||||||
| nssm set $serviceName AppStdoutCreationDisposition 1 | ||||||||||||||||||||||||||||||||||||||
| nssm set $serviceName AppStderrCreationDisposition 1 | ||||||||||||||||||||||||||||||||||||||
| nssm set $serviceName Start SERVICE_AUTO_START | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - name: Restart help-bot | ||||||||||||||||||||||||||||||||||||||
| shell: powershell | ||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||
| $ErrorActionPreference = 'Stop' | ||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||
| nssm restart gameci-help-bot | ||||||||||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||||||||||
| Write-Host "NSSM restart failed, trying service start: $_" | ||||||||||||||||||||||||||||||||||||||
| Start-Service -Name 'gameci-help-bot' | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - name: Verify service is running | ||||||||||||||||||||||||||||||||||||||
| shell: powershell | ||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||
| $ErrorActionPreference = 'Stop' | ||||||||||||||||||||||||||||||||||||||
| Start-Sleep -Seconds 8 | ||||||||||||||||||||||||||||||||||||||
| $svc = Get-Service -Name 'gameci-help-bot' -ErrorAction SilentlyContinue | ||||||||||||||||||||||||||||||||||||||
| if ($svc.Status -ne 'Running') { | ||||||||||||||||||||||||||||||||||||||
| Write-Error "Service is not running: $($svc.Status)" | ||||||||||||||||||||||||||||||||||||||
| Get-Content "C:\game-ci\help-bot\logs\service.log" -Tail 30 | ||||||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+118
to
124
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: With $ErrorActionPreference = 'Stop', Write-Error terminates a Windows PowerShell script immediately, and subsequent statements do not run. Citations:
The log tail is unreachable on the failure path. With Proposed fix- if ($svc.Status -ne 'Running') {
- Write-Error "Service is not running: $($svc.Status)"
- Get-Content "C:\game-ci\help-bot\logs\service.log" -Tail 30
- exit 1
- }
+ if (-not $svc -or $svc.Status -ne 'Running') {
+ $status = if ($svc) { $svc.Status } else { 'Missing' }
+ Write-Host "Service is not running: $status"
+ if (Test-Path "C:\game-ci\help-bot\logs\service.log") {
+ Get-Content "C:\game-ci\help-bot\logs\service.log" -Tail 30
+ }
+ throw "gameci-help-bot failed verification"
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| # Verify the node process restarted recently | ||||||||||||||||||||||||||||||||||||||
| $nodes = Get-Process node -ErrorAction SilentlyContinue | Where-Object { $_.StartTime -gt (Get-Date).AddMinutes(-2) } | ||||||||||||||||||||||||||||||||||||||
| if ($nodes) { | ||||||||||||||||||||||||||||||||||||||
| Write-Host "Service is running with fresh node process (PID $($nodes[0].Id), started $($nodes[0].StartTime))" | ||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||
| Write-Host "WARNING: Service is running but node process may not have restarted" | ||||||||||||||||||||||||||||||||||||||
| $app = nssm get gameci-help-bot Application | ||||||||||||||||||||||||||||||||||||||
| $args = nssm get gameci-help-bot AppParameters | ||||||||||||||||||||||||||||||||||||||
| $dir = nssm get gameci-help-bot AppDirectory | ||||||||||||||||||||||||||||||||||||||
| if ($app -notmatch 'powershell(\.exe)?$') { | ||||||||||||||||||||||||||||||||||||||
| Write-Error "Service Application is not PowerShell: $app" | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| if ($args -notmatch 'startup\.ps1') { | ||||||||||||||||||||||||||||||||||||||
| Write-Error "Service AppParameters do not point at startup.ps1: $args" | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| if ($dir.Trim() -ne 'C:\game-ci\help-bot') { | ||||||||||||||||||||||||||||||||||||||
| Write-Error "Service AppDirectory is unexpected: $dir" | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| Write-Host "Service is running with reconciled NSSM configuration" | ||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,5 +1,5 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # startup.ps1 — Auto-update wrapper for NSSM service | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Runs on every service start (including reboot): pulls latest, builds, then starts the bot. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # startup.ps1 — NSSM startup wrapper for deployed help-bot | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Starts from the deployed working tree and performs a minimal repair if runtime artifacts are missing. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $ErrorActionPreference = "Continue" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $repoDir = "C:\game-ci\help-bot" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $logFile = "$repoDir\logs\startup.log" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -14,31 +14,30 @@ New-Item -ItemType Directory -Force -Path "$repoDir\logs" | Out-Null | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log "=== Service starting ===" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Step 1: git pull | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log "Pulling latest from main..." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $pullOutput = git pull origin main 2>&1 | Out-String | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log " git pull: $($pullOutput.Trim())" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log " git pull failed: $_ (continuing with current version)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Step 2: npm ci | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log "Installing dependencies..." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| npm ci 2>&1 | Out-Null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log " npm ci: done" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log " npm ci failed: $_ (continuing with current modules)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Step 3: Build | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log "Building..." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| npm run build 2>&1 | Out-Null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log " Build: done" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log " Build failed: $_ (continuing with existing dist)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $distCli = Join-Path $repoDir "dist\cli.js" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $nodeModulesDir = Join-Path $repoDir "node_modules" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $needsRepair = -not (Test-Path $distCli) -or -not (Test-Path $nodeModulesDir) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ($needsRepair) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log "Runtime artifacts missing; repairing local install..." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log "Installing dependencies..." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| yarn install --frozen-lockfile 2>&1 | Out-Null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log " yarn install: done" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log " yarn install failed: $_" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log "Building..." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| yarn build 2>&1 | Out-Null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log " Build: done" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log " Build failed: $_" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+24
to
+37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: In Windows PowerShell 5.1, non-zero exit codes from native commands like yarn do not trigger try/catch blocks and are not affected by $ErrorActionPreference. These mechanisms handle PowerShell-native errors (terminating or non-terminating with -ErrorAction Stop), but external executables only set Citations:
In PowerShell 5.1, non-zero exit codes from native commands like Proposed fix try {
Log "Installing dependencies..."
yarn install --frozen-lockfile 2>&1 | Out-Null
- Log " yarn install: done"
+ if ($LASTEXITCODE -eq 0) {
+ Log " yarn install: done"
+ } else {
+ Log " yarn install failed with exit code $LASTEXITCODE"
+ }
} catch {
Log " yarn install failed: $_"
}
try {
Log "Building..."
yarn build 2>&1 | Out-Null
- Log " Build: done"
+ if ($LASTEXITCODE -eq 0) {
+ Log " Build: done"
+ } else {
+ Log " Build failed with exit code $LASTEXITCODE"
+ }
} catch {
Log " Build failed: $_"
}📝 Committable suggestion
Suggested change
🧰 Tools🪛 PSScriptAnalyzer (1.25.0)[warning] Missing BOM encoding for non-ASCII encoded file 'startup.ps1' (PSUseBOMForUnicodeEncodedFile) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log "Runtime artifacts present; skipping repair build" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Log "Starting bot..." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
In Windows PowerShell 5.1, do native executables likeyarnandnssmthrow on non-zero exit codes when$ErrorActionPreference = 'Stop'is set, or must scripts check$LASTEXITCODEexplicitly?💡 Result:
In Windows PowerShell 5.1, native executables like yarn and nssm do not throw terminating errors on non-zero exit codes when $ErrorActionPreference = 'Stop' is set. Scripts must check$LASTEXITCODE explicitly (or use $ ?) after calling such executables to detect and handle failures. This behavior is consistent across multiple authoritative sources discussing PowerShell 5.1 error handling. $ErrorActionPreference = 'Stop' makes non-terminating errors from PowerShell cmdlets into terminating errors catchable by try/catch, but external native commands (executables) only set $LASTEXITCODE to the process exit code and $ ? to $false if non-zero; they do not generate PowerShell errors or respect ErrorActionPreference for exit codes. Official docs (about_Preference_Variables) demonstrate the preference working for PowerShell commands like Write-Error, but not external exes. GitHub issue
#3996confirms no terminating error from native non-zero exit even with 'Stop', requiring explicit $LASTEXITCODE checks. Stack Overflow answers (e.g., on call operator, bash set -e equivalent) explicitly state the need to check $LASTEXITCODE -ne 0 and throw manually. This changed in PowerShell 7.4+ with $PSNativeCommandUseErrorActionPreference = $true, but not in 5.1. Example: $ErrorActionPreference = 'Stop' yarn --version # Assume non-zero exit if ($LASTEXITCODE -ne 0) { throw "yarn failed with exit code $LASTEXITCODE" } Write-Host "Continues here only if success" Without the if check, execution continues despite failure.Citations:
🏁 Script executed:
# Check if file exists and get its structure ls -la .github/workflows/deploy.yml wc -l .github/workflows/deploy.ymlRepository: game-ci/help-bot
Length of output: 170
🏁 Script executed:
Repository: game-ci/help-bot
Length of output: 2924
Native command failures won't fail these steps or trigger the fallback.
These
yarnandnssminvocations run undershell: powershell, so non-zero exit codes do not throw. That means the live-repair step can continue after a failed install/build, the NSSM reconciliation can partially fail silently, and thenssm restartcatchblock never runs.Suggested pattern
- name: Repair live install shell: powershell run: | $ErrorActionPreference = 'Stop' $deployRoot = 'C:\game-ci\help-bot' Push-Location $deployRoot try { yarn install --frozen-lockfile + if ($LASTEXITCODE -ne 0) { throw "yarn install failed with exit code $LASTEXITCODE" } yarn build + if ($LASTEXITCODE -ne 0) { throw "yarn build failed with exit code $LASTEXITCODE" } } finally { Pop-Location } … - try { - nssm restart gameci-help-bot - } catch { - Write-Host "NSSM restart failed, trying service start: $_" + nssm restart gameci-help-bot + if ($LASTEXITCODE -ne 0) { + Write-Host "NSSM restart failed, trying service start" Start-Service -Name 'gameci-help-bot' }Apply the same
$LASTEXITCODEguard after eachnssm install,nssm stop,nssm set, andnssm getcall.📝 Committable suggestion
🤖 Prompt for AI Agents