- Python 61%
- Shell 16%
- HCL 8.3%
- Dockerfile 7.8%
- Makefile 6.9%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
Some checks are pending
validate / validate (push) Waiting to run
- Add final build-push step that retargets the endpoint template to the freshly-pushed <sha> image via tools/update_runpod_template.py, gated on vars.RUNPOD_ENDPOINT_ID + secrets.RUNPOD_API_KEY (no-ops when absent). - validate.yml: add --break-system-packages so ansible-core installs under PEP 668 (bookworm) system Python. - runbook step 5: note the wiring is now in-repo. |
||
| .forgejo/workflows | ||
| .github/workflows | ||
| docs | ||
| infra | ||
| skills/comfy-workflow-gitops | ||
| src | ||
| tests | ||
| tools | ||
| workflows | ||
| .dockerignore | ||
| .git-credentials | ||
| .gitignore | ||
| custom_nodes.json | ||
| Dockerfile | ||
| extra_model_paths.yaml | ||
| Makefile | ||
| models.json | ||
| network-volume-layout.txt | ||
| README.md | ||
| requirements.txt | ||
| smoke-test-request.json | ||
| smoke-test-run-request.json | ||
| start.sh | ||
| versions.env | ||
| workflow-manifest.json | ||
RunPod Serverless ComfyUI staging worker — txt2img only
Review-only hardening staging repository for the current Yuna txt2img workflow. No endpoint deployment has been performed.
Scope deliberately excludes i2i, inpainting, Flux, video, explicit workflows, image inputs, Discord credentials, and Hermes prompt assembly. Hermes remains the prompt assembler; this worker only receives the final prompt and executes the approved workflow.
Workflow registry and GitOps flow
Approved API-format workflows live in workflows/ and are copied into the
worker image. A request selects a packaged filename; it cannot upload arbitrary
JSON into a running worker. Add a workflow by committing the file, then run:
python3 tools/inventory_workflows.py
This regenerates workflow-manifest.json and
infra/ansible/workflow-dependencies.json. CI validates the manifests, tests
the handler, runs Ansible syntax checks, builds the image, and validates the
Terraform configuration. A manually triggered plan job can create a reviewed
Terraform plan; apply is intentionally not automated.
Migration documentation:
docs/existing-flow-baseline.md— current Tailscale flow as the oracle.docs/migration-requirements.md— functional and non-functional requirements.docs/migration-test-plan.md— provider-swap regression plan.docs/migration-milestones.md— milestones, deliverables, and exit criteria.
Local build commands
The Makefile is the local/CI entrypoint:
make all-checks # inventory, manifests, unit tests, shell syntax
make ansible-check # requires ansible-playbook
make terraform-check # requires terraform
make docker-build # requires a Docker daemon and GPU-capable runtime test separately
make smoke-local # requires a built image and prepared model volume
make smoke-runpod # requires RUNPOD_ENDPOINT_ID and RUNPOD_API_KEY
Immutable pins
- ComfyUI source target:
0.33.1 - ComfyUI source commit:
72865f4f27eaf5396f8f36370e0a2be3a9a090ee - Official worker base tag:
runpod/worker-comfyui:5.8.6-base - Official worker base Linux/AMD64 child digest:
sha256:bc873b59b613dcd8144db9f9f080e706453f5299268c8b0b7936e07b32dbbd43 - rgthree commit:
13b4399c00b5ef5a97b1b6800fc1185874740f5d
The Dockerfile uses the immutable base digest and then replaces the base
ComfyUI checkout with the exact audited ComfyUI source commit. It includes a
build-time assertion that comfyui_version.__version__ == "0.33.1".
Startup hardening
start.sh performs this sequence:
- Verify every required model file exists under
/runpod-volume/models. - Assert the ComfyUI Python version is exactly
0.33.1. - Start ComfyUI on
127.0.0.1:8188. - Wait for
/system_statsreadiness, with a bounded timeout. - Query
/object_infoand require both rgthree classes. - Start the RunPod handler only after all checks pass.
ComfyUI logs are written to /var/log/comfyui.log. No secrets are printed by
the startup checks or handler.
Custom nodes
custom_nodes.json pins:
Seed (rgthree)Power Lora Loader (rgthree)
Both come from rgthree-comfy at the pinned commit in versions.env.
Models
models.json and network-volume-layout.txt specify:
/runpod-volume/models/diffusion_models/moodyProMix_zitV11DPOFP8.safetensors
/runpod-volume/models/text_encoders/qwen_3_4b.safetensors
/runpod-volume/models/vae/ae.safetensors
/runpod-volume/models/loras/momoka-zib-v2_clean.safetensors
/runpod-volume/models/loras/abf.safetensors
The worker refuses to start if any of these files is missing.
Handler input contract
{
"input": {
"workflow": "txt2img_api.json",
"prompt": "already assembled txt2img prompt",
"seed": 42,
"output_format": "base64"
}
}
prompt: required non-empty string.workflow: packaged workflow filename; defaults totxt2img_api.json.seed: integer;-1is accepted for workflow randomization.output_format: onlybase64is implemented in this staging worker.- No image input field exists.
- No prompt assembly or appearance-file logic runs in the worker.
Handler output contract
{
"status": "success",
"prompt_id": "runpod-job-id",
"images": [
{
"filename": "...png",
"mime_type": "image/png",
"node_id": "732",
"data": "<base64 PNG>"
}
]
}
Only final SaveImage node 732 is returned. Hermes can decode the base64 data,
save it locally, and attach it through MEDIA:/absolute/path/to/file.png.
Tests
Unit tests:
python3 -m unittest -v tests/test_handler.py
They cover:
- prompt mutation at node
627; - seed mutation at node
649; - filename-prefix mutation at node
732; - input validation;
- final-node-only output filtering;
- base64 output encoding.
Container-level smoke test after building locally:
IMAGE=<local-image-tag> MODEL_VOLUME=/path/to/network-volume \
tests/container_smoke_test.sh
This starts the container, waits for /health, and sends
smoke-test-request.json to /runsync. It is not executed by this audit.
Asynchronous production smoke test
Production should use /run, not /runsync, because cold starts and this
workflow’s generation time may exceed synchronous limits.
The asynchronous smoke script submits smoke-test-run-request.json to /run,
then polls /status/{job_id}:
RUNPOD_ENDPOINT_ID=<endpoint-id> \
RUNPOD_API_KEY=<set-in-shell-only> \
tests/serverless_async_smoke_test.sh
The script does not print the API key. It has not been run because there is no deployed endpoint.
Proposed diff summary
Compared with the previous staging draft:
- Floating
runpod/worker-comfyui:basereplaced with an immutable5.8.6-base@sha256:...reference. - Exact ComfyUI
v0.33.1source commit is checked out during image build. - Build-time version assertion added.
start.shadded for ordered ComfyUI readiness and handler startup.- Runtime model-file checks added.
- Runtime rgthree
/object_infochecks added. - Unit tests added under
tests/test_handler.py. - Local container
/runsyncsmoke test added. - Asynchronous deployed-endpoint
/runsmoke test added. - Staging model manifest corrected to the current workflow’s fixed LoRAs:
Momoka character LoRA plus
abf.safetensors.
Unresolved risks
- The Docker image has not been built in this environment. The installed Docker
client is legacy and does not support
docker build --check; no Docker daemon is available for a real build/run proof. - The immutable registry digest was verified as the Docker Hub Linux/AMD64
child manifest for
5.8.6-base. - The final proof that the built image runs ComfyUI
0.33.1depends on the Docker build executing its explicit assertion and CPU import smoke test. - GPU inference, model loading, rgthree execution, and final image generation still require a real RunPod GPU build/container test.
- Network Volume permissions and mount configuration are deployment-specific.
- Base-image startup behavior may include inherited RunPod conventions; this
draft deliberately replaces the base command with
start.shand should be tested against the pinned image before deployment. - Base64 output increases response size. A future S3 output mode may be better for large images, but it is intentionally not included in this staging scope.
- The worker currently returns only node
732; it does not return PreviewImage node651. - No credentials are embedded in the image or tests.
RUNPOD_API_KEYis read only from the caller’s environment by the async test script.