aspect-build / aspect-build/rules_py

[FR]: Expose a stable venv location for non-launcher processes in py_image_layer images

Open
#1,377 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Starlark
Stars
145
Forks
97
Avg merge
1d 1h
Merged PRs (30d)
71

Description

### What's the problem?

`py_image_layer` ships a ready-to-run venv plus a compiled launcher at `/app`. The launcher sets `VIRTUAL_ENV` (and effectively puts the venv on `PATH`) for the process **it** spawns. But there's no stable, documented way for *other* processes in the same container — ones that don't go through the `/app` launcher — to locate or activate that venv.

Real cases where this bites:

- **KubeRay**: runs the head/worker `ray start` command through `bash -lc` (a login shell, whose `/etc/profile` resets `PATH`), and injects an **autoscaler sidecar** with its own `bash -c` command. Neither goes through the app launcher, so neither inherits `VIRTUAL_ENV`/`PATH` — yet both must resolve the venv's `ray` console script.
- **k8s health/readiness probes** exec a binary directly in the container (e.g. `wget … | grep`), independent of the launcher.
- Generally: any sidecar, cron-in-container, or login shell that needs the venv's console scripts / `python`.

Today the only handle is the venv directory's **internal** name — `._.venv/bin` (`py/private/py_venv/py_venv.bzl`, `venv_name = "." + safe_name`) — which consumers must reverse-engineer by globbing:

```sh
VENV_BIN=$(find /app.runfiles -type d -path '*/._*.venv/bin' | head -1)
export PATH="$VENV_BIN:$PATH"
```

That's undocumented and version-coupled: the `._.venv` naming is an implementation detail, and this is an alpha. We hit exactly this (an image entrypoint + a `wget` probe shim both globbing that path); it's the kind of thing a rules_py bump can silently break.

### Proposed

Give `py_image_layer` a **stable, documented** way to locate/activate the venv for non-launcher processes. Any one of:

1. **Image-level env** — have `py_image_layer` set `VIRTUAL_ENV` and prepend `$VIRTUAL_ENV/bin` to `PATH` in the image config `Env`, so *every* process in the container inherits it (the OCI analog of what the launcher already does per-process). Most ergonomic.
2. **Stable symlink** — a documented, stable path (e.g. `/.venv`) → the internal `._.venv`, so consumers reference a stable name instead of globbing.
3. At minimum, **document** the in-image venv-location contract.

### Notes

- Related but distinct: #533 (launcher needing a shell — about execution, not locating the venv from other processes). Same family as #1366 (venv omits wheel `share/` data_files) and #1369 (guidance not to hardcode `py_venv_link`'s venv path).
- Filing before the 2.0.0 stable release, since `._.venv` is currently the only handle.
- Environment: `aspect_rules_py` 2.0.0-alpha.5.

Contributor guide

Open the contributing guide

Research direction

Start by reading py/private/py_venv/py_venv.bzl, especially the venv_name definition, and trace how py_image_layer constructs the image configuration. Decide which proposed stable contract fits the project, then verify that non-launcher processes can locate or activate the venv without depending on the internal name; document the resulting contract and add or update relevant coverage if available.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
build-system
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.