Skip to content

ci: set UV_LINK_MODE=copy in the Windows workflow#529

Open
mattmillerai wants to merge 1 commit into
mainfrom
matt/be-3278-uv-link-mode-copy
Open

ci: set UV_LINK_MODE=copy in the Windows workflow#529
mattmillerai wants to merge 1 commit into
mainfrom
matt/be-3278-uv-link-mode-copy

Conversation

@mattmillerai

Copy link
Copy Markdown
Collaborator

ELI-5

The Windows CI job installs packages with uv, and uv saves time by hardlinking files instead of copying them. On Windows it cannot overwrite a .pyd that some other process still has open, so the install blows up with "Access is denied" before any test runs. Telling uv to just copy the files makes the problem go away.

What

Adds UV_LINK_MODE: copy to jobs.test.env in .github/workflows/test-windows.yml, alongside the existing PYTHONIOENCODING.

Why

The "Windows Specific Commands" workflow fails on every recent PR across all branches, in the Install Dependencies step, before any test runs:

error: failed to remove file `...\venv\Lib\site-packages\pydantic_core\_pydantic_core.cp312-win_amd64.pyd`: Access is denied. (os error 5)

uv then exits non-zero and the half-removed .pyd produces a downstream ImportError: cannot import name '__version__' from 'pydantic_core'.

comfy install --fast-deps shells out to python -m uv pip install (comfy_cli/uv.py), and uv's default link mode on Windows is hardlink/clone — it cannot replace a .pyd that is loaded/locked by another process on the runner. Copy mode writes a fresh file instead, which is the standard remediation for this error. Setting it at job level (rather than on the step) means it also reaches the uv subprocess that comfy install spawns; comfy_cli/uv.py never passes an explicit env=, so the child inherits it.

Verification / judgment calls

  • This PR cannot verify itself. The workflow only triggers on paths: comfy_cli/**, so a workflow-only change does not run it. Verify by re-running "Windows Specific Commands" on any open PR that touches comfy_cli/** (e.g. fix(generate): fetch spec from /openapi not /openapi.yml (BE-2982) #517) once this lands, and confirm Install Dependencies and the subsequent comfy launch --quick-test-for-ci both pass.
  • I deliberately did not add .github/workflows/test-windows.yml to the paths filter (which would make the workflow self-testing) — that is a separate behavior change and out of scope here. Flagging it as a reasonable follow-up.
  • No Python source is touched, so there is no test or lint surface for this diff; the YAML was parsed to confirm jobs.test.env resolves to {PYTHONIOENCODING: utf8, UV_LINK_MODE: copy}.
  • Tradeoff: copy mode is marginally slower/more disk than hardlinking. On a fresh CI runner that is negligible next to a job that currently always fails.

uv defaults to hardlink/clone link mode on Windows, which cannot replace
_pydantic_core.*.pyd while the file is loaded by another process on the
runner. That surfaces as "failed to remove file ...: Access is denied.
(os error 5)" in the Install Dependencies step (comfy install --fast-deps
shells out to python -m uv pip install), followed by a half-removed .pyd
and an ImportError on pydantic_core.

Copy mode writes a fresh file instead of hardlinking, sidestepping the
in-use-file replacement failure.
@mattmillerai mattmillerai added the agent-coded PR authored by the agent-work loop label Jul 17, 2026
@mattmillerai
mattmillerai marked this pull request as ready for review July 17, 2026 05:46
@dosubot dosubot Bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Jul 17, 2026
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 42 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9460063a-d6a4-4c63-8b16-a12042e7850f

📥 Commits

Reviewing files that changed from the base of the PR and between a732f5c and 9e43e67.

📒 Files selected for processing (1)
  • .github/workflows/test-windows.yml
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch matt/be-3278-uv-link-mode-copy
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch matt/be-3278-uv-link-mode-copy

Comment @coderabbitai help to get the list of available commands.

@mattmillerai mattmillerai added the cursor-review Request Cursor bot review label Jul 17, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Cursor Review — Consolidated panel

Triggered by @mattmillerai.

✅ No high-signal findings.

Panel: 6/8 reviewers contributed findings.

Reviewers that did not contribute: kimi-k2.5:adversarial (empty), kimi-k2.5:edge-case (empty)

@mattmillerai

Copy link
Copy Markdown
Collaborator Author

Reviews-resolver pass: no changes needed on this PR — no unresolved review threads, no merge conflict (`MERGEABLE`), and the diff is still exactly the intended 3 lines in `.github/workflows/test-windows.yml`. Verified `jobs.test.env` resolves to `{PYTHONIOENCODING: utf8, UV_LINK_MODE: copy}`.

The red build check is pre-existing and unrelated to this PR

build fails on tests/comfy_cli/registry/test_config_parser.py (7 tests) and tests/comfy_cli/command/nodes/test_node_init.py::test_node_init_strips_credentials with:

ValueError: Comment cannot contain line breaks
  tomlkit/items.py:504

Root cause: comfy_cli/registry/config_parser.py:75-77 attaches a multi-line comment to [tool.comfy].includes. tomlkit 0.15.0+ rejects line breaks in Item.comment(). CI installs via pip install -e . (unpinned, pyproject.toml:49), so it resolves tomlkit 0.15.1, while uv.lock still pins 0.13.3 — which is why it reproduces in CI but not under uv run.

Evidence this is not caused by this PR:

  • With tomlkit==0.13.381 passed; with tomlkit==0.15.18 failed, 73 passed.
  • Reproduced against main's own code (same 8 failures), so it predates this branch and affects every open PR.
  • This PR touches no Python and does not affect build-and-test.yml at all.

This is also real user-facing breakage, not just tests: create_comfynode_config() backs comfy node init, so a fresh install crashes today.

Fixing product code inside a Windows-CI env-var PR would be scope creep, so I've deferred it to a follow-up ticket with a verified fix (comfy.add(tomlkit.comment(...)) preserves the original rendering under 0.15.1) plus a recommendation to make CI installs honor uv.lock. That fix lands on main and unblocks this PR and everything else.

No action needed here beyond a re-run once the tomlkit fix merges.

@mattmillerai

Copy link
Copy Markdown
Collaborator Author

Correction to my previous comment: the tomlkit fix is already in flight as #533 ("fix(registry): emit pyproject hint blocks as single-line tomlkit comments", BE-3285), so no new follow-up ticket is needed and I have not filed one.

#533 covers the same root cause and is in fact broader than what I sketched — it fixes both multi-line .comment() sites (the requires-comfyui hint and the classifiers block in initialize_project_config), emitting one comment item per line via a shared _append_hint() helper.

So the state of this PR is unchanged: nothing to fix here. Once #533 merges to main, re-run build on this PR and it should go green. Still worth considering separately (not filing unless someone wants it) is that CI's pip install -e . ignores uv.lock, which is why tomlkit 0.15.1 reached CI while local uv run stayed on the locked 0.13.3 — that gap is what let this land unnoticed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-coded PR authored by the agent-work loop cursor-review Request Cursor bot review size:XS This PR changes 0-9 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant