The installer inferred that question from whatever the server happened to look like: a MySQL service exists, the database has tables, the site exists, the venv exists. None of those record who created them. A retry after a failed first install was therefore taken for an upgrade of somebody else's working system, which produced two dead ends on exactly the retry the wizard invites: stage 3 demanded a mandatory backup of a database its own failed attempt had written, and then refused to prune tables it had created minutes earlier, because core migration 7d05 seeds access protocols owned by the computers plugin and any profile without that plugin hit the refusal every single time. An install record at ProgramData\ShopDB-Flask\install-state.json answers it instead. It is written when provisioning STARTS rather than when it finishes, because the run that dies halfway is precisely the run whose retry needs it, and it records what this installer created as it goes, so a crashed run no longer leaves the next one guessing from the machine. During unfinished first provisioning the pre-migration backup becomes advisory and prune may force, since every row present was written by an earlier attempt of the same install. On an established install both stay exactly as they were. The classification is deliberately asymmetric: an install predating this record carries a version stamp and probably real data, so it is treated as established and keeps the mandatory backup. Guessing "first run" there would arm prune --force against live tables. Get-CreatedItems comma-protects its return. A zero-length array returned from a PowerShell function unrolls to $null, and $null.Count is fatal under StrictMode 2.0 - the same fault that made bundle verification fail on every install earlier. The harness caught it before it shipped. Tests: deploy/windows/installer/tests/test-install-state.ps1 exercises new servers, retries, completed installs, unrecorded-but-stamped installs, records naming another directory, corrupt records, and persistence across a crash. tests/test_installer_state.py runs it wherever pwsh exists and asserts the invariants as text everywhere else. Both were confirmed to fail when the prune gate or the comma protection is removed. pytest.ini stops collection walking into deploy/windows/installer/bundle, which is build output holding a complete second copy of the application. Importing every plugin twice made SQLAlchemy refuse a redefined table and the whole suite fail to collect, on a tree with nothing wrong in it, purely because an installer had been built first. It surfaced only when the bundle grew from four plugins to thirteen.
29 lines
1001 B
INI
29 lines
1001 B
INI
[pytest]
|
|
# Tests live in tests/. Saying so is not cosmetic.
|
|
#
|
|
# deploy/windows/installer/bundle/ is BUILD OUTPUT: build-installer.sh stages a
|
|
# complete copy of the application there, plugins included. Without this,
|
|
# collection walked into it and imported every plugin a second time under a
|
|
# second path, so SQLAlchemy raised "Table 'printeditems' is already defined for
|
|
# this MetaData instance" and the whole suite failed to collect - on a tree with
|
|
# nothing wrong in it, purely because somebody had built an installer first.
|
|
#
|
|
# It only started biting when the bundle grew from four plugins to thirteen,
|
|
# which is the sort of delay that makes this look like a code fault rather than
|
|
# a stale artefact.
|
|
testpaths = tests
|
|
|
|
# Belt and braces: even an explicit path or an IDE run must not descend into
|
|
# build output or a staged copy of the tree.
|
|
norecursedirs =
|
|
.git
|
|
venv
|
|
.venv
|
|
node_modules
|
|
bundle
|
|
dist
|
|
build
|
|
frontend/dist
|
|
frontend/dist-subpath
|
|
*.egg-info
|