0.1.0
First public release of compose2pod: convert a Docker Compose file into a POSIX sh script that runs its services as a single Podman pod. Extracted from a CI-proven prototype; no prior versions, so nothing to migrate.
Feature
- Compose → single Podman pod.
compose2pod --target <service> --image <ci-image> [file]reads a compose document and emits a shell script that creates one pod (shared network namespace, no bridge), starts dependencies in topological order, gates startup on health by pollingpodman healthcheck run, runs the target service, copies out artifacts, and cleans up via anEXITtrap. - Supported compose subset.
image/build,command,environment/env_file, short-form bindvolumes,healthcheck(CMD / CMD-SHELL),depends_on(service_started/service_healthy/service_completed_successfully), and networkaliases(mapped to--add-host). Anything outside the subset raises a clearUnsupportedComposeError;ports/restart/stdin_open/ttyare ignored with a warning. - CLI and library API. Use the
compose2podcommand (orpython -m compose2pod), or importvalidate,emit_script,EmitOptions, andUnsupportedComposeError. - JSON always, YAML optional. The core reads compose-as-JSON with zero dependencies (
--format json, or pipeyq);pip install compose2pod[yaml]adds direct YAML input.
Why
CI runners often give unprivileged containers a read-only /proc/sys, so netavark can't create bridge networks (upstream declined: podman#20713 closed, netavark#910 unmerged), and there's no systemd to schedule podman healthchecks. docker compose and podman kube play can't work there. A single pod shares one netns (no bridge, no netavark), services reach each other over 127.0.0.1, and health-gated depends_on works via manual podman healthcheck run polling. No existing tool covered that combination.
Packaging
- Published to PyPI via Trusted Publishing:
pip install compose2pod(core, zero runtime dependencies) orpip install compose2pod[yaml](adds PyYAML). requires-python >=3.10,<4; tested on CPython 3.10–3.14. Typed (py.typed). MIT licensed.
Downstream
No action needed — first release, no public API predecessors.
Internals
- 78 tests at 100% line coverage (enforced);
ruff select=ALL,ty, andeof-fixerclean. - One known follow-up is tracked in
planning/deferred.md: hardening the pod-cleanuptrap's nested quoting for the library API path (unreachable from the CLI, which validates pod names).