Skip to content

deploy: dependency rollback is reachable only by hand — no service, task or update path invokes its playbooks #17257

Description

@mrveiss

Corrected 2026-09-22, shortly after filing. This issue originally claimed the
dependency_patching role was "invoked by nothing". That was false. It is invoked by four
playbooks. The original claim came from a grep whose scope was api/*.py, services/*.py and
two named playbooks — a scope that excluded the playbooks that actually call it — and I filed
it without independently verifying the negative. Corrected below to the finding that survives,
which is real but materially narrower. Caught in review on #17241.

What is actually true

autobot-slm-backend/ansible/roles/dependency_patching/ is wired — to playbooks:

Caller
playbooks/patch-dependencies.yml five - role: dependency_patching invocations (phases 1-5, lines 63/75/87/99/111)
playbooks/rollback-dependencies.yml
playbooks/patch-system-packages.yml
playbooks/rollback-system-packages.yml

So the role is not orphaned, and it is not dead code.

The finding that survives

Nothing runs those playbooks. Repo-wide, outside tests:

grep -rn "patch-dependencies|patch_dependencies" --include=*.py autobot-slm-backend/   -> 0
grep -c  dependency_patching  ansible/playbooks/update-all-nodes.yml                   -> 0

No service, no API route, and no scheduled task invokes patch-dependencies.yml or
rollback-dependencies.yml, and the main update path — update-all-nodes.yml — does not include
the role. The capability is reachable only by an operator running a playbook by hand.

That still matters for a rollback mechanism specifically: it is the thing you need at the
moment an update has gone wrong, which is the moment nobody is going to be reading playbooks/
to discover that a manual entry point exists. But "reachable only by hand" is a different and
smaller claim than "invoked by nothing", and the fix is correspondingly smaller.

Acceptance criteria

  • Decide and record whether dependency rollback should be operator-initiated by design, or
    whether the update path should invoke it — either is defensible; the gap is that neither
    was chosen.
  • If it stays manual, the entry point is documented where an operator handling a failed
    update will actually find it, not only in playbooks/.
  • If it becomes automatic, update-all-nodes.yml invokes it and the backup is shown to be
    produced and restored on a real host.
  • Whichever way: an unexercised rollback is the same failure one step later, so it is run at
    least once against a real target.

Method note, because this issue is its own example

The original claim was produced by a grep over a scope that could not see the answer, and the
empty result was read as an absence. docs/developer/MEASUREMENT_DISCIPLINE.md names exactly
this: an instrument answers a narrower question than the one it is read as answering, and the
narrow answer is empty.
Verifying a negative means enumerating where the thing could be
referenced, not grepping where you expect it.

Related

Activity

  1. added this to the v0.9.0 milestone on Sep 22, 2026
  2. changed the title [-]not-wired(ansible): the dependency_patching rollback role is fully implemented and invoked by nothing[/-] [+]deploy: dependency rollback is reachable only by hand — no service, task or update path invokes its playbooks[/+] on Sep 22, 2026
  3. mrveiss commented on Sep 22, 2026

    @mrveiss
    OwnerAuthor

    Closing: not a defect. The premise was wrong three times, and I filed it on the first one.

    dependency_patching is fully wired. Verified references, all read directly:

    Reference
    playbooks/patch-dependencies.yml five - role: dependency_patching invocations, lines 63/75/87/99/111
    playbooks/rollback-dependencies.yml, patch-system-packages.yml, rollback-system-packages.yml role invocations
    ansible/deploy.sh runs both dependency playbooks — patch_dependencies() at :359, run_playbook "patch-dependencies.yml" at :372, "rollback-dependencies.yml" at :388, CLI flags at :491-493, dispatch at :646-649
    autobot-backend/api/settings.py:213 run_system_update_endpoint, an admin route that triggers patch-dependencies.yml as a Celery task

    So there is a role, a playbook layer, an operator CLI and an admin API route. Nothing is orphaned.

    How this issue came to exist

    Three claims, three wrong, each from a grep whose scope could not contain the answer:

    1. "Invoked by nothing" — greps covering api/*.py, services/*.py and two named playbooks. The four playbooks that invoke the role were outside that scope. I filed this issue from that, without verifying the negative.
    2. "Reachable only by hand" — after review corrected (1). This used grep -rn "patch-dependencies|patch_dependencies", and grep treats | literally without -E, so it matched nothing for a reason unrelated to the question. An empty result from a broken instrument, read as an absence.
    3. "four times" — a grep piped through head -4. It is five.

    The one thing that is true: update-all-nodes.yml does not include the role. Given a dedicated patch/rollback CLI and an admin API route, that reads as deliberate separation rather than a gap, and I am not going to file a fourth version of this claim to assert otherwise.

    What is worth keeping

    Not this issue — the method. docs/developer/MEASUREMENT_DISCIPLINE.md already names the failure: an instrument answers a narrower question than the one it is read as answering, and the narrow answer is empty. Three consecutive instances on one claim, each surviving because the output was empty and empty looked like absence. Verifying a negative means enumerating where the thing could be referenced, not grepping where you expect it — and checking the instrument works before trusting its silence.

    Recorded against #17259, which is that rule as a product property.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions