From 5321649e022e798a9743d5d21be6726f7a38d497 Mon Sep 17 00:00:00 2001 From: cproudlock Date: Tue, 4 Aug 2026 10:00:44 -0400 Subject: [PATCH] fix(installer): stop blocking the wizard on things the installer itself installs The preflight page began refusing to continue while any check was failing, which is right for something the operator must go and fix. HttpPlatformHandler was marked FAIL when absent - so on a server without it the wizard stopped dead, telling the operator the server was not ready, over a module the bundle carries and stage 4 installs a few pages later. The only way forward was to go and install by hand the exact thing the installer was about to install. It is now INFO: reported, not blocking, matching how URL Rewrite is already handled. Nothing the installer SUPPLIES may block the wizard, and tests/test_installer_defaults.py now fails if that rule is broken again. The site-port conflict check is downgraded from FAIL to WARN for the same class of reason: it runs before the operator reaches the Address page, so it tests the DEFAULT port rather than the one they intend to use, and blocking refuses an install over a conflict the very next page lets them resolve. Genuine blockers are unchanged - no IIS, no WebAdministration, wrong Windows edition or architecture, no disk, and the MySQL 5.6 index flags. Those the operator really does have to fix first. --- deploy/windows/installer/shopdb-preflight.ps1 | 17 ++++++++--- tests/test_installer_defaults.py | 29 +++++++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/deploy/windows/installer/shopdb-preflight.ps1 b/deploy/windows/installer/shopdb-preflight.ps1 index 5a8c24d..424afe3 100644 --- a/deploy/windows/installer/shopdb-preflight.ps1 +++ b/deploy/windows/installer/shopdb-preflight.ps1 @@ -221,8 +221,12 @@ Invoke-Check 'Network' 'Site port' { Add-Result 'Network' 'Site port' 'INFO' ` "TCP $SitePort is used by the existing $SiteName site - this will be upgraded in place" } else { - Add-Result 'Network' 'Site port' 'FAIL' "TCP $SitePort is in use$owner" ` - "Choose a different port with -SitePort, or stop the listener." + # WARN, not FAIL. This check runs before the operator has reached the + # Address page, so it is testing the DEFAULT port, not necessarily + # the one they intend to use. Blocking here would refuse an install + # over a conflict the very next page lets them resolve. + Add-Result 'Network' 'Site port' 'WARN' "TCP $SitePort is in use$owner" ` + "Pick a different port on the Address page later in this wizard, or stop whatever is holding it." } } } @@ -266,8 +270,13 @@ Invoke-Check 'IIS' 'HttpPlatformHandler' { if ($modules -match 'httpPlatformHandler') { Add-Result 'IIS' 'HttpPlatformHandler' 'PASS' 'installed' } else { - Add-Result 'IIS' 'HttpPlatformHandler' 'FAIL' 'not installed' ` - 'Install httpPlatformHandler_amd64.msi from the bundle. IIS cannot launch waitress without it.' + # NOT a blocker: the MSI is in the bundle and stage 4 installs it. This + # was a FAIL, which - once the preflight page started blocking on any + # failure - stopped the wizard dead over something the installer was + # about to do by itself, with no way forward but to go and install it by + # hand. Nothing the installer SUPPLIES may be a blocker. + Add-Result 'IIS' 'HttpPlatformHandler' 'INFO' 'not installed yet' ` + 'The installer installs it from the bundle. No action needed.' } } diff --git a/tests/test_installer_defaults.py b/tests/test_installer_defaults.py index 1d479eb..a6b39f3 100644 --- a/tests/test_installer_defaults.py +++ b/tests/test_installer_defaults.py @@ -53,3 +53,32 @@ def test_every_wizard_exclusion_is_a_real_plugin(): for name in wizard_excludes(): assert (PLUGINS / name / 'manifest.json').exists(), ( '%s is excluded by the wizard but has no manifest' % name) + + +# The preflight blocks the wizard on any FAIL. That is correct for something the +# operator must go and fix, and wrong for anything the installer carries in its +# own bundle - there, blocking stops the wizard over something it was about to do +# itself, with no way forward. +BUNDLE_SUPPLIED = [ + 'HttpPlatformHandler', # httpplatformhandler\*.msi, installed by stage 4 + 'URL Rewrite', # urlrewrite\*.msi, installed by stage 4 +] + +PREFLIGHT = REPO / 'deploy' / 'windows' / 'installer' / 'shopdb-preflight.ps1' + + +def test_nothing_the_bundle_supplies_is_a_blocker(): + """Regression: HttpPlatformHandler was a FAIL, so a server without it could + not get past the preflight page - to install the very thing that was + missing.""" + text = PREFLIGHT.read_text(encoding='utf-8', errors='replace') + offenders = [] + for line in text.splitlines(): + if "'FAIL'" not in line: + continue + for component in BUNDLE_SUPPLIED: + if component.lower() in line.lower(): + offenders.append(line.strip()) + assert not offenders, ( + 'the installer supplies these, so they must not block the wizard:\n %s' + % '\n '.join(offenders))