Skip to content

fix: add python3 to spacebot runtime (closes #485) - #31

Merged
shipyard-ci[bot] merged 1 commit into
mainfrom
fix/485-python3-install
Jul 31, 2026
Merged

fix: add python3 to spacebot runtime (closes #485)#31
shipyard-ci[bot] merged 1 commit into
mainfrom
fix/485-python3-install

Conversation

@shipyard-ci

@shipyard-ci shipyard-ci Bot commented Jul 31, 2026

Copy link
Copy Markdown

Fixes marcmantei/shipyard#485 by adding python3 and python3-pip to the
apt-get install list in the spacebot Dockerfile runtime stage, enabling
python execution inside the container as intended by the shipyard#482 shim.

The bug

shipyard#482 added a python PATH shim on the premise that the Debian base
already shipped python3 and merely lacked the python alias. That premise
was wrong for this image.
The runtime stage is debian:bookworm-slim, whose
package list contains no interpreter at all — so the shim had nothing to
delegate into and correctly reported:

$ docker exec spacebot python --version
python: no python3 interpreter on PATH (shim: /usr/local/bin/python)
$ docker exec spacebot find / -maxdepth 4 -iname 'python*' -type f
/usr/local/bin/python   # only the shim script itself

The shim was still worth having — it turned a bare not found into a named
diagnostic. But it could not make Python work, because there was no Python.

Why this is expensive rather than cosmetic: a missing interpreter exits 127,
which reads as "the command failed", not "the command does not exist". Agents
running python -m pytest ... misread that as a red test suite and abandon
correct implementations (shipyard#99).

The fix

python3 + python3-pip in the runtime stage's package list, with a comment
recording why they are load-bearing so a future slimming pass does not drop them
again.

Verification

Built the runtime stage from this branch and exercised it with the shipyard#482
shim in place at /usr/local/bin/python:

check before after
python3 --version not found Python 3.11.2
pip3 --version not found pip 23.0.1
python --version (via shim) exit 127, no python3 interpreter on PATH Python 3.11.2, exit 0
python -m pip --version exit 127 pip 23.0.1, exit 0
issue's own find probe only the shim script /usr/bin/python3.11

command -v resolution confirms no shadowing regression: python
/usr/local/bin/python (shim), python3/usr/bin/python3.

Scope

This is the spacebot source repo's Dockerfile. shipyard PR spacedriveapp#488 applies the
same fix to stack/spacebot/Dockerfile.headless, the deployment recipe the live
spacebot service actually builds. Both need it: spacedriveapp#488 fixes the running
container, this fixes the upstream image so the gap does not reappear on a
rebuild from source.

The runtime stage builds on debian:bookworm-slim, which ships no Python
interpreter at all. shipyard#99/spacedriveapp#482 added a `python` PATH shim on the
premise that the base image already had `python3` and merely lacked the
`python` alias — but there was nothing for the shim to delegate into, so
it correctly reported `no python3 interpreter on PATH` and exited 127.

A missing interpreter surfaces as exit 127, which reads as "the command
failed" rather than "the command does not exist". That is the expensive
part of the bug: agents invoking `python -m pytest ...` misread it as a
red test suite and abandon correct work (shipyard#99).

Verified on the built runtime stage:

  python3 --version            -> Python 3.11.2   (was: not found)
  pip3 --version               -> pip 23.0.1
  python --version (via shim)  -> Python 3.11.2, exit 0
                                  (was: exit 127, "no python3 on PATH")

Refs shipyard#485, shipyard#482, shipyard#99
@shipyard-ci

shipyard-ci Bot commented Jul 31, 2026

Copy link
Copy Markdown
Author

1. Summary

Adds python3 and python3-pip to the apt package list in the Dockerfile so that agent shell tool calls invoking Python don't fail with exit 127 on the debian:bookworm-slim base. The change is a two-line addition to an existing apt-get install --no-install-recommends block, with an explanatory comment.

2. Findings

P2 — python3-pip on bookworm is PEP 668 "externally managed" and will refuse installs

+    python3-pip

Debian 12 (bookworm) ships /usr/lib/python3.11/EXTERNALLY-MANAGED, so a plain pip install X inside this image fails with error: externally-managed-environment rather than installing. If the motivation is "agents invoke Python from shell tool calls" (as the comment states), installing pip without also making it usable — e.g. removing the EXTERNALLY-MANAGED marker, setting PIP_BREAK_SYSTEM_PACKAGES=1, or provisioning a venv — reproduces exactly the class of confusing failure this PR is trying to eliminate: the agent sees a nonzero exit and misreads it. Worth either handling in this PR or dropping python3-pip until it's handled.

P3 — Comment justifies python3 but not python3-pip

+    # python3 — the interpreter agents actually invoke from shell tool calls
+    # (`python3 -m pytest …`, inline scripts). debian:bookworm-slim ships no
...
+    python3 \
+    python3-pip \

The comment block is well written for python3, but python3-pip is silently appended. Given the PEP 668 caveat above, a one-line note on why pip is needed (and how it's expected to be used) would save the next reader a round trip.

P3 — Image size impact not acknowledged

+    python3-pip \

python3-pip pulls in setuptools/wheel and associated data, typically adding on the order of tens of MB even with --no-install-recommends. Fine if intentional; just flagging since the surrounding block is otherwise minimal-runtime-oriented (tini, openssh-server, Chrome shared libs).

Nothing in this diff introduces a crash, data-loss, or API-breaking change. Package pinning is absent, but that matches the existing style of the unchanged lines in this block, so I'm not flagging it.

3. Security

No injection, auth, or secret-handling surface is touched. Two mild notes, neither blocking:

  • Shipping python3-pip in the runtime image gives anything with shell access (including the agent itself) a straightforward path to fetch and execute arbitrary code from PyPI at runtime. If this image runs untrusted-ish agent output, consider build-time-only pip or an index allowlist.
  • Adding an interpreter enlarges the CVE surface of the image; ensure python3 is covered by whatever base-image rebuild/scan cadence already applies.

4. Verdict

COMMENT — the change is small, well motivated, and correctly placed. The one substantive item is the PEP 668 behavior of python3-pip on bookworm: as-is, pip is present but effectively unusable for the stated use case. Confirm that's intended (or handled elsewhere in the image) before merge.


✅ Verification gate (closed-loop Regelkreis · spacedriveapp#58 Phase 1)

An adversarial audit could not ground any blocking finding in the actual diff, so the blocking verdict was downgraded to APPROVE to avoid a false fix cycle (cf. PR spacedriveapp#57/spacedriveapp#48).

Audit

Per-finding audit

P2 — "python3-pip on bookworm is PEP 668 externally-managed; pip install will fail"
PHANTOM

The quoted line does exist in the diff (+ python3-pip \), but existence of the line is not evidence of the alleged defect. The finding asserts a runtime failure (pip install Xerror: externally-managed-environment), yet there is no pip install anywhere in this diff — no RUN pip install, no PIP_* env var, no venv setup, nothing that the PEP 668 marker would block. The diff only adds the package to an apt list; apt-get install python3-pip itself succeeds normally on bookworm.

The finding is also explicitly conditional and intent-speculative in its own text: "If the motivation is…", "Confirm that's intended (or handled elsewhere in the image)". "Handled elsewhere / unclear intent" claims only count when the literal evidence is in the diff, and it is not. Additionally, pip on bookworm remains fully usable via python3 -m venv or --break-system-packages, so no breakage is demonstrated — this is at most an advisory note about a base-image property that predates the PR. Not a should-fix defect grounded in the diff.

P3 — "Comment justifies python3 but not python3-pip"
→ P3 nit; non-blocking by definition. (Lines do exist, but severity does not block.)

P3 — "Image size impact not acknowledged"
→ P3 nit; non-blocking by definition. No measured evidence in the diff either way.

Conclusion

Zero P1 findings were raised. The single P2 finding cannot be grounded in any diff line — it depends on a pip install invocation that does not appear in this change, and is framed conditionally on unverified intent. The remaining two findings are self-labeled P3 nits, which do not block. The diff is a clean two-line addition to an existing apt block with an accurate explanatory comment, correctly continued (python3 \, python3-pip \) and correctly placed inside the --no-install-recommends list.

VERIFIED_VERDICT: APPROVE


AI Review · Verdict: APPROVE · Diff-Score: 0.84
Routed as code_review (100%) → github_code_review_flow · View AI traces

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants