Servy 8.1 introduces many fixes across main components. The full release notes are available in the expandable section below.
Full Changelog
Click to expand release notes!
- fix(core): Child folder ACLs in %ProgramData%\Servy break multi-account setups (#725)
- fix(service): Partial nginx shutdown leaves orphan process running (#784)
- fix(core): mixed string empty checks: IsNullOrWhiteSpace vs IsNullOrEmpty used interchangeably (#397)
- fix(core): Multiple files - Process.MainModule!.FileName! pattern repeated in 7 locations (follow-up to #724) (#757)
- fix(core): RotatingStreamWriter.cs - Synchronous Thread.Sleep retries during rotation stall stdout/stderr capture (#761)
- fix(core): Post-launch hook missing EnvironmentVariables / Stdout / Stderr / Timeout / Retry / IgnoreFailure — asymmetric with pre-launch (#762)
- fix(core): Servy Event Log - C# code (1000/2000/3000) and PowerShell scripts (9901/9903) use disjoint Event ID ranges on the same source (#764)
- fix(core): AppConfig.cs - ConfigurationAppPublishDebugPath and ManagerAppPublishDebugPath point to Release folders (#768)
- fix(core): AppConfig.cs - Inconsistent relative-path depth across Debug/Release folder constants (#769)
- fix(core): HandleHelper.cs - Silent catch swallows Kill() failure on handle.exe timeout (#771)
- fix(core): Domain/Service.cs - StartupType, Priority, and DateRotationType lack inline default initializers despite sibling properties having them (#776)
- fix(core): ServiceManager.cs - Null-forgiving operator on scmHandle then null check is self-contradictory (#781)
- fix(infra): DapperExecutor.cs - synchronous Thread.Sleep in SQLite busy-retry blocks thread pool (#759)
- fix(infra): DapperExecutor.cs - SpinWait.SpinUntil(() => false, delay) misuses SpinWait as Thread.Sleep (#779)
- fix(service): Fire-and-forget PRESHUTDOWN registration races OnStart failure (#758)
- fix(service): ProcessLauncher.cs - stdout/stderr log flush has no error handling, buffer lost on disk failure (#770)
- fix(service): EnvironmentVariableHelper.cs - MaxExpansionPasses and MaxStringLength hardcoded, should live in AppConfig (#775)
- fix(restarter): database locked on restricted accounts
- fix(desktop): MainViewModel.cs - ConfirmPassword silently overwritten with Password on configuration reload (#782)
- fix(desktop,manager): Export/Import XML vs JSON methods duplicated in both GUI projects (#407)
- fix(desktop,manager): Start/Stop/Restart boilerplate duplicated in both ServiceCommands (#408)
- fix(desktop,manager): MainViewModel.cs - IsManagerAppAvailable snapshotted at ctor, never refreshed (#783)
- fix(desktop,manager,cli): Validation logic triplicated across Servy, Manager, and CLI (#404)
- fix(manager): ConsoleViewModel.cs - LogTailer instances leaked across service switches (no store, no dispose) (#763)
- fix(manager): Strings.resx - Status_StopPending and Status_PausePending display values lack space, inconsistent with sibling statuses (#778)
- fix(psm1): stderr ArrayList capture is unbounded while stdout has a 1 MB cap (asymmetric) (#765)
- fix(notifications): ServyFailureEmail.ps1 - timestamp only persisted on email success causes event storm after SMTP outage (#760)
- fix(tests): ProcessKillerTests.Dispose - cmd cleanup loop has empty body; dead code or missing Kill() (#740)
- fix(tests): LogTailerTests - Hardcoded Task.Delay(300/1000) timing flake risk (#749)
- fix(bump-version): dead else branches in version-format logic (#772)
- fix(publish): docstring example uses -fm but actual parameter is -Tfm (#773)
- fix(bump-runtime): counters use $global: scope, pollute caller session (#774)
- ci(workflows): Multiple workflows - No permissions block, inheriting default read-write token scope (#589)
- ci(scoop): scoop.yml - git config --global injects PAT into runner globally, persists for all subsequent steps (#777)