Repository navigation
fix(deploy): rewrite the AI stack's constraint path at any depth so provisioning completes (#14272) - #14273
Conversation
✅ SSOT Configuration Compliance: Passing🎉 No hardcoded values detected that have SSOT config equivalents! |
|
Two things I checked on this myself before the review lands, both worth recording. The widened pattern changes one existing file's output, and it is a fix rather than a regression. So that file had the same latent defect as the AI stack's: had it ever been installed from a directory at a different depth, pip would have failed the same way. No role installs it through this script today ( The empty-output trap fails loud, not silent. A requirements file consisting only of the That is the safe direction — pip never sees a 0-byte file and "succeeds" installing nothing. Pre-existing behaviour, not introduced here, but it is the failure mode I flagged as a risk in the PR body and it turns out to be already handled. |
Thinking Path
The error names an absolute path nothing in the repo writes:
requirements-ai.txt:25says-c ../../../../constraints/shared.txt, which is correct wherethe file lives — four levels up from
autobot-infrastructure/shared/docker/ai-stack/is therepo root. The role copies it to
/opt/autobot/autobot-ai-stack/and pip-installs it in place,where four levels up is
/.The interesting part is that this was already solved.
scripts/build-filtered-requirements.shexists for exactly this and says so in its own header — "Without this, pip errors on the missing
constraint file" (#11117). The backend role and
services/role_registry.pyboth use it. Theai-stack role never did.
And it would not have worked if it had: the sed matched
^-c \.\./constraints/— literally twodots, the backend's depth. A rewrite that only handles the depth it was written against does not
transfer to its next caller.
What Changed
The rewrite is depth-agnostic:
(\.\./)+for both-cand-r, viased -E.The ai-stack role now runs the canonical script and installs its output, instead of pip-installing
the copied file raw. One implementation, not a second sed — the backend already shares this script
with
role_registry.py, and adding another copy is how the original divergence happened.Verification
13 tests. Mutation-checked:
\.\./patternloop:-driven sourcesRewrite probed directly at depths 1 and 4:
Two defects in my own tests, both worth recording
The invariant test was vacuous. It excluded paths containing
.worktrees/venvby checkingcandidate.partson the absolute path — and it runs from.worktrees/issue-14272/, so everyfile was excluded and the scan reported clean having read nothing. Same shape as the bug it
guards. Fixed by filtering on the path relative to the repo root.
Then it was over-broad. Matching pip targets to repo files by basename flagged four false
offenders, because a hardcoded deploy path like
/opt/autobot/app/requirements.txtcannot betraced back to a source file from the YAML. Narrowed to the mapping the YAML does determine: a
file the same role copies and then pip-installs. That is exactly this bug's shape and cannot
guess.
The third mutation exists because the first version of that narrowed rule read only
src:— theai-stack role uses
src: "{{ item }}"with aloop:, so the scan found no copies and the rulewas vacuously true for the very role this issue is about.
Risks
The AI stack now installs
requirements-ai-filtered.txt. If the rewrite ever produced an emptyfile, pip would install nothing and succeed — worth watching on the first run, though the
constraint line surviving is what the tests pin.
Model Used
Opus 5 (1M context).
Closes #14272