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
117 changes: 117 additions & 0 deletions .github/workflows/tests-flows-install.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
name: Flows Install

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

concurrency:
group: flows_install-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
github_flows_install:
name: Flows Install GitHub Ubuntu 24
runs-on: ubuntu-24.04
env:
DATABASE_URI: postgresql+psycopg://vix_user:vix_password@localhost:5432/vix_db

services:
postgres:
image: postgres:17
env:
POSTGRES_USER: vix_user
POSTGRES_PASSWORD: vix_password
POSTGRES_DB: vix_db
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

steps:
- uses: actions/checkout@v4
- name: Checkout Visionatrix (engine)
uses: actions/checkout@v4
with:
repository: Visionatrix/Visionatrix
path: visionatrix_main

- uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install Visionatrix dependencies
working-directory: visionatrix_main
run: |
python3 -m pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
python3 -m pip install ".[pgsql]"

- name: Export Visionatrix exclude flows
run: |
value=$(python3 scripts/ci/get_excludes.py flows)
echo "VISIONATRIX_EXCLUDE_FLOWS=$value" >> "$GITHUB_ENV"

- name: Export Visionatrix exclude nodes
run: |
value=$(python3 scripts/ci/get_excludes.py nodes)
echo "VISIONATRIX_INSTALL_EXCLUDE_NODES=$value" >> "$GITHUB_ENV"

- name: Run Visionatrix install
working-directory: visionatrix_main
run: python3 -m visionatrix install

- name: Install flows from CMD
working-directory: visionatrix_main
run: |
echo "Y" | VIX_MODE=SERVER VIX_SERVER_FULL_MODELS=0 python3 -m visionatrix install-flow --name=*

- name: Generate openapi-flows.json
working-directory: visionatrix_main
run: |
VIX_MODE=SERVER VIX_SERVER_FULL_MODELS=0 python3 -m visionatrix openapi --flows="*" --exclude-base --file=openapi-flows.json

- name: Create test user
working-directory: visionatrix_main
run: |
VIX_MODE=SERVER VIX_SERVER_FULL_MODELS=0 python3 -m visionatrix create-user --name=user --password=user

- name: Start Visionatrix in Server mode
working-directory: visionatrix_main
run: |
nohup python3 -m visionatrix run --ui --mode=SERVER > visionatrix.log 2>&1 &
echo "Server started in background with PID $!"

- name: Wait for Visionatrix server
run: |
max_attempts=30
for i in $(seq 1 $max_attempts); do
echo "Attempt $i/$max_attempts: Checking Visionatrix server..."
if curl -s http://localhost:8288/whoami > /dev/null; then
echo "Visionatrix server is up!"
exit 0
fi
echo "Server not ready yet. Sleeping 10s..."
sleep 10
done
echo "Server not responding after 5 minutes!"
exit 1

- name: Download test image
working-directory: visionatrix_main
run: |
wget -O tests/source-cube_rm_background.png "https://github.com/Visionatrix/VixFlowsDocs/blob/main/tests_data/source-cube_rm_background.png?raw=true"

- name: Create task for each Flow
working-directory: visionatrix_main
run: python3 tests/create_flow_tasks.py

- name: Display logs
if: ${{ always() }}
working-directory: visionatrix_main
run: cat visionatrix.log
9 changes: 7 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,17 @@ RUN --mount=type=cache,target=/root/.cache/pip \
venv/bin/python -m pip install torch==2.7.0 torchvision torchaudio; \
fi

COPY ex_app/lib/exclude_nodes.py ex_app/lib/exclude_flows.py /ex_app/lib/
COPY scripts/ci/get_excludes.py /get_excludes.py
RUN --mount=type=cache,target=/root/.cache/pip \
cd /Visionatrix && \
venv/bin/python -m pip install "psycopg[binary]" greenlet && \
venv/bin/python -m pip install . && \
venv/bin/python -m visionatrix install && \
rm visionatrix.db
VISIONATRIX_INSTALL_EXCLUDE_NODES="$(python /get_excludes.py nodes)" \
venv/bin/python -m visionatrix install && \
rm visionatrix.db && \
rm /get_excludes.py && \
rm -rf /ex_app

# Setup nodejs and npm for building the front-end client
RUN apt-get update && \
Expand Down
5 changes: 5 additions & 0 deletions ex_app/lib/exclude_flows.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
EXCLUDE_FLOWS_IDS = [
"all_your_life",
"photo_stickers2",
"photomaker_2",
]
5 changes: 5 additions & 0 deletions ex_app/lib/exclude_nodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
EXCLUDE_NODES_IDS = [
"https://github.com/Fannovel16/ComfyUI-Frame-Interpolation",
"https://github.com/shiimizu/ComfyUI-PhotoMaker-Plus",
"https://github.com/FizzleDorf/ComfyUI_FizzNodes",
]
7 changes: 6 additions & 1 deletion ex_app/lib/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
from time import sleep

import httpx
from exclude_flows import EXCLUDE_FLOWS_IDS
from exclude_nodes import EXCLUDE_NODES_IDS
from fastapi import BackgroundTasks, Body, Depends, FastAPI, Request, responses
from nc_py_api import NextcloudApp
from nc_py_api.ex_app import (
Expand All @@ -29,7 +31,7 @@
from nc_py_api.ex_app.providers.task_processing import TaskProcessingProvider
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import FileResponse, Response
from supported_flows import FLOWS_IDS
from task_processing_flows import FLOWS_IDS

# ---------Start of configuration values for manual deploy---------
# Uncommenting the following lines may be useful when installing manually.
Expand Down Expand Up @@ -74,6 +76,9 @@
print("[DEBUG]: PROJECT_ROOT_FOLDER=", PROJECT_ROOT_FOLDER, flush=True)
print("[DEBUG]: STATIC_FRONTEND_PRESENT=", STATIC_FRONTEND_PRESENT, flush=True)

os.environ["VISIONATRIX_INSTALL_EXCLUDE_NODES"] = EXCLUDE_NODES_IDS
os.environ["VISIONATRIX_EXCLUDE_FLOWS"] = EXCLUDE_FLOWS_IDS


def _(text):
return current_translator.get().gettext(text)
Expand Down
File renamed without changes.
74 changes: 74 additions & 0 deletions scripts/ci/get_excludes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env python3
"""
Tiny helper for GitHub Actions *and* Docker builds.

Usage:
python3 get_excludes.py flows # → prints "id1;id2;…"
python3 get_excludes.py nodes # → prints "url1;url2;…"

It echoes a semicolon-joined list so callers can assign it to an environment variable, e.g.:

VISIONATRIX_INSTALL_EXCLUDE_NODES="$(python /get_excludes.py nodes)"
"""

from __future__ import annotations

import importlib.util
import sys
from pathlib import Path
from collections.abc import Sequence


def _import_list(file: Path, var: str) -> Sequence[str]:
spec = importlib.util.spec_from_file_location(file.stem, file)
module = importlib.util.module_from_spec(spec) # type: ignore[arg-type]
spec.loader.exec_module(module) # type: ignore[attr-defined]
value: list[str] | Sequence[str] = getattr(module, var, [])
if not isinstance(value, list | tuple):
raise TypeError(f"{file}:{var} is not a list/tuple")
return value


def find_repo_root() -> Path:
"""
Locate directory that contains ex_app/lib/ .
Strategy (first match wins):
1. Walk up from this script's directory.
2. Walk up from CWD (useful if script is executed via absolute path).
3. Fallback to filesystem root (where Dockerfile copies it as /ex_app/lib).
"""
def search_up(start: Path) -> Path | None:
for p in [start, *list(start.parents)]:
if (p / "ex_app" / "lib").is_dir():
return p
return None

here = Path(__file__).resolve().parent
return search_up(here) or search_up(Path.cwd()) or Path("/")


def main() -> None:
if len(sys.argv) != 2 or sys.argv[1] not in {"flows", "nodes"}:
print("Usage: get_excludes.py [flows|nodes]", file=sys.stderr)
sys.exit(1)

mode = sys.argv[1]
repo_root = find_repo_root() # <repo root> or "/" inside container

if mode == "flows":
py_file = repo_root / "ex_app" / "lib" / "exclude_flows.py"
var_name = "EXCLUDE_FLOWS_IDS"
else:
py_file = repo_root / "ex_app" / "lib" / "exclude_nodes.py"
var_name = "EXCLUDE_NODES_IDS"

if not py_file.is_file():
print(f"Error: cannot locate {py_file}", file=sys.stderr)
sys.exit(2)

items = _import_list(py_file, var_name)
print(";".join(items))


if __name__ == "__main__":
main()