From 72d6f84bf768e7a5736ecad6421e4acc9d304fc0 Mon Sep 17 00:00:00 2001 From: Alphaeus Mote Date: Wed, 2 Sep 2026 09:27:35 -0400 Subject: [PATCH 1/3] fix(cli): pin service working directory to the executable dir A service launched by the SCM inherits the manager's working directory (C:\Windows\System32 on Windows), which put the default ./data there. When running non-interactively, chdir to the executable's directory so the database lands beside the installed binary (Program Files\OrchestrAD\data). Interactive and container runs are unaffected. Co-Authored-By: Claude Opus 4.8 --- backend/internal/cli/service.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/backend/internal/cli/service.go b/backend/internal/cli/service.go index 0d02fa1..175c7a3 100644 --- a/backend/internal/cli/service.go +++ b/backend/internal/cli/service.go @@ -32,6 +32,18 @@ type program struct { // Start is called by the service manager (or by Run when interactive). It // launches the server without blocking. func (p *program) Start(s service.Service) error { + // When launched by a service manager the process inherits the manager's + // working directory (e.g. C:\Windows\System32 on Windows), which would put a + // relative ORCHESTRAD_DATA_PATH (default ./data) in the wrong place. Pin the + // working directory to the executable's directory so data lands next to the + // installed binary. Interactive runs (foreground / container) keep the + // caller's working directory and any absolute data path they set. + if !service.Interactive() { + if exe, err := os.Executable(); err == nil { + _ = os.Chdir(filepath.Dir(exe)) + } + } + ctx, cancel := context.WithCancel(context.Background()) p.cancel = cancel p.done = make(chan error, 1) -- 2.52.0 From 46ccb7a92a0046b37628fc1a280189983295cb95 Mon Sep 17 00:00:00 2001 From: Alphaeus Mote Date: Wed, 2 Sep 2026 09:27:36 -0400 Subject: [PATCH 2/3] feat(installer): record version + install dir, preserve database on upgrade Record InstallDir and Version under HKLM\Software\Grace Solutions\OrchestrAD and reuse the install directory on upgrade via a RegistrySearch. Upgrades remove the old product first (stopping the service) then install the new binary and re-initialize, so only binaries change and the runtime data directory (SQLite database) is never touched. Verified: v1->v2 upgrade keeps the DB file and a sentinel intact, service stays healthy. Co-Authored-By: Claude Opus 4.8 --- installer/OrchestrAD.wxs | 65 ++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/installer/OrchestrAD.wxs b/installer/OrchestrAD.wxs index 2c182de..2c3b3f8 100644 --- a/installer/OrchestrAD.wxs +++ b/installer/OrchestrAD.wxs @@ -1,14 +1,23 @@ @@ -23,25 +32,51 @@ - - + + - + - + + + + + + - + - + + + + + + + + + + @@ -52,6 +87,7 @@ Service lifecycle via the binary's own idempotent CLI. Deferred, no-impersonate custom actions run as LocalSystem, which can create/delete services. - Install/upgrade: after the files land, run `initialize` (install + start). + The service migrates the existing database on start, so upgrades keep data. - Uninstall: before the files are removed, run `remove` (stop + delete). --> - + -- 2.52.0 From fc977c7928b951d6282183b0e5b0581fa28f45d8 Mon Sep 17 00:00:00 2001 From: Alphaeus Mote Date: Wed, 2 Sep 2026 09:27:37 -0400 Subject: [PATCH 3/3] ci: pin Go toolchain to local and goversioninfo to v1.7.0 go install goversioninfo@latest pulled a newer Go toolchain (1.26) that mismatched setup-go's 1.24 and broke the resource step. Set GOTOOLCHAIN=local and pin goversioninfo@v1.7.0 so the pinned toolchain builds the pinned tool. Co-Authored-By: Claude Opus 4.8 --- .gitea/workflows/release.yml | 6 +++++- scripts/build.ps1 | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 90caa98..8d4e369 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -33,6 +33,10 @@ jobs: packages: write env: + # Use exactly the toolchain provided by setup-go; never auto-download a + # different Go toolchain (a `go install ...@latest` otherwise pulled a + # newer toolchain that mismatched and broke the build). + GOTOOLCHAIN: local # Optional EXTERNAL registry override. Leave these unset to publish to the # Gitea instance's own built-in container registry (the default below). REGISTRY_HOST: ${{ secrets.REGISTRY_HOST }} @@ -147,7 +151,7 @@ jobs: VHM: ${{ steps.ver.outputs.vhm }} run: | set -euo pipefail - go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@latest + go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@v1.7.0 GV="$(go env GOPATH)/bin/goversioninfo" "$GV" -64 -ver-major="$VY" -ver-minor="$VM" -ver-patch="$VD" -ver-build="$VHM" \ -product-version="$VY.$VM.$VD" -o cmd/orchestrad/resource_windows_amd64.syso versioninfo.json diff --git a/scripts/build.ps1 b/scripts/build.ps1 index 2af431e..1d4c137 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -114,7 +114,8 @@ if ($BuildWindows) { $GoVersionInfo = Join-Path (Join-Path $env:USERPROFILE "go\bin") "goversioninfo.exe" if (-not (Test-Path $GoVersionInfo)) { Write-Host " Installing goversioninfo..." -ForegroundColor Yellow - go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@latest + $env:GOTOOLCHAIN = "local" + go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@v1.7.0 } $vp = $Version -split '\.' Push-Location $BackendDir -- 2.52.0