-
Notifications
You must be signed in to change notification settings - Fork 20
134 lines (124 loc) · 6.32 KB
/
Copy pathtier2.yml
File metadata and controls
134 lines (124 loc) · 6.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
name: Tier 2 — M2 / ANE (self-hosted)
on:
pull_request:
# `labeled` fires when run-m2 is first added; `synchronize`/`reopened`
# re-run on every subsequent push while the label is present, so the
# result tracks the PR head instead of going stale. The `if` below keeps
# the run gated on the run-m2 label for all pull_request events.
types: [labeled, synchronize, reopened]
schedule:
# Nightly at 04:00 UTC (~05/06 in PL). Keeps the M2 path honest
# without burning the runner on every PR.
- cron: "0 4 * * *"
workflow_dispatch:
jobs:
m2:
if: |
github.event_name == 'schedule' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' &&
contains(github.event.pull_request.labels.*.name, 'run-m2'))
# Self-hosted Apple Silicon runner. Prerequisites: COMFY_DIR pointing at
# a runner-owned ComfyUI clone, plus a cached SD1.5 checkpoint.
runs-on: [self-hosted, macOS, ARM64, coreml]
timeout-minutes: 90
steps:
- uses: actions/checkout@v4
# Hybrid ComfyUI strategy:
# - schedule (nightly) -> latest origin/master + ComfyUI's own
# requirements.txt (constrained). Canary for upstream API breakage.
# - PR label / dispatch -> the requires-comfyui version tag + the frozen
# `comfy` uv group. Reproducible merge gate, immune to overnight drift.
- name: Resolve ComfyUI ref + mode
run: |
if [ "$GITHUB_EVENT_NAME" = "schedule" ]; then
echo "COMFY_MODE=latest" >> "$GITHUB_ENV"
echo "COMFY_REF=master" >> "$GITHUB_ENV"
else
# requires-comfyui is a semver constraint (e.g. ">=0.3.27"); pin the
# gate to the matching ComfyUI release tag (vX.Y.Z).
VERSION="$(sed -nE 's/^requires-comfyui *= *"[^0-9]*([0-9]+\.[0-9]+\.[0-9]+).*/\1/p' pyproject.toml)"
if [ -z "$VERSION" ]; then echo "could not parse requires-comfyui from pyproject.toml"; exit 1; fi
echo "COMFY_MODE=pinned" >> "$GITHUB_ENV"
echo "COMFY_REF=v$VERSION" >> "$GITHUB_ENV"
fi
- name: Set up ComfyUI checkout
# COMFY_DIR is exported by the self-hosted runner's .env and MUST be a
# runner-owned ComfyUI clone (never your dev checkout — this step does
# git reset --hard and rewrites custom_nodes). Cloned on first run.
run: |
set -euo pipefail
if [ -z "${COMFY_DIR:-}" ]; then echo "COMFY_DIR unset"; exit 1; fi
# Init-in-place rather than `git clone`: COMFY_DIR may already hold the
# cached checkpoint (models/checkpoints) or converted .mlmodelc, and
# `git clone` refuses a non-empty target. init + fetch + `checkout -f`
# populates the ComfyUI tree while leaving untracked files (the
# checkpoint, the cached models) untouched — so setup order is free.
if [ ! -d "$COMFY_DIR/.git" ]; then
echo "initialising ComfyUI repo in $COMFY_DIR"
mkdir -p "$COMFY_DIR"
git -C "$COMFY_DIR" init -q
fi
git -C "$COMFY_DIR" remote get-url origin >/dev/null 2>&1 \
|| git -C "$COMFY_DIR" remote add origin https://github.com/comfyanonymous/ComfyUI.git
git -C "$COMFY_DIR" fetch --quiet origin
if [ "$COMFY_MODE" = "latest" ]; then
git -C "$COMFY_DIR" checkout -f -B master origin/master
else
git -C "$COMFY_DIR" checkout -f "$COMFY_REF"
fi
COMFY_SHA="$(git -C "$COMFY_DIR" rev-parse HEAD)"
echo "COMFY_SHA=$COMFY_SHA" >> "$GITHUB_ENV"
echo "Tier 2 mode=$COMFY_MODE, ComfyUI \`$COMFY_SHA\`" >> "$GITHUB_STEP_SUMMARY"
# Point ComfyUI's custom-node loader at this checkout. Refresh the
# symlink only; refuse to clobber a real directory (guards against a
# COMFY_DIR that is accidentally a dev checkout).
NODE_LINK="$COMFY_DIR/custom_nodes/ComfyUI-CoreMLSuite"
if [ -e "$NODE_LINK" ] && [ ! -L "$NODE_LINK" ]; then
echo "ERROR: $NODE_LINK is a real directory, not a symlink."
echo "COMFY_DIR must be a runner-owned ComfyUI, not your dev checkout."
exit 1
fi
mkdir -p "$COMFY_DIR/custom_nodes"
ln -sfn "$GITHUB_WORKSPACE" "$NODE_LINK"
- name: Install dependencies
run: |
set -euo pipefail
if [ "$COMFY_MODE" = "latest" ]; then
# Node deps (our coremltools-9 toolchain), then ComfyUI's own
# requirements for the pulled SHA, capped by the toolchain ceiling.
uv sync
uv pip install -r "$COMFY_DIR/requirements.txt" \
-c constraints/comfy-ceiling.txt
else
# Pinned gate: the frozen group mirrors the known-good pinned SHA.
uv sync --group comfy
fi
- name: Start ComfyUI server (background)
run: |
cd "$COMFY_DIR"
nohup "$GITHUB_WORKSPACE/.venv/bin/python" main.py --port 8188 --cpu-vae > /tmp/comfyui-ci.log 2>&1 &
# Poll the HTTP endpoint for readiness — robust to startup-banner
# wording / colored-log changes in a floating-latest ComfyUI.
for _ in $(seq 1 90); do
if curl -sf -o /dev/null http://127.0.0.1:8188/system_stats; then
echo "comfy ready (ComfyUI ${COMFY_SHA:-unknown})"; exit 0
fi
sleep 2
done
echo "comfy failed to start"; tail -100 /tmp/comfyui-ci.log; exit 1
- name: Purge cached Core ML UNets (force fresh conversion)
# The converter skips when a model of the same name already exists. That
# cache key is conversion *parameters* only, not the conversion code or
# toolchain — so a stale model would let a conversion regression pass.
# Clear it so every Tier 2 run exercises the full convert -> compile ->
# sample path end to end.
run: |
rm -rf "$COMFY_DIR"/models/unet/*.mlpackage "$COMFY_DIR"/models/unet/*.mlmodelc || true
- name: Run Tier 2 (m2 marker)
# Drives the Core ML Converter node, which converts the UNet from the
# checkpoint on every run (cache purged above).
run: uv run --no-sync pytest -m m2 tests/ -v
- name: Stop ComfyUI server
if: always()
run: pkill -f "main.py.*8188" || true