Skip to content

bug(deploy): three more path defects around the backend PYTHONPATH and module symlinks #15560

Closed

Description

@mrveiss

Three findings from the B3/B4 work in PR #15559. All pre-existing, none fixed
there — that PR was scoped to the autobot_shared symlink and the
backend_install_dir meaning, and widening it would have made a deploy-path
change harder to review.

1. ai-stack builds backend-module symlink targets absolutely

autobot-slm-backend/ansible/roles/ai-stack/tasks/main.yml — the
"Create src/ symlinks to backend modules" task builds each src: as an absolute
path under the backend install directory.

Same defect family as B4, but wider: B4 was one well-known link, this is an
arbitrary set of backend modules. A link whose target does not depend on where
the link lives cannot survive the tree moving, which is the property #13539's
release scheme depends on.

  • Targets resolve relative to the link's own directory
  • A test resolves them with realpath under a relocated root, in the style of repo_tests/autobot_shared_symlink_relative_13539_test.py — asserting on the resolved destination, not on the absence of a string

2. fix-backend-environment.yml hand-writes a PYTHONPATH it just rendered

The playbook renders autobot-backend.service.j2 and then, a few lines later,
writes a PYTHONPATH again via lineinfile/shell. Two sources for one value,
which can drift — and the template is the canonical one.

This sits directly on the defect B3 exposed: the same playbook was producing
PYTHONPATH=…:/opt/autobot_shared, a directory that does not exist. #15559 fixed
the rendered value; the hand-written duplicate is still a second, independent
writer of the same setting.

  • Establish whether the hand-written path is needed at all, or is a leftover from before the template covered it
  • If it is needed, it derives from the same variables as the template rather than restating them
  • A test asserts the two agree, or that only one writer exists

3. setup-user-backend.yml defines a variable nothing consumes

backend_shared_dir is defined and never referenced in that file or the role it
invokes. Dead configuration reads as meaningful to whoever edits next.

  • Confirm it is genuinely unconsumed across every playbook and role that could inherit it
  • Remove it, or wire it in if the omission is the actual bug

Evidence

Found while fixing #13539's B3/B4 blockers (PR #15559). The B4 sweep also turned
up three symlink sites the design document had not listed, so the population here
should be assumed larger than these three until swept.

Activity

  1. mrveiss commented on Sep 4, 2026

    @mrveiss
    OwnerAuthor

    Closed on code evidence, verified against merged Dev_new_gui (PR #15602, e1d8b51d).

    Defect Evidence from base
    1 — ai-stack symlink src spelled out Now ../../{{ backend_install_dir | basename }}/{{ item }}; the basename comes from the variable, so the two sibling install dirs cannot drift apart. Proved with real symlinks under tmp_path + os.path.realpath, with the historical absolute form as the contrast case
    2 — two lineinfile writers fighting the template Both removed. grep -c lineinfile returns 2 on the file, and both hits are inside comments recording why they went — no live task. The play now slurps the rendered unit, derives backend_unit_pythonpath (4 uses), and fails if the unit carries none
    3 — backend_shared_dir names a variable no role reads setup-user-backend.yml now uses backend_shared_standalone_dir (2 uses), which is the name roles/backend and roles/autobot_shared actually declare
    Regression guard repo_tests/ansible_backend_path_defects_15560_test.py present in base

    Defect 2 is the one worth recording properly. The two lineinfile tasks rewrote EnvironmentFile= and Environment="PYTHONPATH=..." a few lines after the template had already written both — one setting with two writers that disagreed. That is how this play came to produce a PYTHONPATH entry pointing at a directory that does not exist (#13539/B3). #15559 corrected the rendered value; the hand-written duplicate was a separate, independent writer and survived that fix untouched.

    Removing them is not deletion of working code: the template is confirmed the sole writer of both settings, its single-line output matches the regex the play reads back with, and every downstream consumer — the import test and the summary — was moved onto the derived value in the same change. Verified before removal rather than after.

    Defect 3 was wired in rather than dropped: the play's backend_deployed_root now actually reaches the standalone autobot_shared copy, which the misnamed variable meant it never did.

    The guard generalises the third defect instead of pinning it — every variable setup-user-backend.yml defines must be referenced somewhere in the tree, so the next variable named for a reader that does not exist fails at authoring time.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions