Skip to content
Draft
Show file tree
Hide file tree
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
113 changes: 64 additions & 49 deletions src/openenv/cli/commands/push.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,64 @@ def _validate_openenv_directory(directory: Path) -> tuple[str, dict]:
return env_name, manifest


def _rewrite_dockerfile_for_space(
dockerfile_content: str,
*,
base_image: str | None,
enable_interface: bool,
) -> tuple[str, list[str]]:
"""Rewrite deployment Dockerfile content and return printed change labels."""
lines = dockerfile_content.split("\n")
new_lines = []
cmd_found = False
base_image_updated = False
web_interface_env_exists = "ENABLE_WEB_INTERFACE" in dockerfile_content
last_instruction = None

for line in lines:
stripped = line.strip()
token = stripped.split(maxsplit=1)[0] if stripped else ""
current_instruction = token.upper()

is_healthcheck_continuation = last_instruction == "HEALTHCHECK"

# Update base image if specified
if base_image and stripped.startswith("FROM") and not base_image_updated:
new_lines.append(f"FROM {base_image}")
base_image_updated = True
last_instruction = "FROM"
continue

if (
stripped.startswith("CMD")
and not cmd_found
and not web_interface_env_exists
and enable_interface
and not is_healthcheck_continuation
):
new_lines.append("ENV ENABLE_WEB_INTERFACE=true")
cmd_found = True

new_lines.append(line)

if current_instruction:
last_instruction = current_instruction

if not cmd_found and not web_interface_env_exists and enable_interface:
new_lines.append("ENV ENABLE_WEB_INTERFACE=true")

if base_image and not base_image_updated:
new_lines.insert(0, f"FROM {base_image}")

changes = []
if base_image and base_image_updated:
changes.append("updated base image")
if enable_interface and not web_interface_env_exists:
changes.append("enabled web interface")

return "\n".join(new_lines), changes


def _get_hf_username() -> str:
"""Return the authenticated Hugging Face username from whoami()."""
username = _extract_hf_username(whoami())
Expand Down Expand Up @@ -323,55 +381,12 @@ def _prepare_staging_directory(
# Modify Dockerfile to optionally enable web interface and update base image
if dockerfile_path and dockerfile_path.exists():
dockerfile_content = dockerfile_path.read_text()
lines = dockerfile_content.split("\n")
new_lines = []
cmd_found = False
base_image_updated = False
web_interface_env_exists = "ENABLE_WEB_INTERFACE" in dockerfile_content
last_instruction = None

for line in lines:
stripped = line.strip()
token = stripped.split(maxsplit=1)[0] if stripped else ""
current_instruction = token.upper()

is_healthcheck_continuation = last_instruction == "HEALTHCHECK"

# Update base image if specified
if base_image and stripped.startswith("FROM") and not base_image_updated:
new_lines.append(f"FROM {base_image}")
base_image_updated = True
last_instruction = "FROM"
continue

if (
stripped.startswith("CMD")
and not cmd_found
and not web_interface_env_exists
and enable_interface
and not is_healthcheck_continuation
):
new_lines.append("ENV ENABLE_WEB_INTERFACE=true")
cmd_found = True

new_lines.append(line)

if current_instruction:
last_instruction = current_instruction

if not cmd_found and not web_interface_env_exists and enable_interface:
new_lines.append("ENV ENABLE_WEB_INTERFACE=true")

if base_image and not base_image_updated:
new_lines.insert(0, f"FROM {base_image}")

dockerfile_path.write_text("\n".join(new_lines))

changes = []
if base_image and base_image_updated:
changes.append("updated base image")
if enable_interface and not web_interface_env_exists:
changes.append("enabled web interface")
dockerfile_content, changes = _rewrite_dockerfile_for_space(
dockerfile_content,
base_image=base_image,
enable_interface=enable_interface,
)
dockerfile_path.write_text(dockerfile_content)
if changes:
console.print(
f"[bold green]✓[/bold green] Updated Dockerfile: {', '.join(changes)}"
Expand Down
27 changes: 27 additions & 0 deletions tests/test_cli/test_push.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import yaml
from openenv.cli.__main__ import app
from openenv.cli.commands.push import _rewrite_dockerfile_for_space
from typer.testing import CliRunner


Expand Down Expand Up @@ -809,6 +810,32 @@ def test_push_handles_base_image_not_found_in_dockerfile(tmp_path: Path) -> None
assert mock_api.upload_folder.called


def test_rewrite_dockerfile_skips_healthcheck_cmd() -> None:
"""Test that web-interface ENV is not inserted before a HEALTHCHECK CMD."""
dockerfile = "\n".join(
[
"FROM openenv-base:latest",
"HEALTHCHECK --interval=30s \\",
" CMD curl -f http://localhost:8000/health || exit 1",
'CMD ["uvicorn", "server.app:app"]',
]
)

rewritten, changes = _rewrite_dockerfile_for_space(
dockerfile,
base_image=None,
enable_interface=True,
)

assert changes == ["enabled web interface"]
assert (
"HEALTHCHECK --interval=30s \\\n"
" CMD curl -f http://localhost:8000/health || exit 1\n"
"ENV ENABLE_WEB_INTERFACE=true\n"
'CMD ["uvicorn", "server.app:app"]'
) in rewritten


def test_push_excludes_files_from_ignore_file(tmp_path: Path) -> None:
"""Test that push excludes files using patterns loaded via --exclude."""
_create_test_openenv_env(tmp_path)
Expand Down
Loading