Repository navigation
fix(deploy): code-sync updates the install instead of discarding it (#14275) - #14276
Conversation
Applied Black, isort, and autoflake to match code-quality checks. Triggered by workflow auto-fix-formatting.yml.
|
Self-review before the reviewer landed found a regression I had introduced, and fixed it. The host-state excludes are SOURCE on this path, not host state. I reused Applying them would have made the update silently incomplete — precisely the failure this PR exists to remove, reintroduced by the fix for it. Now only the artifact excludes (
And that test needed two attempts, for the same reason as the last one. Its first version read
447 passed across |
✅ SSOT Configuration Compliance: Passing🎉 No hardcoded values detected that have SSOT config equivalents! |
Applied Black, isort, and autoflake to match code-quality checks. Triggered by workflow auto-fix-formatting.yml.
…on a failed post-sync (#14275)
|
Review found two more real defects, both confirmed against the branch. Fixed in 1. Three roles installed into the wrong interpreter. I fixed ai-stack's to
A bare
2. A failed post-sync was discarded. It now returns success, and a failure stops the sync before the restart and before the DB Mutation-checked, 14 tests, 451 across
On that third row — this is the fourth time in this PR I asserted on text rather than |
Applied Black, isort, and autoflake to match code-quality checks. Triggered by workflow auto-fix-formatting.yml.
|
Line 218 is Hoisted to The 4 remaining violations in that file are on lines this PR does not touch and the job explicitly does not fail on them (#13950 backlog). 451 passed in |
Thinking Path
#14273 fixed the ai-stack's constraint path on the ansible side. This is the code-sync side —
the path an operator actually reaches from the maintenance UI, and the one CLAUDE.md designates as
the only way updates may reach a host.
Chasing the same defect there turned up a worse one. Code-sync is an update procedure: downtime is
expected, discarding the installation is not. It was discarding it.
Problem
1. A sync of ai-stack deleted the live install.
ai_install_diris that same directory. The ansible role builds the venv at<dir>/venv, createssrc/module symlinks, and deploysai_api_server.py,ai_container_main.py,requirements-ai.txtthere. The real sources live underautobot-infrastructure/shared/docker/ai-stack/— not wheresource_pathspointed.So the sync copied one README over the live install in delete mode. Data was never at risk
(ChromaDB is
/var/lib/autobot/chromadb; postgres hassource_paths: []and never syncs at all),but the AI stack needed a full re-provision to come back.
2. A missing source path reported success.
_rsync_source_pathreturnedTrue, "skipped",so a role pointing at a directory absent from the checkout reported a clean sync having copied
nothing — an update that silently did not happen.
3. Three components installed requirements raw.
ai-stack,npu-workerandtts-workerrana bare
pip install -r requirements.txt; both worker files carry a relative-cconstraintinclude. Only
backenddelegated toscripts/build-filtered-requirements.sh— and its own commentat
:124says why: "A barepip install -r requirements.txtwould error on the unresolvableinclude".
What Changed
stale leftover file is far below the cost of deleting a live installation. The ansible syncs keep
it, because theirs do carry the full tree (bug(deploy): resync refusal is all-or-nothing — four host-only paths are not in _PROTECTED_EXCLUDES, so the only way to finish a sync is to delete them #14231).
HOST_STATE_EXCLUDESand the canonical artifact setfrom
services/deploy_artifacts.py— the same vocabularyapi/code_sync.pyuses. This was thethird implementation of the sync and the only one consulting neither.
post_sync_cmds route through the shared rewrite, and ai-stack's now namesrequirements-ai.txt— the file that is actually deployed — and installs into its own venv.source_pathsfor ai-stack points at the real sources.Deliberately unchanged: the two other rsyncs in this file (
_build_rsync_command,_build_local_rsync_command) keep delete mode. They write the git checkout into the sync cache,not onto an install, and already exclude
.git,venv,node_modulesand friends. I checkedthem before assuming they shared the defect; they do not.
Verification
9 new tests; 446 passed across
tests/services/. Mutation-checked:True, "skipped"againThat last row needed a second attempt, and it is the useful one: my first version asserted the
module text contained
HOST_STATE_EXCLUDES, which stayed true after the excludes were deletedfrom the argv, because the import line still named them. It now parses the
rsync_cmdlist andasserts on what is actually built.
test_a_source_path_carries_more_than_a_readmeexists because an existence check would not havecaught this: the placeholder directory was there.
Risks
Without delete mode, a file removed from the repo lingers on the host until the next provisioning
run. That is the deliberate trade — the alternative deleted installations.
Model Used
Opus 5 (1M context).
Closes #14275