Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7ee982e
fix(code-sync): remove files deleted from source on every update, nev…
mrveiss Sep 11, 2026
4fbf54f
feat(drift): check every file, name every exclusion (#16310)
mrveiss Sep 11, 2026
94da05b
fix(sync-deletions): never write .deployed_commit, skip host state, s…
mrveiss Sep 11, 2026
d45d11d
fix(deploy): move deletion into the ansible roles themselves (#16310,…
mrveiss Sep 11, 2026
6678fea
fix(deploy): bound the bootstrap enumeration, contain a fleet failure…
mrveiss Sep 11, 2026
cda6b4d
fix(sync-deletions): catch rename-only paths, prove injection resista…
mrveiss Sep 11, 2026
f283914
fix(deploy,drift): re-deliver AC4 via ansible, wire full-tree drift i…
mrveiss Sep 11, 2026
d349ed9
fix(deploy): reach the update path, not just main.yml, for #16310 del…
mrveiss Sep 11, 2026
eace1ed
test(sync-deletions): assert the correct end state, cover slm_manager…
mrveiss Sep 11, 2026
eeba472
fix(drift): stop the source-disk walk from hiding a kept, gitignored …
mrveiss Sep 11, 2026
5958d35
fix(tests): slash-free injection payload, --allow-empty no-op commits…
mrveiss Sep 11, 2026
c3fa66b
fix(tests): site.yml's real path, an unmasked xfail, move two tests u…
mrveiss Sep 11, 2026
11b7265
chore(types): regenerate generated API types from OpenAPI schema(s)
github-actions[bot] Sep 11, 2026
6caf6dc
fix(slm): dash-safe deletion shell, target-side delete list, bootstra…
mrveiss Sep 11, 2026
8d5e02f
fix(tests): expect bootstrap_required in the planner CLI's JSON, and …
mrveiss Sep 11, 2026
0cdd323
fix(slm): cleanup can't abort the fleet, the bootstrap switch is a re…
mrveiss Sep 11, 2026
f326ded
test(slm): no two deletion passes with different sources can share or…
mrveiss Sep 11, 2026
cfd9aba
test(slm): derive every deletion target's landing directory from the …
mrveiss Sep 11, 2026
c3968cb
fix(slm-frontend): the drift panel's helpers accept the readonly data…
mrveiss Sep 11, 2026
e559e61
test(slm-frontend): drift panel fixtures use low-entropy placeholder …
mrveiss Sep 11, 2026
af5ec1c
fix(guards): clear the three guard findings on the sync-deletion bran…
mrveiss Sep 12, 2026
91be31f
Merge remote-tracking branch 'origin/main' into issue-16310-sync-deletes
mrveiss Sep 13, 2026
9ba1e93
Merge remote-tracking branch 'origin/main' into issue-16310-sync-deletes
mrveiss Sep 13, 2026
b6fd5ac
Merge remote-tracking branch 'origin/main' into issue-16310-sync-deletes
mrveiss Sep 13, 2026
3426b6e
fix(config): defer external_url's socket probe past import time (#16262)
mrveiss Sep 13, 2026
331c10f
fix(config): drop @computed_field on external_url, keep it out of dum…
mrveiss Sep 13, 2026
49e3dea
fix(guard): shrink 4 cleared import-hermeticity offenders (#16262)
mrveiss Sep 13, 2026
cb0a3b5
fix(guard): shrink the remaining 47 cleared import-hermeticity offend…
mrveiss Sep 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 169 additions & 0 deletions autobot-slm-backend/ansible/playbooks/update-all-nodes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,61 @@
- autobot-plugins
tags: [slm]

# #16310: `unarchive` above only extracts/overwrites -- it never removes a
# path that dropped out of the tarball because it was deleted from
# source, so deleted modules piled up here forever. One shared task file,
# same contract roles/backend and roles/frontend use.
- name: "[PLAY 1] SLM | Delete files removed from source: slm-backend (#16310)"
ansible.builtin.include_tasks: ../roles/_shared/tasks/sync_deletions.yml
vars:
sync_deletions_label: "SLM Backend (self-update)"
sync_deletions_source_dir: "{{ code_source_dir | default(autobot.base_dir ~ '/code_source') }}/autobot-slm-backend"
sync_deletions_target_dir: "{{ autobot.base_dir }}/autobot-slm-backend"
sync_deletions_owner: autobot
tags: [slm, slm-backend]

- name: "[PLAY 1] SLM | Delete files removed from source: slm-frontend (#16310)"
ansible.builtin.include_tasks: ../roles/_shared/tasks/sync_deletions.yml
vars:
sync_deletions_label: "SLM Frontend (self-update)"
sync_deletions_source_dir: "{{ code_source_dir | default(autobot.base_dir ~ '/code_source') }}/autobot-slm-frontend"
sync_deletions_target_dir: "{{ autobot.base_dir }}/autobot-slm-frontend"
sync_deletions_owner: autobot
tags: [slm, slm-frontend]

- name: "[PLAY 1] SLM | Delete files removed from source: autobot_shared (#16310)"
ansible.builtin.include_tasks: ../roles/_shared/tasks/sync_deletions.yml
vars:
sync_deletions_label: "SLM autobot_shared (self-update)"
sync_deletions_source_dir: "{{ code_source_dir | default(autobot.base_dir ~ '/code_source') }}/autobot_shared"
sync_deletions_target_dir: "{{ autobot.base_dir }}/autobot_shared"
sync_deletions_owner: autobot
tags: [slm, shared]

# #16310 review round 12, N3: `libs` and `autobot-plugins` are unarchived
# above (#15462 -- both frontends resolve `file:` workspace deps into
# these deployed trees) exactly like the three components above, and were
# missing their own deletion pass -- a file dropped from either would
# never be removed from a deployed host, contradicting the PR's own claim
# that deletion runs after every component's sync.
- name: "[PLAY 1] SLM | Delete files removed from source: libs (#16310)"
ansible.builtin.include_tasks: ../roles/_shared/tasks/sync_deletions.yml
vars:
sync_deletions_label: "SLM libs (self-update)"
sync_deletions_source_dir: "{{ code_source_dir | default(autobot.base_dir ~ '/code_source') }}/libs"
sync_deletions_target_dir: "{{ autobot.base_dir }}/libs"
sync_deletions_owner: autobot
tags: [slm, slm-frontend, libs]

- name: "[PLAY 1] SLM | Delete files removed from source: autobot-plugins (#16310)"
ansible.builtin.include_tasks: ../roles/_shared/tasks/sync_deletions.yml
vars:
sync_deletions_label: "SLM autobot-plugins (self-update)"
sync_deletions_source_dir: "{{ code_source_dir | default(autobot.base_dir ~ '/code_source') }}/autobot-plugins"
sync_deletions_target_dir: "{{ autobot.base_dir }}/autobot-plugins"
sync_deletions_owner: autobot
tags: [slm, slm-frontend, plugins]

# #12223 (#12202): the self-update path deploys the SLM backend via the
# unarchive above and never runs the slm_manager role — where the #12202
# marker-write lives — so without this the .deployed_commit marker is never
Expand Down Expand Up @@ -739,6 +794,37 @@
changed_when: true
tags: [backend]

# #16310 review round 6 (reachability): `unarchive` above only
# extracts/overwrites -- it never removes a path deleted from source, and
# this play (not roles/backend/tasks/main.yml) is what the builtin
# updater actually runs for remote backend nodes (#12959 delivery
# contract -- backend's role is applied only via targeted
# `tasks_from`, never in full, so main.yml's own #16310 wiring never
# reaches this host through Update All).
- name: "[PLAY 2] Backend | Delete files removed from source: backend (#16310)"
ansible.builtin.include_tasks: ../roles/_shared/tasks/sync_deletions.yml
vars:
sync_deletions_label: "Backend (fleet update)"
sync_deletions_source_dir: "{{ code_source_dir | default(autobot.base_dir ~ '/code_source') }}/autobot-backend"
sync_deletions_target_dir: /opt/autobot/autobot-backend
sync_deletions_owner: autobot
when: "'backend' in group_names"
tags: [backend]

# AC4 (#16310): same reachability gap as above -- moved to its own task
# file (roles/backend/tasks/npu_workers_cleanup.yml) so it can be applied
# here via `tasks_from`, the #12959-contract way, without dragging the
# rest of the backend role's provisioning (apt, venv, service accounts)
# onto every fleet update.
- name: "[PLAY 2] Backend | Clean up legacy npu_workers.yaml duplicate (#16310)"
ansible.builtin.include_role:
name: backend
tasks_from: npu_workers_cleanup
vars:
backend_code_dir: /opt/autobot/autobot-backend
when: "'backend' in group_names"
tags: [backend]

- name: "[PLAY 2] Backend | Fix shared ownership (#1632)"
file:
path: /opt/autobot/autobot_shared
Expand All @@ -749,6 +835,16 @@
when: "'backend' in group_names"
tags: [backend, shared]

- name: "[PLAY 2] Backend | Delete files removed from source: autobot_shared (#16310)"
ansible.builtin.include_tasks: ../roles/_shared/tasks/sync_deletions.yml
vars:
sync_deletions_label: "Backend autobot_shared (fleet update)"
sync_deletions_source_dir: "{{ code_source_dir | default(autobot.base_dir ~ '/code_source') }}/autobot_shared"
sync_deletions_target_dir: /opt/autobot/autobot_shared
sync_deletions_owner: autobot
when: "'backend' in group_names"
tags: [backend, shared]

- name: "[PLAY 2] Backend | Ensure autobot_shared symlink inside backend dir (#2651)"
ansible.builtin.file:
src: ../autobot_shared
Expand Down Expand Up @@ -1152,6 +1248,20 @@
when: "'frontend' in group_names"
tags: [frontend]

# #16310 review round 6 (reachability): roles/frontend/tasks/main.yml's
# own #16310 wiring only runs when the frontend role is applied in full
# (provisioning), which Update All never does for this component --
# `unarchive` above is the actual deploy mechanism on this path.
- name: "[PLAY 2] Frontend | Delete files removed from source: frontend (#16310)"
ansible.builtin.include_tasks: ../roles/_shared/tasks/sync_deletions.yml
vars:
sync_deletions_label: "Frontend (fleet update)"
sync_deletions_source_dir: "{{ code_source_dir | default(autobot.base_dir ~ '/code_source') }}/autobot-frontend"
sync_deletions_target_dir: /opt/autobot/autobot-frontend
sync_deletions_owner: autobot
when: "'frontend' in group_names"
tags: [frontend]

- name: "[PLAY 2] Frontend | Install Node.js dependencies"
command:
cmd: npm ci --ignore-scripts
Expand Down Expand Up @@ -1213,6 +1323,20 @@
'npu' in group_names
tags: [npu, npu-worker]

# #16310 review round 6 (reachability): same gap as backend/frontend --
# `unarchive` above never deletes, and no npu-worker role's main.yml runs
# on this path.
- name: "[PLAY 2] NPU | Delete files removed from source: npu-worker (#16310)"
ansible.builtin.include_tasks: ../roles/_shared/tasks/sync_deletions.yml
vars:
sync_deletions_label: "NPU worker (fleet update)"
sync_deletions_source_dir: "{{ code_source_dir | default(autobot.base_dir ~ '/code_source') }}/autobot-npu-worker"
sync_deletions_target_dir: /opt/autobot/autobot-npu-worker
sync_deletions_owner: autobot
when: >-
'npu' in group_names
tags: [npu, npu-worker]

- name: "[PLAY 2] NPU | Install Python dependencies"
command:
cmd: /opt/autobot/autobot-npu-worker/venv/bin/pip install
Expand Down Expand Up @@ -1347,6 +1471,18 @@
'browser' in group_names
tags: [browser, browser-worker]

# #16310 review round 6 (reachability): same gap as backend/frontend/npu.
- name: "[PLAY 2] Browser | Delete files removed from source: browser-worker (#16310)"
ansible.builtin.include_tasks: ../roles/_shared/tasks/sync_deletions.yml
vars:
sync_deletions_label: "Browser worker (fleet update)"
sync_deletions_source_dir: "{{ code_source_dir | default(autobot.base_dir ~ '/code_source') }}/autobot-browser-worker"
sync_deletions_target_dir: /opt/autobot/autobot-browser-worker
sync_deletions_owner: autobot
when: >-
'browser' in group_names
tags: [browser, browser-worker]

- name: "[PLAY 2] Browser | Install Python dependencies"
command:
cmd: /opt/autobot/autobot-browser-worker/venv/bin/pip install
Expand Down Expand Up @@ -1487,6 +1623,25 @@
'aiml' in group_names
tags: [ai-stack, aiml]

# #16310 review round 6 (reachability): same gap as the other workers.
# Nonstandard source path (#12450, _NONSTANDARD_COMPONENT_PATHS): this
# component has no top-level code_source/autobot-ai-stack/ -- it lives
# under autobot-infrastructure/ and the archive strips 4 path components
# so its contents land directly under the deployed root, matching
# services/drift_checker.py's override for "autobot-ai-stack".
- name: "[PLAY 2] AI Stack | Delete files removed from source: ai-stack (#16310)"
ansible.builtin.include_tasks: ../roles/_shared/tasks/sync_deletions.yml
vars:
sync_deletions_label: "AI Stack (fleet update)"
sync_deletions_source_dir: >-
{{ (code_source_dir | default(autobot.base_dir ~ '/code_source')) ~
'/autobot-infrastructure/shared/docker/ai-stack' }}
sync_deletions_target_dir: /opt/autobot/autobot-ai-stack
sync_deletions_owner: autobot
when: >-
'aiml' in group_names
tags: [ai-stack, aiml]

- name: "[PLAY 2] AI Stack | Restart autobot-ai-stack service"
systemd:
name: autobot-ai-stack
Expand Down Expand Up @@ -1526,6 +1681,20 @@
when: "'backend' not in group_names"
tags: [shared]

# #16310 review round 6 (reachability): the backend-colocated copy of
# this same component is handled separately, right after "Backend |
# Delete files removed from source: backend" above -- the two `when`
# conditions are mutually exclusive, one marker file per host either way.
- name: "[PLAY 2] Shared | Delete files removed from source: autobot_shared (#16310)"
ansible.builtin.include_tasks: ../roles/_shared/tasks/sync_deletions.yml
vars:
sync_deletions_label: "Shared autobot_shared (fleet update)"
sync_deletions_source_dir: "{{ code_source_dir | default(autobot.base_dir ~ '/code_source') }}/autobot_shared"
sync_deletions_target_dir: /opt/autobot/autobot_shared
sync_deletions_owner: autobot
when: "'backend' not in group_names"
tags: [shared]

# Issue #9225: slm-agent needs autobot_shared in PYTHONPATH
- name: "[PLAY 2] SLM Agent | Create autobot_shared symlink for agent imports"
ansible.builtin.file:
Expand Down
Loading
Loading