Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
167 changes: 167 additions & 0 deletions .github/workflows/auto_bump_comfyui_release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
name: Auto Bump ComfyUI Release

on:
workflow_dispatch:
inputs:
comfyui_version:
description: 'Optional ComfyUI version or tag (e.g. 0.12.3 or v0.12.3)'
required: false
type: string

permissions:
contents: write
pull-requests: write

concurrency:
group: auto-bump-comfyui-release
cancel-in-progress: true

jobs:
bump-comfyui:
runs-on: ubuntu-latest
steps:
- name: Checkout desktop repository
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Resolve target ComfyUI version
id: version
env:
GITHUB_TOKEN: ${{ github.token }}
INPUT_COMFYUI_VERSION: ${{ github.event.inputs.comfyui_version || '' }}
run: |
set -euo pipefail

normalize_version() {
local raw_version="$1"
raw_version="${raw_version#refs/tags/}"
raw_version="${raw_version#v}"
echo "$raw_version"
}

if [ -n "${INPUT_COMFYUI_VERSION:-}" ]; then
TARGET_VERSION="$(normalize_version "$INPUT_COMFYUI_VERSION")"
TARGET_TAG="v${TARGET_VERSION}"
TARGET_RELEASE_URL="https://github.com/Comfy-Org/ComfyUI/releases/tag/${TARGET_TAG}"
else
RELEASE_JSON="$(curl -fsSL \
-H "Authorization: Bearer ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/Comfy-Org/ComfyUI/releases/latest)"

TARGET_TAG="$(echo "$RELEASE_JSON" | jq -r '.tag_name')"
TARGET_RELEASE_URL="$(echo "$RELEASE_JSON" | jq -r '.html_url')"
if [ -z "$TARGET_TAG" ] || [ "$TARGET_TAG" = "null" ]; then
echo "Could not resolve ComfyUI latest release tag" >&2
exit 1
fi

TARGET_VERSION="${TARGET_TAG#v}"
fi

if [[ -z "$TARGET_VERSION" || ! "$TARGET_VERSION" =~ ^[0-9A-Za-z._-]+$ ]]; then
echo "Invalid ComfyUI version: ${TARGET_VERSION}" >&2
exit 1
fi

TAG_STATUS="$(curl -fsSL -o /dev/null -w '%{http_code}' \
-H "Authorization: Bearer ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/Comfy-Org/ComfyUI/git/ref/tags/${TARGET_TAG}")"
if [ "$TAG_STATUS" != "200" ]; then
echo "ComfyUI tag not found: ${TARGET_TAG}" >&2
exit 1
fi

CURRENT_VERSION="$(jq -r '.config.comfyUI.version' package.json)"

{
echo "target_tag=${TARGET_TAG}"
echo "target_version=${TARGET_VERSION}"
echo "target_release_url=${TARGET_RELEASE_URL}"
echo "current_version=${CURRENT_VERSION}"
} >> "$GITHUB_OUTPUT"

if [ "$TARGET_VERSION" = "$CURRENT_VERSION" ]; then
echo "should_update=false" >> "$GITHUB_OUTPUT"
echo "ComfyUI version already at ${CURRENT_VERSION}; skipping."
else
echo "should_update=true" >> "$GITHUB_OUTPUT"
echo "Will bump ComfyUI from ${CURRENT_VERSION} to ${TARGET_VERSION}."
fi

- name: Update package.json ComfyUI version
if: steps.version.outputs.should_update == 'true'
env:
TARGET_VERSION: ${{ steps.version.outputs.target_version }}
run: |
set -euo pipefail
TMP_FILE="$(mktemp)"
jq --arg version "$TARGET_VERSION" '.config.comfyUI.version = $version' package.json > "$TMP_FILE"
mv "$TMP_FILE" package.json

- name: Checkout target ComfyUI release
if: steps.version.outputs.should_update == 'true'
uses: actions/checkout@v6
with:
repository: Comfy-Org/ComfyUI
ref: ${{ steps.version.outputs.target_tag }}
path: assets/ComfyUI

- name: Regenerate core requirements patch
if: steps.version.outputs.should_update == 'true'
run: |
set -euo pipefail
bash scripts/regenerateCoreRequirementsPatch.sh
Comment on lines +123 to +135
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This workflow runs uv pip compile (via scripts/recompileRequirementsFromHeaders.sh) but never pins/installs a specific Python version. update_compiled_requirements.yml explicitly sets up Python 3.12 before compiling; without that, uv may resolve markers differently depending on the runner image and produce inconsistent .compiled outputs. Add a actions/setup-python step (matching the version used elsewhere) before installing/running uv.

Copilot uses AI. Check for mistakes.

- name: Apply core requirements patch
if: steps.version.outputs.should_update == 'true'
run: |
set -euo pipefail
cd assets/ComfyUI
patch -p1 < ../../scripts/core-requirements.patch

- name: Install uv
if: steps.version.outputs.should_update == 'true'
run: |
set -euo pipefail
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
"$HOME/.local/bin/uv" --version

- name: Recompile pre-shipped requirements
if: steps.version.outputs.should_update == 'true'
run: |
set -euo pipefail
bash scripts/recompileRequirementsFromHeaders.sh

- name: Clean generated ComfyUI checkout
if: steps.version.outputs.should_update == 'true'
run: rm -rf assets/ComfyUI

- name: Create pull request
if: steps.version.outputs.should_update == 'true'
uses: peter-evans/create-pull-request@v6
with:
token: ${{ github.token }}
branch: automated/bump-comfyui-v${{ steps.version.outputs.target_version }}
delete-branch: true
commit-message: Bump ComfyUI to v${{ steps.version.outputs.target_version }}
title: Bump ComfyUI to v${{ steps.version.outputs.target_version }}
body: |
## Summary
- bump `config.comfyUI.version` from `${{ steps.version.outputs.current_version }}` to `${{ steps.version.outputs.target_version }}`
- regenerate `scripts/core-requirements.patch` from upstream ComfyUI requirements
- recompile pre-shipped requirements in `assets/requirements/*.compiled` using `uv pip compile` commands stored in file headers

## Upstream Release
- ${{ steps.version.outputs.target_release_url }}

## Testing
- workflow regenerated compiled requirements and patch artifacts
labels: dependencies
add-paths: |
package.json
scripts/core-requirements.patch
assets/requirements/*.compiled
Comment on lines +168 to +192
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

PRs created with github.token won't trigger CI workflows.

GitHub deliberately prevents workflows triggered by the default GITHUB_TOKEN from triggering further workflow runs (to avoid infinite loops). The auto-generated PR won't run CI checks (e.g., build, test, lint) unless you use a GitHub App token or PAT.

If CI validation on the bump PR is required, swap github.token for an app-generated token:

-          token: ${{ github.token }}
+          token: ${{ steps.app-token.outputs.token }}

(after adding a step to generate a token from a GitHub App installation)

If the intent is to merge without CI or to manually re-trigger, the current setup is fine — just document that expectation.

🤖 Prompt for AI Agents
In @.github/workflows/auto_bump_comfyui_release.yml around lines 143 - 167, The
PR creation uses the default github.token (see the
peter-evans/create-pull-request@v6 step and its token input), which prevents CI
from running; replace token: ${{ github.token }} with an app-generated
installation token or PAT (e.g., a secret like ${{ secrets.GH_APP_TOKEN }}), and
add a preceding step to create or retrieve that GitHub App/PAT token (store it
in a job output or a secret-name) so the create-pull-request action consumes
that token instead; update the token reference in the create-pull-request step
(token input) to use the generated token variable.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

106 changes: 106 additions & 0 deletions scripts/recompileRequirementsFromHeaders.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#!/usr/bin/env bash
set -euo pipefail

usage() {
cat <<'USAGE'
Re-run uv compile commands embedded in assets/requirements/*.compiled headers.

Usage:
scripts/recompileRequirementsFromHeaders.sh [--dry-run] [compiled-file ...]

Examples:
scripts/recompileRequirementsFromHeaders.sh --dry-run
scripts/recompileRequirementsFromHeaders.sh
scripts/recompileRequirementsFromHeaders.sh assets/requirements/macos.compiled
USAGE
}

dry_run=0
compiled_files=()

for argument in "$@"; do
case "$argument" in
--dry-run)
dry_run=1
;;
-h|--help)
usage
exit 0
;;
*)
compiled_files+=("$argument")
;;
esac
done

if [[ ! -f "package.json" || ! -d "assets/requirements" ]]; then
echo "Run this script from the desktop repository root." >&2
exit 1
fi

if [[ ${#compiled_files[@]} -eq 0 ]]; then
mapfile -t compiled_files < <(find assets/requirements -maxdepth 1 -type f -name '*.compiled' | sort)
fi

if [[ ${#compiled_files[@]} -eq 0 ]]; then
echo "No compiled requirements files found." >&2
exit 1
fi

for compiled_file in "${compiled_files[@]}"; do
if [[ ! -f "$compiled_file" ]]; then
echo "Missing file: $compiled_file" >&2
exit 1
fi

compile_command="$(
awk '
/^#/ {
line = $0
sub(/^#[[:space:]]*/, "", line)
if (line ~ /^uv[[:space:]]+pip[[:space:]]+compile([[:space:]]|$)/) {
print line
exit
}
}
' "$compiled_file"
)"
if [[ -z "$compile_command" ]]; then
echo "Could not extract uv pip compile command from header comments in $compiled_file" >&2
exit 1
fi

output_path="$(printf '%s\n' "$compile_command" | awk '{
for (i = 1; i <= NF; i++) {
if ($i == "-o" && i < NF) {
print $(i + 1)
exit
}
}
}')"
if [[ -z "$output_path" ]]; then
echo "Could not find output path (-o) in compile command for $compiled_file" >&2
exit 1
fi

output_path="${output_path%\"}"
output_path="${output_path#\"}"
output_path="${output_path%\'}"
output_path="${output_path#\'}"

normalized_compiled_file="${compiled_file#./}"
normalized_output_path="${output_path#./}"
if [[ "$normalized_output_path" != "$normalized_compiled_file" ]]; then
echo "Compile command output path mismatch for $compiled_file" >&2
echo "Expected: $normalized_compiled_file" >&2
echo "Found: $normalized_output_path" >&2
exit 1
fi

echo "[$compiled_file]"
echo "$compile_command"

if [[ $dry_run -eq 0 ]]; then
bash -lc "$compile_command"
fi
done
45 changes: 45 additions & 0 deletions scripts/regenerateCoreRequirementsPatch.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env bash
set -euo pipefail

requirements_path="${1:-assets/ComfyUI/requirements.txt}"
output_patch="${2:-scripts/core-requirements.patch}"

if [[ ! -f "$requirements_path" ]]; then
echo "Requirements file not found: $requirements_path" >&2
exit 1
fi

tmp_dir="$(mktemp -d)"
trap 'rm -rf "$tmp_dir"' EXIT

original_requirements="$tmp_dir/requirements.original.txt"
patched_requirements="$tmp_dir/requirements.patched.txt"
frontend_pattern='^[[:space:]]*comfyui-frontend-package(\[[^]]+\])?([[:space:]]*([<>=!~].*)?)?$'

cp "$requirements_path" "$original_requirements"

if ! grep -Eq "$frontend_pattern" "$original_requirements"; then
echo "Missing comfyui-frontend-package pin in: $requirements_path" >&2
exit 1
fi

grep -Ev "$frontend_pattern" "$original_requirements" > "$patched_requirements"

if cmp -s "$original_requirements" "$patched_requirements"; then
echo "No changes detected after removing comfyui-frontend-package from $requirements_path" >&2
exit 1
fi

diff_body="$(diff -u --label a/requirements.txt --label b/requirements.txt "$original_requirements" "$patched_requirements" || true)"

if [[ -z "$diff_body" ]]; then
echo "Failed to generate patch body for $requirements_path" >&2
exit 1
fi

{
echo "diff --git a/requirements.txt b/requirements.txt"
echo "$diff_body"
} > "$output_patch"

echo "Wrote $output_patch from $requirements_path"