MSI upgrade/data preservation + service data dir + CI toolchain fixes #4
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
+52
-13
@@ -1,14 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
OrchestrAD Windows installer (WiX v4+ / built with WiX 7).
|
||||
OrchestrAD Windows installer (WiX v4+ / built with WiX 5).
|
||||
|
||||
Installs orchestrad.exe to "Program Files\OrchestrAD" and registers +
|
||||
starts the Windows service by invoking the binary's own idempotent
|
||||
`initialize` command. Uninstall runs `remove` (idempotent stop + delete)
|
||||
before the files are deleted, so no orphaned service is left behind.
|
||||
Installs orchestrad.exe to "Program Files\OrchestrAD" and registers + starts
|
||||
the Windows service by invoking the binary's own idempotent `initialize`
|
||||
command. Uninstall runs `remove` (idempotent stop + delete) before the files
|
||||
are deleted, so no orphaned service is left behind.
|
||||
|
||||
Upgrades update only the binaries: the runtime data directory
|
||||
(INSTALLDIR\data, which holds the SQLite database) is created by the app, not
|
||||
by the installer, so MSI never tracks or deletes it. On upgrade the old
|
||||
product is removed first (service stopped + deleted, old binary removed) and
|
||||
the new product then installs the new binary and re-initializes the service,
|
||||
which migrates the preserved database on start. The install location and
|
||||
version are recorded in the registry, and the install directory is reused on
|
||||
upgrade.
|
||||
|
||||
Build:
|
||||
wix build installer/OrchestrAD.wxs \
|
||||
wix build -arch x64 installer/OrchestrAD.wxs \
|
||||
-d Version=<x.y.z> -d BinDir=<dir containing orchestrad.exe> \
|
||||
-d IconPath=<path to orchestrad.ico> -o OrchestrAD.msi
|
||||
-->
|
||||
@@ -23,25 +32,51 @@
|
||||
|
||||
<SummaryInformation Description="OrchestrAD - Active Directory Rule Automation Platform" />
|
||||
|
||||
<!-- Block downgrades; replace older/equal on upgrade. -->
|
||||
<MajorUpgrade DowngradeErrorMessage="A newer version of OrchestrAD is already installed." />
|
||||
<!-- Replace older/equal on upgrade; block downgrades. The default schedule
|
||||
(afterInstallValidate) removes the old product first, so the old
|
||||
service is stopped and deleted and the old binary removed before the
|
||||
new binary installs and re-initializes the service. Only
|
||||
installer-tracked files are touched; the runtime data directory
|
||||
(the database) is never removed. -->
|
||||
<MajorUpgrade
|
||||
DowngradeErrorMessage="A newer version of OrchestrAD is already installed." />
|
||||
|
||||
<MediaTemplate EmbedCab="yes" />
|
||||
|
||||
<!-- Add/Remove Programs metadata. -->
|
||||
<!-- Add/Remove Programs metadata. ProductVersion is recorded by MSI
|
||||
automatically; surface it in ARP alongside the icon. -->
|
||||
<Icon Id="OrchestradIcon" SourceFile="$(IconPath)" />
|
||||
<Property Id="ARPPRODUCTICON" Value="OrchestradIcon" />
|
||||
<Property Id="ARPNOMODIFY" Value="1" />
|
||||
|
||||
<!-- Install tree: Program Files\OrchestrAD -->
|
||||
<!-- On upgrade/repair, reuse the previously recorded install directory so
|
||||
the binary, service, and data stay in one place across versions. On a
|
||||
fresh install this search finds nothing and the default below is used. -->
|
||||
<Property Id="INSTALLDIR">
|
||||
<RegistrySearch Id="FindInstallDir" Root="HKLM"
|
||||
Key="Software\Grace Solutions\OrchestrAD"
|
||||
Name="InstallDir" Type="directory" />
|
||||
</Property>
|
||||
|
||||
<!-- Default install tree: Program Files\OrchestrAD -->
|
||||
<StandardDirectory Id="ProgramFiles64Folder">
|
||||
<Directory Id="INSTALLFOLDER" Name="OrchestrAD" />
|
||||
<Directory Id="INSTALLDIR" Name="OrchestrAD" />
|
||||
</StandardDirectory>
|
||||
|
||||
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
|
||||
<ComponentGroup Id="ProductComponents" Directory="INSTALLDIR">
|
||||
<!-- The application binary. -->
|
||||
<Component Id="OrchestradExe" Bitness="always64">
|
||||
<File Id="OrchestradExe" Name="orchestrad.exe" Source="$(BinDir)/orchestrad.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
|
||||
<!-- Record the install location and product version so upgrades reuse the
|
||||
directory and external tooling can discover both. -->
|
||||
<Component Id="RegistryEntries" Bitness="always64" Guid="7C1E2A64-9B3D-4E1A-9F2B-2D0E6C8A5B10">
|
||||
<RegistryKey Root="HKLM" Key="Software\Grace Solutions\OrchestrAD">
|
||||
<RegistryValue Name="InstallDir" Type="string" Value="[INSTALLDIR]" KeyPath="yes" />
|
||||
<RegistryValue Name="Version" Type="string" Value="$(Version)" />
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
|
||||
<Feature Id="Main" Title="OrchestrAD" Level="1">
|
||||
@@ -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).
|
||||
-->
|
||||
<CustomAction Id="InitializeService"
|
||||
@@ -69,7 +105,10 @@
|
||||
Return="ignore" />
|
||||
|
||||
<InstallExecuteSequence>
|
||||
<!-- Remove the service before its binary is deleted, only when uninstalling. -->
|
||||
<!-- Remove the service before its binary is deleted. This runs both on a
|
||||
plain uninstall and on the old product's removal during an upgrade
|
||||
(REMOVE=ALL in both), so the upgrade stops the old service before the
|
||||
new binary installs and re-initializes it. -->
|
||||
<Custom Action="RemoveService" Before="RemoveFiles" Condition="REMOVE="ALL"" />
|
||||
<!-- Install and start the service after files are present, when not uninstalling. -->
|
||||
<Custom Action="InitializeService" After="InstallFiles" Condition="NOT REMOVE="ALL"" />
|
||||
|
||||
+2
-1
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user