Repository navigation
fix(v3/build): dedupe shared tasks racing in parallel universal builds - #5573
Conversation
darwin:build:universal runs its amd64 and arm64 builds as task deps, which go-task executes in parallel. Each arch build's dependency chain runs common:build:frontend, so a single universal build executed the whole frontend pipeline twice concurrently: one invocation regenerates frontend/bindings (with -clean=true deleting the directory first) while the other's bundler is reading it, failing intermittently with 'Could not resolve "./bindings/<pkg>"' — most often on slow CI runners. Two go:mod:tidy processes also raced on go.mod. Mark the shared, arch-independent tasks (go:mod:tidy, install:frontend:deps, build:frontend, generate:bindings, generate:icons) as run:once so concurrent invocations with identical vars deduplicate. Side benefit: universal builds now run the frontend pipeline once instead of twice. Verified with scaffolded apps on macOS: a universal build from the old template executes 'wails3 generate bindings' and the frontend bundle twice (the race window); from the patched template exactly once, and lipo reports a correct x86_64+arm64 binary. Existing projects pick this up via 'wails3 update build-assets'. Fixes #4637
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
WalkthroughAdds ChangesBuild Task Serialization for Parallel Architecture Safety
Possibly related PRs
Suggested labels:
🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR fixes an intermittent CI failure in v3 darwin:build:universal where per-arch builds run as parallel dependencies and were concurrently re-running shared frontend/build-asset tasks (notably bindings generation with -clean=true), causing the frontend bundler to sometimes read a partially-deleted frontend/bindings directory.
Changes:
- Mark shared, arch-independent Taskfile steps as
run: onceso parallel universal-build deps dedupe instead of executing concurrently (go:mod:tidy,install:frontend:deps,build:frontend,generate:bindings,generate:icons). - Add a changelog entry documenting the universal build race fix and the recommended update path for existing projects.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| v3/internal/commands/build_assets/Taskfile.tmpl.yml | Adds run: once to shared tasks to prevent concurrent duplicate execution during parallel multi-arch builds. |
| v3/UNRELEASED_CHANGELOG.md | Documents the intermittent universal-build bindings resolution failure fix and mitigation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
v3/internal/commands/build_assets/Taskfile.tmpl.yml (1)
15-15: 💤 Low valueConsider adding explanatory comments for consistency.
Three tasks (
install:frontend:deps,generate:bindings,generate:icons) gainedrun: oncewithout explanatory comments, whilego:mod:tidyandbuild:frontendinclude detailed race-condition explanations. Adding brief comments to the remaining tasks would help future maintainers understand why the directive is necessary and maintain consistency with the documented tasks.📝 Suggested comment additions
For
install:frontend:deps(after line 14):install:frontend:deps: summary: Install frontend dependencies + # Parallel per-arch builds share the same node_modules; concurrent installs race. run: onceFor
generate:bindings(after line 178):generate:bindings: label: generate:bindings (BUILD_FLAGS={{.Opn}}.BUILD_FLAGS{{.Cls}}) summary: Generates bindings for the frontend + # Parallel builds share frontend/bindings; -clean=true causes one to delete while the other reads. run: onceFor
generate:icons(after line 195):generate:icons: summary: Generates Windows `.ico` and Mac `.icns` from an image; on macOS, `-iconcomposerinput appicon.icon -macassetdir darwin` also produces `Assets.car` from a `.icon` file (skipped on other platforms). + # Parallel builds share build/darwin and build/windows icon outputs. run: onceAlso applies to: 179-179, 196-196
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@v3/internal/commands/build_assets/Taskfile.tmpl.yml` at line 15, The three Taskfile tasks install:frontend:deps, generate:bindings, and generate:icons each set run: once but lack explanatory comments; add a short comment above or immediately after each task stating why run: once is required (e.g., to avoid concurrent execution/race conditions and because the step is a one-time or expensive setup operation), mirroring the style and brevity used in the existing go:mod:tidy and build:frontend comments so maintainers understand the rationale for run: once.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@v3/internal/commands/build_assets/Taskfile.tmpl.yml`:
- Line 15: The three Taskfile tasks install:frontend:deps, generate:bindings,
and generate:icons each set run: once but lack explanatory comments; add a short
comment above or immediately after each task stating why run: once is required
(e.g., to avoid concurrent execution/race conditions and because the step is a
one-time or expensive setup operation), mirroring the style and brevity used in
the existing go:mod:tidy and build:frontend comments so maintainers understand
the rationale for run: once.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d85786ed-ec6f-492d-a097-63c7758773d6
📒 Files selected for processing (2)
v3/UNRELEASED_CHANGELOG.mdv3/internal/commands/build_assets/Taskfile.tmpl.yml
…elog conflict # Conflicts: # v3/UNRELEASED_CHANGELOG.md
Description
darwin:build:universaldeclares its amd64/arm64 builds as taskdeps, which go-task runs in parallel. Each arch build's chain includescommon:build:frontend→generate:bindings -clean=true, so one universal build executed the entire frontend pipeline twice concurrently: one invocation deletes/regeneratesfrontend/bindingswhile the other's bundler reads it. On slow CI runners the bundler loses the race and fails with the reportedCould not resolve \"./bindings/changeme\". Two concurrentgo mod tidyprocesses also race ongo.mod.Fix
Mark the shared, arch-independent tasks as
run: once:go:mod:tidy,install:frontend:deps,build:frontend,generate:bindings,generate:icons. Concurrent invocations with identical vars now deduplicate — the second waits for the first instead of re-running. Per-arch Go builds remain fully parallel.Side benefit: universal builds run the frontend pipeline once instead of twice.
Verification (proves the issue)
Scaffolded one app from the master CLI and one from this branch, ran
darwin:build:universalon macOS, counted executions in the task output:wails3 generate bindingsrunslipo -archs→x86_64 arm64✓The reporter's CI logs show the same double-execution interleaving before the rollup failure.
Existing projects pick the fix up via
wails3 update build-assets(noted in the changelog).Fixes #4637
Type of change
Checklist:
v3/UNRELEASED_CHANGELOG.mdSummary by CodeRabbit