Skip to content

feat: add recursive discovery of compose files up to 10 levels #1268

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 58 additions & 2 deletions podman_compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -1975,6 +1975,45 @@ def dotenv_to_dict(dotenv_path: str) -> dict[str, str | None]:
]


def find_compose_files_recursively(
start_dir: str, compose_files: list[str], max_depth: int = 10
) -> tuple[list[str], str] | None:
"""
Search for compose files recursively up the directory tree.

Args:
start_dir: Directory to start searching from
compose_files: List of compose file names to search for
max_depth: Maximum depth

Returns:
A tuple (found_files, base_directory) or None if no files found
"""
current_dir = os.path.abspath(start_dir)

for depth in range(max_depth):
# Search for compose files in current directory
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obvious comment

found_files = []
for compose_file in compose_files:
file_path = os.path.join(current_dir, compose_file)
if os.path.exists(file_path):
found_files.append(file_path)

if found_files:
log.debug("Found compose files in %s: %s", current_dir, found_files)
return found_files, current_dir

parent_dir = os.path.dirname(current_dir)

# If we've reached the root directory, stop searching
if parent_dir == current_dir:
break

current_dir = parent_dir

return None


class PodmanCompose:
class XPodmanSettingKey(Enum):
DOCKER_COMPOSE_COMPAT = "docker_compose_compat"
Expand Down Expand Up @@ -2169,13 +2208,30 @@ def _parse_compose_file(self) -> None:
if project_dir and os.path.isdir(project_dir):
os.chdir(project_dir)
pathsep = os.environ.get("COMPOSE_PATH_SEPARATOR", os.pathsep)

if not args.file:
default_str = os.environ.get("COMPOSE_FILE")
if default_str:
default_ls = default_str.split(pathsep)
args.file = list(filter(os.path.exists, default_ls))
else:
default_ls = COMPOSE_DEFAULT_LS
args.file = list(filter(os.path.exists, default_ls))
# Recursive search up the directory tree
current_working_dir = os.getcwd()
log.debug("Starting compose file search from directory: %s", current_working_dir)
result = find_compose_files_recursively(current_working_dir, COMPOSE_DEFAULT_LS)

if result:
found_files, base_dir = result
args.file = found_files
# Change to the directory where compose files were found
log.info("Found compose files in: %s", base_dir)
log.info("Changing working directory to: %s", base_dir)
os.chdir(base_dir)
else:
# Fallback to original behavior if no files found
default_ls = COMPOSE_DEFAULT_LS
args.file = list(filter(os.path.exists, default_ls))

files = args.file
if not files:
log.fatal(
Expand Down
Loading