Skip to content
Merged
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
16 changes: 14 additions & 2 deletions comfy_cli/command/custom_nodes/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,13 @@
signed_url = response.signedUrl
zip_filename = NODE_ZIP_FILENAME
typer.echo("Creating zip file...")
zip_files(zip_filename)

includes = config.tool_comfy.includes if config and config.tool_comfy else []

if includes:
typer.echo(f"Including additional directories: {', '.join(includes)}")

zip_files(zip_filename, includes=includes)

# Upload the zip file to the signed URL
typer.echo("Uploading zip file...")
Expand Down Expand Up @@ -917,7 +923,13 @@
raise typer.Exit(code=1)

zip_filename = NODE_ZIP_FILENAME
zip_files(zip_filename)
includes = config.tool_comfy.includes if config and config.tool_comfy else []

Check warning on line 926 in comfy_cli/command/custom_nodes/command.py

View check run for this annotation

Codecov / codecov/patch

comfy_cli/command/custom_nodes/command.py#L926

Added line #L926 was not covered by tests

if includes:
typer.echo(f"Including additional directories: {', '.join(includes)}")

Check warning on line 929 in comfy_cli/command/custom_nodes/command.py

View check run for this annotation

Codecov / codecov/patch

comfy_cli/command/custom_nodes/command.py#L928-L929

Added lines #L928 - L929 were not covered by tests

zip_files(zip_filename, includes=includes)

Check warning on line 931 in comfy_cli/command/custom_nodes/command.py

View check run for this annotation

Codecov / codecov/patch

comfy_cli/command/custom_nodes/command.py#L931

Added line #L931 was not covered by tests

typer.echo(f"Created zip file: {NODE_ZIP_FILENAME}")
logging.info("Node has been packed successfully.")

Expand Down
62 changes: 42 additions & 20 deletions comfy_cli/file_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,39 +88,61 @@
raise DownloadException(f"Failed to download file.\n{status_reason}")


def zip_files(zip_filename):
def zip_files(zip_filename, includes=None):
"""
Zip all files in the current directory that are tracked by git.
Zip all files in the current directory that are tracked by git,
plus any additional directories specified in includes.
"""
includes = includes or []
included_paths = set()
git_files = []

Check warning on line 98 in comfy_cli/file_utils.py

View check run for this annotation

Codecov / codecov/patch

comfy_cli/file_utils.py#L96-L98

Added lines #L96 - L98 were not covered by tests

try:
# Get list of git-tracked files using git ls-files
import subprocess

git_files = subprocess.check_output(["git", "ls-files"], text=True).splitlines()
# Zip only git-tracked files
with zipfile.ZipFile(zip_filename, "w", zipfile.ZIP_DEFLATED) as zipf:
except (subprocess.SubprocessError, FileNotFoundError):
print("Warning: Not in a git repository or git not installed. Zipping all files.")

Check warning on line 105 in comfy_cli/file_utils.py

View check run for this annotation

Codecov / codecov/patch

comfy_cli/file_utils.py#L104-L105

Added lines #L104 - L105 were not covered by tests

# Zip only git-tracked files
with zipfile.ZipFile(zip_filename, "w", zipfile.ZIP_DEFLATED) as zipf:
if git_files:

Check warning on line 109 in comfy_cli/file_utils.py

View check run for this annotation

Codecov / codecov/patch

comfy_cli/file_utils.py#L108-L109

Added lines #L108 - L109 were not covered by tests
for file_path in git_files:
if zip_filename in file_path:
continue
if os.path.exists(file_path):
zipf.write(file_path)
included_paths.add(file_path)

Check warning on line 115 in comfy_cli/file_utils.py

View check run for this annotation

Codecov / codecov/patch

comfy_cli/file_utils.py#L115

Added line #L115 was not covered by tests
else:
print(f"File not found. Not including in zip: {file_path}")
return
except (subprocess.SubprocessError, FileNotFoundError):
print("Warning: Not in a git repository or git not installed. Zipping all files.")

with zipfile.ZipFile(zip_filename, "w", zipfile.ZIP_DEFLATED) as zipf:
for root, dirs, files in os.walk("."):
if ".git" in dirs:
dirs.remove(".git")
for file in files:
file_path = os.path.join(root, file)
# Skip zipping the zip file itself
if zip_filename in file_path:
continue
relative_path = os.path.relpath(file_path, start=".")
zipf.write(file_path, relative_path)
else:
for root, dirs, files in os.walk("."):
if ".git" in dirs:
dirs.remove(".git")
for file in files:
file_path = os.path.join(root, file)

Check warning on line 123 in comfy_cli/file_utils.py

View check run for this annotation

Codecov / codecov/patch

comfy_cli/file_utils.py#L119-L123

Added lines #L119 - L123 were not covered by tests
# Skip zipping the zip file itself
if zip_filename in file_path:
continue
relative_path = os.path.relpath(file_path, start=".")
zipf.write(file_path, relative_path)
included_paths.add(file_path)

Check warning on line 129 in comfy_cli/file_utils.py

View check run for this annotation

Codecov / codecov/patch

comfy_cli/file_utils.py#L125-L129

Added lines #L125 - L129 were not covered by tests

for include_dir in includes:
include_dir = include_dir.lstrip("/")
if not os.path.exists(include_dir):
print(f"Warning: Included directory '{include_dir}' does not exist, creating empty directory")
zipf.writestr(f"{include_dir}/", "")
continue

Check warning on line 136 in comfy_cli/file_utils.py

View check run for this annotation

Codecov / codecov/patch

comfy_cli/file_utils.py#L131-L136

Added lines #L131 - L136 were not covered by tests

for root, dirs, files in os.walk(include_dir):
for file in files:
file_path = os.path.join(root, file)
if zip_filename in file_path or file_path in included_paths:
continue
relative_path = os.path.relpath(file_path, start=".")
zipf.write(file_path, relative_path)
included_paths.add(file_path)

Check warning on line 145 in comfy_cli/file_utils.py

View check run for this annotation

Codecov / codecov/patch

comfy_cli/file_utils.py#L138-L145

Added lines #L138 - L145 were not covered by tests


def upload_file_to_signed_url(signed_url: str, file_path: str):
Expand Down
2 changes: 2 additions & 0 deletions comfy_cli/registry/config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
comfy["PublisherId"] = ""
comfy["DisplayName"] = "ComfyUI-AIT"
comfy["Icon"] = ""
comfy["includes"] = tomlkit.array()

Check warning on line 45 in comfy_cli/registry/config_parser.py

View check run for this annotation

Codecov / codecov/patch

comfy_cli/registry/config_parser.py#L45

Added line #L45 was not covered by tests

tool.add("comfy", comfy)
document.add("tool", tool)
Expand Down Expand Up @@ -196,6 +197,7 @@
display_name=comfy_data.get("DisplayName", ""),
icon=comfy_data.get("Icon", ""),
models=[Model(location=m["location"], model_url=m["model_url"]) for m in comfy_data.get("Models", [])],
includes=comfy_data.get("includes", []),
)

return PyProjectConfig(project=project, tool_comfy=comfy)
1 change: 1 addition & 0 deletions comfy_cli/registry/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class ComfyConfig:
display_name: str = ""
icon: str = ""
models: List[Model] = field(default_factory=list)
includes: List[str] = field(default_factory=list)


@dataclass
Expand Down
62 changes: 59 additions & 3 deletions tests/comfy_cli/command/nodes/test_publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,29 @@
runner = CliRunner()


def create_mock_config(includes_list=None):
if includes_list is None:
includes_list = []

mock_pyproject_config = MagicMock()

mock_tool_comfy_section = MagicMock()
mock_tool_comfy_section.name = "test-node"
mock_tool_comfy_section.version = "0.1.0"
mock_tool_comfy_section.description = "A test node."
mock_tool_comfy_section.author = "Test Author"
mock_tool_comfy_section.license = "MIT"
mock_tool_comfy_section.tags = ["test"]
mock_tool_comfy_section.repository = "http://example.com/repo"
mock_tool_comfy_section.homepage = "http://example.com/home"
mock_tool_comfy_section.documentation = "http://example.com/docs"
mock_tool_comfy_section.includes = includes_list

mock_pyproject_config.tool_comfy = mock_tool_comfy_section

return mock_pyproject_config


def test_publish_fails_on_security_violations():
# Mock subprocess.run to simulate security violations
mock_result = MagicMock()
Expand Down Expand Up @@ -40,7 +63,8 @@ def test_publish_continues_on_no_security_violations():
patch("comfy_cli.command.custom_nodes.command.upload_file_to_signed_url") as mock_upload,
):
# Setup the mocks
mock_extract.return_value = {"name": "test-node"}
mock_extract.return_value = create_mock_config()

mock_prompt.return_value = "test-token"
mock_publish.return_value = MagicMock(signedUrl="https://test.url")

Expand Down Expand Up @@ -76,7 +100,8 @@ def test_publish_with_token_option():
patch("comfy_cli.command.custom_nodes.command.upload_file_to_signed_url") as mock_upload,
):
# Setup the mocks
mock_extract.return_value = {"name": "test-node"}
mock_extract.return_value = create_mock_config()

mock_publish.return_value = MagicMock(signedUrl="https://test.url")

# Run the publish command with token
Expand Down Expand Up @@ -104,7 +129,8 @@ def test_publish_exits_on_upload_failure():
patch("comfy_cli.command.custom_nodes.command.upload_file_to_signed_url") as mock_upload,
):
# Setup the mocks
mock_extract.return_value = {"name": "test-node"}
mock_extract.return_value = create_mock_config()

mock_publish.return_value = MagicMock(signedUrl="https://test.url")
mock_upload.side_effect = Exception("Upload failed with status code: 403")

Expand All @@ -117,3 +143,33 @@ def test_publish_exits_on_upload_failure():
assert mock_publish.called
assert mock_zip.called
assert mock_upload.called


def test_publish_with_includes_parameter():
# Mock subprocess.run to simulate no violations
mock_result = MagicMock()
mock_result.returncode = 0
mock_result.stdout = ""

with (
patch("subprocess.run", return_value=mock_result),
patch("comfy_cli.command.custom_nodes.command.extract_node_configuration") as mock_extract,
patch("comfy_cli.command.custom_nodes.command.registry_api.publish_node_version") as mock_publish,
patch("comfy_cli.command.custom_nodes.command.zip_files") as mock_zip,
patch("comfy_cli.command.custom_nodes.command.upload_file_to_signed_url") as mock_upload,
):
includes = ["/js", "/dist"]

# Setup the mocks
mock_extract.return_value = create_mock_config(includes)

mock_publish.return_value = MagicMock(signedUrl="https://test.url")

# Run the publish command with token
_result = runner.invoke(app, ["publish", "--token", "test-token"])

# Verify the publish flow worked with provided token
assert mock_extract.called
assert mock_publish.called
assert mock_zip.called
assert mock_upload.called
Loading