Skip to content

Commit

Permalink
Merge pull request #17 from Comfy-Org/rh-publish
Browse files Browse the repository at this point in the history
Publish Node: Parse comfynode.toml and calls publisherNodeVersion api.
  • Loading branch information
robinjhuang authored May 3, 2024
2 parents 48b8222 + 77856a0 commit bf31e27
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 24 deletions.
26 changes: 5 additions & 21 deletions DEV_README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@

# Development Guide

This guide provides an overview of how to develop in this repository.

## General guide

1. Clone the repo, create and activate a conda env
1. Clone the repo, create and activate a conda env. Minimum Python version is 3.9.

2. Install the package to local

`pip install -e .`
`pip install -e .`

3. Test script running

`comfy --help`
`comfy --help`

4. Use pre commit hook

`pre-commit install`
`pre-commit install`

## Make changes to the code base

Expand All @@ -28,7 +27,7 @@ env and reinstalling the package (`pip install -e .`)

## Add New Command

- Register it under `comfy_cli/cmdline.py`
- Register it under `comfy_cli/cmdline.py`

If it's contains subcommand, create folder under comfy_cli/command/[new_command] and
add the following boilerplate
Expand Down Expand Up @@ -59,21 +58,6 @@ def remove(name: str):
```

## Code explainer:

- `comfy_cli/cmdline.py` is the entry point of the CLI
- `comfy_cli/command/` contains definition for some commands (e.g. `node`,
`model`, etc)
- `comfy_cli/config_manager.py` implements ConfigManager class that handles
comfy_cli configuration (config.ini) file reading and writing
- `comfy_cli/workspace_manager.py` implements WorkspaceManager class that
handles which ComfyUI workspace (path) and defines workspace comfy-lock.yaml
file that register the state fo the comfy workspace.
- `comfy_cli/env_checker.py` implements EnvChecker class that helps with python
env related variables
- `comfy_cli/tracking.py` handles opt-in anonymous telemetry data from users.


## Guide

- Use `typer` for all command args management
Expand Down
29 changes: 27 additions & 2 deletions comfy_cli/command/custom_nodes/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import uuid
from comfy_cli.config_manager import ConfigManager
from comfy_cli.workspace_manager import WorkspaceManager
from comfy_cli.registry import publish_node_version, extract_node_configuration

app = typer.Typer()
manager_app = typer.Typer()
Expand Down Expand Up @@ -141,7 +142,6 @@ def show(
str, "--mode", typer.Option(show_default=False, help="[remote|local|cache]")
] = None,
):

valid_commands = [
"installed",
"enabled",
Expand Down Expand Up @@ -183,7 +183,6 @@ def simple_show(
str, "--mode", typer.Option(show_default=False, help="[remote|local|cache]")
] = None,
):

valid_commands = [
"installed",
"enabled",
Expand Down Expand Up @@ -399,3 +398,29 @@ def fix(
raise typer.Exit(code=1)

execute_cm_cli(ctx, ["fix"] + args, channel, mode)


@app.command("publish", help="Publish node to registry")
@tracking.track_command("node")
def publish(
ctx: typer.Context,
):
"""
Publish a node with optional validation.
"""

# Perform some validation logic here
typer.echo("Validating node configuration...")
config = extract_node_configuration()

# Prompt for Personal Access Token
token = typer.prompt("Please enter your Personal Access Token", hide_input=True)

# Call API to fetch node version with the token in the body
response = publish_node_version(config, token)

if response.ok:
typer.echo("Node published successfully!")
else:
typer.echo(f"Failed to publish node: {response.text}", err=True)
raise typer.Exit(code=1)
2 changes: 2 additions & 0 deletions comfy_cli/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,5 @@ class OS(Enum):
# Referencing supported pt extension from ComfyUI
# https://github.com/comfyanonymous/ComfyUI/blob/a88b0ebc2d2f933c94e42aa689c42e836eedaf3c/folder_paths.py#L5
SUPPORTED_PT_EXTENSIONS = (".ckpt", ".pt", ".bin", ".pth", ".safetensors")

COMFY_REGISTRY_URL_ROOT = "http://localhost:8080"
7 changes: 7 additions & 0 deletions comfy_cli/registry/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from .api import publish_node_version

# Import specific functions from the config_parser module
from .config_parser import extract_node_configuration
from .types import PyProjectConfig

__all__ = ["publish_node_version", "extract_node_configuration", "PyProjectConfig"]
42 changes: 42 additions & 0 deletions comfy_cli/registry/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import requests
import json
from comfy_cli import constants
from comfy_cli.registry.types import PyProjectConfig


def publish_node_version(node_config: PyProjectConfig, token: str):
"""
Publishes a new version of a node.
Args:
node_config (PyProjectConfig): The node configuration.
token (str): Personal access token for authentication.
Returns:
dict: JSON response from the API server.
"""
url = f"{constants.COMFY_REGISTRY_URL_ROOT}/publishers/{node_config.tool_comfy.publisher_id}/nodes/{node_config.project.name}/versions"
headers = {"Content-Type": "application/json"}
body = {
"personal_access_token": token,
"node": {
"id": node_config.project.name,
"description": node_config.project.description,
"name": node_config.tool_comfy.display_name,
"license": node_config.project.license,
"repository": node_config.project.urls.repository,
},
"node_version": {
"version": node_config.project.version,
"dependencies": node_config.project.dependencies,
},
}

response = requests.post(url, headers=headers, data=json.dumps(body))
# print the json of response
if response.status_code == 200:
return response.json()
else:
raise Exception(
f"Failed to publish node version: {response.status_code} {response.text}"
)
48 changes: 48 additions & 0 deletions comfy_cli/registry/config_parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import os
from comfy_cli.registry.types import (
PyProjectConfig,
ProjectConfig,
URLs,
Model,
ComfyConfig,
)


def extract_node_configuration(
path: str = os.path.join(os.getcwd(), "comfynode.toml"),
) -> PyProjectConfig:
import tomlkit

with open(path, "r") as file:
data = tomlkit.load(file)

project_data = data.get("project", {})
urls_data = project_data.get("urls", {})
comfy_data = data.get("tool", {}).get("comfy", {})

project = ProjectConfig(
name=project_data.get("name", ""),
description=project_data.get("description", ""),
version=project_data.get("version", ""),
requires_python=project_data.get("requires-pyton", ""),
dependencies=project_data.get("dependencies", []),
license=project_data.get("license", ""),
urls=URLs(
homepage=urls_data.get("Homepage", ""),
documentation=urls_data.get("Documentation", ""),
repository=urls_data.get("Repository", ""),
issues=urls_data.get("Issues", ""),
),
)

comfy = ComfyConfig(
publisher_id=comfy_data.get("PublisherId", ""),
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", [])
],
)

return PyProjectConfig(project=project, tool_comfy=comfy)
41 changes: 41 additions & 0 deletions comfy_cli/registry/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from dataclasses import dataclass, field
from typing import List


@dataclass
class URLs:
homepage: str = ""
documentation: str = ""
repository: str = ""
issues: str = ""


@dataclass
class Model:
location: str
model_url: str


@dataclass
class ComfyConfig:
publisher_id: str = ""
display_name: str = ""
icon: str = ""
models: List[Model] = field(default_factory=list)


@dataclass
class ProjectConfig:
name: str = ""
description: str = ""
version: str = "1.0.0"
requires_python: str = ">= 3.9"
dependencies: List[str] = field(default_factory=list)
license: str = ""
urls: URLs = URLs()


@dataclass
class PyProjectConfig:
project: ProjectConfig = ProjectConfig()
tool_comfy: ComfyConfig = ComfyConfig()
3 changes: 2 additions & 1 deletion requirement.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ GitPython
requests
pyyaml
typing-extensions
mixpanel
mixpanel
tomlkit

0 comments on commit bf31e27

Please sign in to comment.