|
| 1 | +--- |
| 2 | +summary: Accept a service-level `profiles:` key instead of hard-rejecting it, by adding it to `IGNORED_SERVICE_KEYS` — it warns and has no effect, because compose2pod's `--target` + `depends_on` closure already fully determines the run set (and targeting a service by name auto-activates its profile, matching Compose). |
| 3 | +--- |
| 4 | + |
| 5 | +# Design: compose profiles |
| 6 | + |
| 7 | +## Summary |
| 8 | + |
| 9 | +Stop hard-rejecting a service-level `profiles:` key. Add `"profiles"` to |
| 10 | +`IGNORED_SERVICE_KEYS` in `compose2pod/parsing.py` so a profiled service is |
| 11 | +accepted, emits `service '<name>': ignoring 'profiles'`, and has no effect on |
| 12 | +the emitted script. This unblocks real-world compose files that tag optional |
| 13 | +services (debug tools, seed jobs) with profiles. |
| 14 | + |
| 15 | +## Motivation |
| 16 | + |
| 17 | +`profiles` is currently in none of the accepted sets (`SERVICE_KEYS`, |
| 18 | +`STRUCTURAL_KEYS`, `IGNORED_SERVICE_KEYS`), so `_validate_service` raises |
| 19 | +`unsupported key 'profiles'` and the whole document fails to convert. Any |
| 20 | +compose file using the common profiles pattern is rejected outright. |
| 21 | + |
| 22 | +Ignoring `profiles` is the *faithful* mapping, not a shortcut, because |
| 23 | +compose2pod's run set is fully determined by `--target` plus its `depends_on` |
| 24 | +closure (`startup_order` in `graph.py`) — there is no `docker compose up`-style |
| 25 | +"start all active services" mode. Two Compose rules make ignoring `profiles` |
| 26 | +correct in that model: |
| 27 | + |
| 28 | +- Targeting a service by name auto-activates its profile (Compose: |
| 29 | + "when you explicitly target a service ... you do not need to enable the |
| 30 | + profile manually"). So `--target X` on a profiled `X` runs `X`, exactly as |
| 31 | + Compose would. |
| 32 | +- A service outside the target's closure never runs regardless of its profile; |
| 33 | + a service inside the closure is a hard `depends_on` dependency that must run. |
| 34 | + Either way, `profiles` changes nothing about what compose2pod emits. |
| 35 | + |
| 36 | +## Design |
| 37 | + |
| 38 | +Single change site: add `"profiles"` to `IGNORED_SERVICE_KEYS` in |
| 39 | +`compose2pod/parsing.py`. `_validate_service` then treats it like `ports`, |
| 40 | +`restart`, `stop_signal`, etc. — accepted, warned, never emitted. No changes to |
| 41 | +`graph.py`, `emit.py`, `store.py`, `keys.py`, or the CLI, and no `--profile` |
| 42 | +flag (in the single-target model it would only add ways to reject valid input, |
| 43 | +since targeting already auto-activates). |
| 44 | + |
| 45 | +`profiles` is not shape-validated, consistent with the other ignored keys and |
| 46 | +because it is never emitted (a malformed value cannot affect output). This |
| 47 | +keeps the change to one line plus its warning, exercised by the existing |
| 48 | +`_validate_service` machinery. |
| 49 | + |
| 50 | +## Non-goals |
| 51 | + |
| 52 | +- A `--profile` / `COMPOSE_PROFILES` activation mechanism — no observable |
| 53 | + effect in the single-target model. |
| 54 | +- Shape-validating `profiles` (a list of strings) — inconsistent with the other |
| 55 | + ignored keys, and pointless for a never-emitted value. |
| 56 | +- Selecting or running services by profile — `--target` + `depends_on` is the |
| 57 | + authoritative run-set selector. |
| 58 | + |
| 59 | +## Divergence |
| 60 | + |
| 61 | +If an active target `depends_on` a member whose profile Compose would leave |
| 62 | +disabled, compose2pod runs it anyway (the closure is authoritative). This |
| 63 | +matches the user's explicit `depends_on` intent and compose2pod's "run the |
| 64 | +target plus its dependency closure" contract; it is *more permissive* than |
| 65 | +Compose, not a silent drop. Recorded in `architecture/supported-subset.md`. |
| 66 | + |
| 67 | +## Testing |
| 68 | + |
| 69 | +`just test-ci` at 100%: |
| 70 | + |
| 71 | +- A service with `profiles: [debug]` is accepted and `validate()` returns the |
| 72 | + warning `service 'debug-tools': ignoring 'profiles'`. |
| 73 | +- The emitted script is byte-identical with and without the `profiles` key on a |
| 74 | + service in the target's closure (profiles has no effect on output). |
| 75 | +- A profiled service *outside* the target's closure does not appear in the |
| 76 | + emitted script (unchanged closure behavior). |
| 77 | +- `--target` naming a profiled service still emits that service. |
| 78 | + |
| 79 | +`just lint-ci` clean and `just check-planning`. |
| 80 | + |
| 81 | +## Risk |
| 82 | + |
| 83 | +Low. The only behavioral change is that a previously-rejected key is now |
| 84 | +accepted-and-ignored. The one semantic subtlety — running a profiled |
| 85 | +`depends_on` member Compose might gate — is documented under Divergence. |
0 commit comments