|
| 1 | +--- |
| 2 | +summary: Add two more integration scenarios -- `env_file` (a real file resolved against `project_dir`, loaded into the container's actual environment) and runtime `${VAR}` interpolation (a variable set via `monkeypatch.setenv` just before `run_pod`, proving the reference survives generation as a live shell expansion and podman actually sets it) -- reusing the existing `run_pod` fixture unchanged. |
| 3 | +--- |
| 4 | + |
| 5 | +# Design: grow the integration scenario set (env_file, runtime interpolation) |
| 6 | + |
| 7 | +## Summary |
| 8 | + |
| 9 | +Two more scenarios in `tests/integration/`, continuing the growth started in |
| 10 | +`planning/changes/2026-07-13.02-grow-integration-scenarios.md`. Both reuse the |
| 11 | +`run_pod` fixture from PR #41 unchanged -- no harness, `conftest.py`, |
| 12 | +`pyproject.toml`, or CI changes. Both are behavioral probes (script exit code |
| 13 | ++ stdout), matching every existing scenario. |
| 14 | + |
| 15 | +## Motivation |
| 16 | + |
| 17 | +Two mechanisms remain untested against real podman: `env_file` (a |
| 18 | +compose-authoring convenience that reads a host file and loads it into the |
| 19 | +container's environment via `--env-file`) and `${VAR}` runtime interpolation |
| 20 | +(compose2pod's core design choice to leave `${VAR}` references live in the |
| 21 | +generated script rather than resolving them at generation time, per |
| 22 | +`architecture/supported-subset.md`'s Variable interpolation section). Both |
| 23 | +involve a real podman flag (`--env-file`, `-e`) and a real shell expansion |
| 24 | +step that only a running script can exercise. |
| 25 | + |
| 26 | +## Design |
| 27 | + |
| 28 | +**Scenario 1 -- `env_file`** (`test_env_file.py`): write `app.env` containing |
| 29 | +`COLOR=teal-9\n` to `tmp_path`; the service declares `env_file: "app.env"`; |
| 30 | +`run_pod(..., project_dir=tmp_path)`. Command: `echo "$COLOR"`. Mirrors |
| 31 | +`test_bind_volume.py`'s file-in-`tmp_path` + `project_dir` override shape |
| 32 | +exactly. Proves `--env-file` resolves against `project_dir` |
| 33 | +(`compose2pod/emit.py:_add_env_flags`) and podman actually loads the file |
| 34 | +into the container's real environment. |
| 35 | + |
| 36 | +**Scenario 2 -- runtime `${VAR}` interpolation** (`test_variable_interpolation.py`): |
| 37 | +`monkeypatch.setenv("C2P_IT_TOKEN", <distinctive value>)` before calling |
| 38 | +`run_pod`; the service declares `environment: ["TOKEN=${C2P_IT_TOKEN}"]`; |
| 39 | +command `echo "$TOKEN"`. `run_pod`'s `subprocess.run` call has no explicit |
| 40 | +`env=` override (`tests/integration/conftest.py`), so it inherits the current |
| 41 | +process environment -- exactly the one `monkeypatch` just modified. Exit 0 + |
| 42 | +the distinctive value in stdout proves the full chain for real: the `${VAR}` |
| 43 | +reference survives generation as a live shell expansion (not a baked-in |
| 44 | +literal), `to_shell`'s quoting produces a valid `podman run -e TOKEN=...` |
| 45 | +invocation once the outer script's own shell expands it, and podman correctly |
| 46 | +sets that as the container's actual environment variable. |
| 47 | + |
| 48 | +Both files: no `pytestmark` (the existing `tryfirst` `pytest_collection_modifyitems` |
| 49 | +hook in `conftest.py` auto-marks by location); `Callable[..., PodRun]` typed |
| 50 | +`run_pod` parameter, matching every existing scenario file. |
| 51 | + |
| 52 | +## Non-goals |
| 53 | + |
| 54 | +- Compose's own `.env`-file-at-project-root convention (implicit variable |
| 55 | + defaults) -- out of scope; `env_file:` is the explicit per-service key |
| 56 | + already supported and is what this scenario tests. |
| 57 | +- Multiple `env_file` entries (list form) -- already unit-tested |
| 58 | + (`tests/test_emit.py::test_env_file_list_form`); one file is enough to |
| 59 | + prove the real podman load path. |
| 60 | +- A second interpolation variable / multiple `${VAR}` references in one |
| 61 | + scenario -- one is enough to prove the run-time-expansion mechanism; more |
| 62 | + is unit-test territory (`tests/test_shell.py`), not a new podman-facing risk. |
| 63 | + |
| 64 | +## Testing |
| 65 | + |
| 66 | +`uv run --no-sync pytest -m integration --collect-only -q` collects 8 (the 6 |
| 67 | +existing scenarios plus these 2). `just test-ci` stays at 100% with all 8 |
| 68 | +deselected. `just lint-ci` and `just check-planning` clean. Real signal: the |
| 69 | +`integration` CI job green against real podman, same as every prior round. |
| 70 | + |
| 71 | +## Risk |
| 72 | + |
| 73 | +- **`monkeypatch.setenv` leaking into other tests in the same session** (low |
| 74 | + x low): `monkeypatch` is function-scoped and pytest tears it down |
| 75 | + automatically after the test, so this is a non-issue -- named for |
| 76 | + completeness, not because it's expected to occur. |
| 77 | +- **A CI runner already defining `C2P_IT_TOKEN`** (very low x low): |
| 78 | + vanishingly unlikely given the deliberately distinctive name; not worth |
| 79 | + additional defensive code. |
0 commit comments