Add a verified deploy script for the worker - #30
Merged
Merged
Conversation
Deploying was eight manual commands in an elevated shell, with three traps: the supervisor has to be stopped before the worker or it resurrects it, a running exe cannot be overwritten, and Start-ScheduledTask is a silent no-op while the task is still marked running. Deploy-FileMill.ps1 avoids all three by leaving the supervisor alone. Windows will not overwrite a running executable but will rename one, so the running binary is renamed aside (becoming the rollback copy), the new build moves into its place, and stopping the worker is enough — the supervisor relaunches it into the new build. Downtime is one restart and Task Scheduler is untouched. Nothing is assumed from an exit code: the new binary must report its version, the old worker must be gone, a new one must appear, and the new version must reach filemill.log. Otherwise the previous binary goes back, the log tail is printed, and it exits non-zero. Worker processes are matched by full path, so a second checkout is never touched. Test-DeployFileMill.ps1 runs it against a stub worker and stub supervisor in a temp directory: one good build, and one that exits at startup to prove the rollback. It needs no elevation and no modules. Build-FileMill.ps1 gains -Output so the deploy can build to a staging name. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The deploy script failed on its first real run, in the elevated 5.1 window it is meant for, while passing the harness under pwsh 7. Two 5.1 differences, both of which the harness now guards: - A string containing an em dash. 5.1 reads a file with no byte-order mark as ANSI, so the em dash decodes to three characters, one of which is a smart quote - and PowerShell accepts smart quotes as string delimiters. It opened a string that never closed and the whole file stopped parsing. The scripts are ASCII-only now, and the harness enforces it. - .Count on the result of Get-Workers. PowerShell unwraps a one-element array on return, and 5.1 answers $null when a lone CimInstance is asked for .Count (it looks for a CIM property of that name). Every worker check therefore read as "no worker running", which in the deploy would mean swapping the binary and never restarting the worker. Every call site wraps in @() now. The harness parses both scripts with both shells before running anything, and its waits report what they saw when they give up - polls made, the path queried, and the process list - which is what finally identified the second bug. It must be run under both shells; only 5.1 showed either of these. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replaces the manual redeploy — eight commands in an elevated shell — with
scripts\Deploy-FileMill.ps1.Why
The manual sequence has three traps:
Start-ScheduledTaskis a silent no-op while the task is still marked running (MultipleInstances IgnoreNew), so a missed check leaves the worker down.How it avoids them
The supervisor is left running. Windows will not overwrite a running exe but it will rename one, so a deploy is:
Downtime is a single worker restart and Task Scheduler is never touched.
Verification and rollback
Nothing is taken from an exit code alone:
filemill.logIf any of that fails, the previous binary goes back, the build that failed is kept as
bin\filemill.failed.exe, the log tail is printed so the cause is visible, and the script exits non-zero. It refuses to run unelevated (the worker runs in session 0) and refuses a dirty working tree unless-AllowDirtyis passed. Worker processes are matched by full executable path, so another checkout's worker is never touched.Tests
scripts\Test-DeployFileMill.ps1runs the deploy against a stub worker and stub supervisor in a temp directory: one good build, and one that exits at startup to prove the rollback and the failure report. 11 checks, no elevation, no modules, and it cannot reach the installed service.Build-FileMill.ps1gains-Outputso the deploy can build to a staging name instead of the running binary.Scope
Operations tooling only. FileMill's Go code is untouched and CI is unchanged.
🤖 Generated with Claude Code