Skip to content

fix(v3/build): dedupe shared tasks racing in parallel universal builds - #5573

Merged
leaanthony merged 5 commits into
masterfrom
fix/universal-build-race-4637
Jun 13, 2026
Merged

leaanthony merged 5 commits into
masterfrom
fix/universal-build-race-4637

Conversation

@leaanthony

@leaanthony leaanthony commented Jun 11, 2026 •

Copy link
Copy Markdown
Member

Description

darwin:build:universal declares its amd64/arm64 builds as task deps, which go-task runs in parallel. Each arch build's chain includes common:build:frontend → generate:bindings -clean=true, so one universal build executed the entire frontend pipeline twice concurrently: one invocation deletes/regenerates frontend/bindings while the other's bundler reads it. On slow CI runners the bundler loses the race and fails with the reported Could not resolve \"./bindings/changeme\". Two concurrent go mod tidy processes also race on go.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:universal on macOS, counted executions in the task output:

Template wails3 generate bindings runs frontend bundles result
master 2 (concurrent) 2 binary OK locally (fast machine — CI loses the timing)
this branch 1 1 lipo -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

  • Bug fix (non-breaking change which fixes an issue)

Checklist:

  • My code follows the general coding style of this project
  • I have updated v3/UNRELEASED_CHANGELOG.md

Summary by CodeRabbit

  • Bug Fixes
    • Prevented intermittent failures in universal macOS builds by ensuring shared build tasks run only once, eliminating race conditions during parallel per-architecture builds.
    • Existing projects can apply the fix by updating build assets.

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
Copilot AI review requested due to automatic review settings June 11, 2026 01:11
@coderabbitai

coderabbitai Bot commented Jun 11, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 189f0f13-808b-484c-829e-5194710fcb68

📥 Commits

Reviewing files that changed from the base of the PR and between d31e109 and ad02b72.

📒 Files selected for processing (1)
  • v3/UNRELEASED_CHANGELOG.md
✅ Files skipped from review due to trivial changes (1)
  • v3/UNRELEASED_CHANGELOG.md

Walkthrough

Adds run: once to five shared Taskfile tasks to serialize execution across parallel per-architecture builds, preventing concurrent regeneration/cleanup races that caused intermittent binding resolution failures; updates the Unreleased changelog to document the fix and the update path for existing projects.

Changes

Build Task Serialization for Parallel Architecture Safety

Layer / File(s) Summary
Build task serialization guards
v3/internal/commands/build_assets/Taskfile.tmpl.yml, v3/UNRELEASED_CHANGELOG.md
Adds run: once to go:mod:tidy (with comment about go.mod corruption), install:frontend:deps, build:frontend (notes universal per-arch parallelism), generate:bindings, and generate:icons; updates changelog entry and references wails3 update build-assets for existing projects.

Possibly related PRs

  • wailsapp/wails#4093: Related to bindings generation and universal/GOARCH handling for GenerateBindings.
  • wailsapp/wails#3902: Introduced darwin:build:universal flow that exposes the parallel per-arch build behavior addressed by this change.
  • wailsapp/wails#4023: Modifies Taskfile frontend/bindings tasks; related at the build-assets task level.

Suggested labels: v3-alpha

🐰 When arches race in parallel dreams,
Bindings clash in concurrent streams.
run: once whispers, "Only I will run,"
One generation done — now builds flow on. ✨

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main change: preventing shared tasks from racing during parallel universal builds by deduplicating them.
Description check ✅ Passed The description provides thorough context, explains the root cause, details the fix, includes verification results, and completes the required checklist items.
Linked Issues check ✅ Passed The code changes directly address issue #4637 by implementing the fix to prevent concurrent execution of shared tasks (go:mod:tidy, install:frontend:deps, build:frontend, generate:bindings, generate:icons) during parallel universal builds.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the universal build race condition: updating the changelog and adding run:once constraints to five specific shared tasks.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/universal-build-race-4637

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.

❤️ Share

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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: once so 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
v3/internal/commands/build_assets/Taskfile.tmpl.yml (1)

15-15: 💤 Low value

Consider adding explanatory comments for consistency.

Three tasks (install:frontend:deps, generate:bindings, generate:icons) gained run: once without explanatory comments, while go:mod:tidy and build:frontend include 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: once

For 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: once

For 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: once

Also 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

📥 Commits

Reviewing files that changed from the base of the PR and between 2633f81 and d31e109.

📒 Files selected for processing (2)
  • v3/UNRELEASED_CHANGELOG.md
  • v3/internal/commands/build_assets/Taskfile.tmpl.yml

@leaanthony
leaanthony merged commit 70c532c into master Jun 13, 2026
15 of 16 checks passed
@leaanthony
leaanthony deleted the fix/universal-build-race-4637 branch June 13, 2026 23:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[v3] Error Could not resolve "./bindings/changeme" from "main.js" sometimes occurs when running package:universal in GitHub Actions

2 participants