Skip to content

v3: convert tool has-cc to generic tool has <target>#5533

Merged
leaanthony merged 11 commits into
masterfrom
feat/tool-has-command
Jun 13, 2026
Merged

v3: convert tool has-cc to generic tool has <target>#5533
leaanthony merged 11 commits into
masterfrom
feat/tool-has-command

Conversation

@leaanthony

@leaanthony leaanthony commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Replaces wails3 tool has-cc with the generic wails3 tool has <target>
  • cc retains its special logic (checks for gcc or clang)
  • Any other name is looked up directly in PATH, so wails3 tool has git, wails3 tool has node, etc. work out of the box without new subcommands
  • Updates the Linux Taskfile template: wails3 tool has-ccwails3 tool has cc

Test plan

  • wails3 tool has cc prints true on a machine with gcc/clang, false without
  • wails3 tool has git prints true on a machine with git in PATH
  • wails3 tool has nonexistent-tool prints false
  • Unit test TestToolHas covers cc, a known tool (git), and a nonexistent tool

Summary by CodeRabbit

  • New Features

    • Session-scoped build warnings: warnings collected during tasks are printed after completion.
  • Refactor

    • Added a generic tool-check command (e.g., tool has git / tool has gcc|clang); old single-tool check is deprecated as an alias.
    • Build task routing now uses the generic tool check.
    • Tasks create per-invocation temporary warnings storage and flush warnings on fatal errors.
  • Tests

    • Tests updated to cover multi-alternative tool checks and missing-tool cases.
  • Documentation

    • CLI docs updated with new Tool Commands and a deprecation notice.

Copilot AI review requested due to automatic review settings June 3, 2026 10:11
@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a generic wails3 tool has <tool> command that accepts |-separated alternatives and prints true/false; keeps has-cc as a deprecated alias. Introduces a WAILS_WARNINGS_FILE-backed build-warnings API, wired into task wrapper and fatal to collect and emit warnings. Tests and docs updated.

Changes

Generic tool availability check & build warnings

Layer / File(s) Summary
Generic tool availability implementation
v3/internal/commands/tool_docker_mounts.go, v3/internal/commands/tool_docker_mounts_test.go
Adds HasOptions{Tool string} and ToolHas which accepts `
CLI registration and Taskfile update
v3/cmd/wails3/main.go, v3/internal/commands/build_assets/linux/Taskfile.yml, docs/src/content/docs/guides/cli.mdx
Registers wails3 tool has wired to commands.ToolHas, updates has-cc help to mark it deprecated (still calls ToolHasCC), updates HAS_CC Taskfile check to `wails3 tool has gcc
Build warnings API and tests
v3/internal/buildwarnings/buildwarnings.go, v3/internal/buildwarnings/buildwarnings_test.go
Adds WAILS_WARNINGS_FILE-based Add(source,message) and FlushAndPrint() plus helper read/entry parsing. Tests validate add+flush behavior, no-op when env unset, and flush-no-op on empty file.
Task wrapper and fatal integration
v3/internal/commands/task_wrapper.go, v3/internal/commands/task.go
wrapTask now creates a per-invocation temp warnings file, sets the env var for subprocesses, and defers buildwarnings.FlushAndPrint(); fatal calls buildwarnings.FlushAndPrint() before logging error and exiting.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • wailsapp/wails#5470: Introduced the earlier has-cc/ToolHasCC command that this PR generalizes into has/ToolHas.
  • wailsapp/wails#4488: Modifies wrapTask flow; related to per-invocation task wiring and environment handling.
  • wailsapp/wails#5126: Related template/taskfile changes touching build asset plumbing and taskfile templates.

Suggested labels

Enhancement, cli, Documentation

Poem

🐰 I sniffed the PATH at break of dawn,
One command now fits on every lawn,
gcc|clang or git — I peep and pry,
True or false — a carrot-coded reply,
Warnings tucked in a temp file — hop! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: converting the deprecated 'tool has-cc' subcommand to a generic 'tool has ' command with special handling for 'cc'.
Description check ✅ Passed The description covers the main change summary, test plan checklist, and implementation details, but lacks explicit issue reference, type-of-change checkbox selection, and testing platform verification.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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 feat/tool-has-command

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 generalizes the Wails v3 CLI tool-check command from a dedicated wails3 tool has-cc to a generic wails3 tool has <target>, while preserving special handling for cc (gcc/clang). This improves extensibility for Taskfile templates and user scripts by enabling ad-hoc checks for arbitrary tools in PATH.

Changes:

  • Replaced wails3 tool has-cc with wails3 tool has <tool> and added special-case cc logic (gcc/clang).
  • Updated the Linux build assets Taskfile template to use wails3 tool has cc.
  • Updated/renamed the unit test to cover the new ToolHas entrypoint.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
v3/internal/commands/tool_docker_mounts.go Replaces the old has-cc implementation with the new generic ToolHas + HasOptions.
v3/internal/commands/tool_docker_mounts_test.go Renames and adjusts the tool availability test for the new command.
v3/internal/commands/build_assets/linux/Taskfile.yml Updates template usage from has-cc to has cc.
v3/cmd/wails3/main.go Switches CLI registration from has-cc to has.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +25 to +28
func ToolHas(opts *HasOptions) error {
DisableFooter = true
_, gccErr := exec.LookPath("gcc")
_, clangErr := exec.LookPath("clang")
if gccErr == nil || clangErr == nil {
fmt.Print("true")
} else {
fmt.Print("false")
switch opts.Tool {
case "cc":
Comment on lines +180 to 190
func TestToolHas(t *testing.T) {
for _, tool := range []string{"cc", "git", "nonexistent-tool-xyz"} {
out, err := captureStdout(t, func() error { return ToolHas(&HasOptions{Tool: tool}) })
if err != nil {
t.Fatalf("ToolHas(%q) returned error: %v", tool, err)
}
if out != "true" && out != "false" {
t.Errorf("ToolHas(%q): expected \"true\" or \"false\", got %q", tool, out)
}
}
}
Comment thread v3/cmd/wails3/main.go

@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/tool_docker_mounts_test.go (1)

180-190: ⚡ Quick win

Assert exact results here and avoid relying on git being installed.

This only verifies that ToolHas prints a boolean-looking string, so it would still pass if generic PATH lookup always returned "false". Using git also makes the “known tool” case runner-dependent. Please make one known-tool case deterministic and assert exact "true"/"false" outputs.

🧪 Example tightening for this test
 func TestToolHas(t *testing.T) {
-	for _, tool := range []string{"cc", "git", "nonexistent-tool-xyz"} {
-		out, err := captureStdout(t, func() error { return ToolHas(&HasOptions{Tool: tool}) })
+	exe, err := os.Executable()
+	if err != nil {
+		t.Fatalf("os.Executable: %v", err)
+	}
+	t.Setenv("PATH", filepath.Dir(exe)+string(os.PathListSeparator)+os.Getenv("PATH"))
+
+	for _, tc := range []struct {
+		tool string
+		want string
+	}{
+		{tool: filepath.Base(exe), want: "true"},
+		{tool: "nonexistent-tool-xyz", want: "false"},
+	} {
+		out, err := captureStdout(t, func() error { return ToolHas(&HasOptions{Tool: tc.tool}) })
 		if err != nil {
-			t.Fatalf("ToolHas(%q) returned error: %v", tool, err)
+			t.Fatalf("ToolHas(%q) returned error: %v", tc.tool, err)
 		}
-		if out != "true" && out != "false" {
-			t.Errorf("ToolHas(%q): expected \"true\" or \"false\", got %q", tool, out)
+		if out != tc.want {
+			t.Errorf("ToolHas(%q): want %q, got %q", tc.tool, tc.want, out)
 		}
 	}
+
+	out, err := captureStdout(t, func() error { return ToolHas(&HasOptions{Tool: "cc"}) })
+	if err != nil {
+		t.Fatalf("ToolHas(%q) returned error: %v", "cc", err)
+	}
+	if out != "true" && out != "false" {
+		t.Errorf("ToolHas(%q): expected \"true\" or \"false\", got %q", "cc", out)
+	}
 }
🤖 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/tool_docker_mounts_test.go` around lines 180 - 190,
TestToolHas currently only checks that output looks boolean and relies on the
environment having "git"; make the test deterministic by asserting exact "true"
for a tool we can control and "false" for a guaranteed-missing tool: replace the
ambiguous "git" case with a deterministic known-good binary (for example create
a temporary executable file in the test and call ToolHas on its basename) and
assert out == "true", keep the nonexistent-tool case and assert out == "false";
update TestToolHas to use captureStdout to run ToolHas(&HasOptions{Tool:
<name>}) for both the temp executable and the nonexistent name and assert exact
outputs, referencing TestToolHas, ToolHas, HasOptions, and captureStdout to
locate the change.
🤖 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/tool_docker_mounts_test.go`:
- Around line 180-190: TestToolHas currently only checks that output looks
boolean and relies on the environment having "git"; make the test deterministic
by asserting exact "true" for a tool we can control and "false" for a
guaranteed-missing tool: replace the ambiguous "git" case with a deterministic
known-good binary (for example create a temporary executable file in the test
and call ToolHas on its basename) and assert out == "true", keep the
nonexistent-tool case and assert out == "false"; update TestToolHas to use
captureStdout to run ToolHas(&HasOptions{Tool: <name>}) for both the temp
executable and the nonexistent name and assert exact outputs, referencing
TestToolHas, ToolHas, HasOptions, and captureStdout to locate the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5ee6fd68-f5ee-4cf3-a001-691184516df0

📥 Commits

Reviewing files that changed from the base of the PR and between afe8693 and 687a58c.

📒 Files selected for processing (4)
  • v3/cmd/wails3/main.go
  • v3/internal/commands/build_assets/linux/Taskfile.yml
  • v3/internal/commands/tool_docker_mounts.go
  • v3/internal/commands/tool_docker_mounts_test.go

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
v3/internal/commands/tool_docker_mounts.go (1)

30-53: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add empty opts.Tool validation in ToolHas
In v3/internal/commands/tool_docker_mounts.go, ToolHas falls through to the default path calling exec.LookPath(opts.Tool); when opts.Tool is "", this ends up calling exec.LookPath("") and should instead return a clear error.

🛡️ Proposed fix
 func ToolHas(opts *HasOptions) error {
 	DisableFooter = true
+	if opts.Tool == "" {
+		return fmt.Errorf("tool name is required")
+	}
 	switch opts.Tool {
 	case "cc":
🤖 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/tool_docker_mounts.go` around lines 30 - 53, ToolHas
currently calls exec.LookPath with an empty string when opts.Tool == "", causing
unexpected behavior; add an early validation at the start of ToolHas (and handle
nil opts) that returns a clear error if opts is nil or opts.Tool is empty (e.g.,
return fmt.Errorf("Tool must be specified")). Place this check before the switch
so functions like exec.LookPath are never called with an empty string and
reference the function ToolHas and the field opts.Tool when implementing the
validation.
🤖 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.

Outside diff comments:
In `@v3/internal/commands/tool_docker_mounts.go`:
- Around line 30-53: ToolHas currently calls exec.LookPath with an empty string
when opts.Tool == "", causing unexpected behavior; add an early validation at
the start of ToolHas (and handle nil opts) that returns a clear error if opts is
nil or opts.Tool is empty (e.g., return fmt.Errorf("Tool must be specified")).
Place this check before the switch so functions like exec.LookPath are never
called with an empty string and reference the function ToolHas and the field
opts.Tool when implementing the validation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ba4fda90-48fa-4581-a7a1-11c486bdc37d

📥 Commits

Reviewing files that changed from the base of the PR and between 687a58c and c3fba00.

📒 Files selected for processing (2)
  • v3/cmd/wails3/main.go
  • v3/internal/commands/tool_docker_mounts.go

@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/task_wrapper.go (1)

44-51: ⚡ Quick win

Restore WAILS_WARNINGS_FILE after wrapTask returns.

Line 49 sets process-global env state but never restores it. That can leak warnings routing across multiple wrapTask calls in the same process (tests or embedded usage), violating per-invocation scoping.

♻️ Proposed fix
-	if f, err := os.CreateTemp("", "wails-build-warnings-*"); err == nil {
-		f.Close()
-		os.Setenv(buildwarnings.EnvVar, f.Name())
-		defer buildwarnings.FlushAndPrint()
-	}
+	if f, err := os.CreateTemp("", "wails-build-warnings-*"); err == nil {
+		_ = f.Close()
+		prev, hadPrev := os.LookupEnv(buildwarnings.EnvVar)
+		_ = os.Setenv(buildwarnings.EnvVar, f.Name())
+		defer func() {
+			buildwarnings.FlushAndPrint()
+			if hadPrev {
+				_ = os.Setenv(buildwarnings.EnvVar, prev)
+			} else {
+				_ = os.Unsetenv(buildwarnings.EnvVar)
+			}
+		}()
+	}
🤖 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/task_wrapper.go` around lines 44 - 51, The code in
wrapTask sets the process-wide environment variable buildwarnings.EnvVar
(WAILS_WARNINGS_FILE) but never restores the prior value, leaking state across
invocations; modify the wrapTask logic around the os.CreateTemp block to capture
the previous environment value (e.g., os.LookupEnv(buildwarnings.EnvVar)) before
calling os.Setenv, then defer a restore that either os.Setenv back to the
previous value if present or os.Unsetenv if it was absent, while keeping the
existing deferred buildwarnings.FlushAndPrint() behavior; reference the
environment variable symbol buildwarnings.EnvVar and the wrapTask scope when
making this change.
🤖 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/task_wrapper.go`:
- Around line 44-51: The code in wrapTask sets the process-wide environment
variable buildwarnings.EnvVar (WAILS_WARNINGS_FILE) but never restores the prior
value, leaking state across invocations; modify the wrapTask logic around the
os.CreateTemp block to capture the previous environment value (e.g.,
os.LookupEnv(buildwarnings.EnvVar)) before calling os.Setenv, then defer a
restore that either os.Setenv back to the previous value if present or
os.Unsetenv if it was absent, while keeping the existing deferred
buildwarnings.FlushAndPrint() behavior; reference the environment variable
symbol buildwarnings.EnvVar and the wrapTask scope when making this change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 39edc0e5-688c-445a-b5fa-54a0c00d6f3b

📥 Commits

Reviewing files that changed from the base of the PR and between 3069a7d and 2df82b1.

📒 Files selected for processing (6)
  • docs/src/content/docs/guides/cli.mdx
  • v3/internal/buildwarnings/buildwarnings.go
  • v3/internal/buildwarnings/buildwarnings_test.go
  • v3/internal/commands/task.go
  • v3/internal/commands/task_wrapper.go
  • v3/internal/commands/tool_docker_mounts.go

@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/tool_docker_mounts_test.go (1)

187-197: ⚡ Quick win

Add test case for whitespace-only tool argument.

The PR objectives state that validation should "return an error when the tool argument is empty or only whitespace." The test currently only covers the empty string case (line 196), but should also verify that whitespace-only inputs like " " or " \t " produce an error.

✅ Suggested additional test case
 		{tool: stubName + "|nonexistent-wails-tool-xyz", want: "true"}, // first alternative found
 		{tool: "", wantErr: true},                                 // missing arg: error
+		{tool: "   ", wantErr: true},                              // whitespace-only: error
 	}
🤖 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/tool_docker_mounts_test.go` around lines 187 - 197, Add
a test case to cover whitespace-only "tool" inputs: extend the tests slice in
tool_docker_mounts_test.go (the tests variable) to include an entry where tool
is a whitespace-only string (e.g., "   " or "\t  ") and wantErr is true, so the
test verifies that validate/processing of the tool argument (the logic exercised
by the existing table-driven test for tool) returns an error for whitespace-only
inputs just like the empty-string case.
🤖 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/tool_docker_mounts_test.go`:
- Around line 187-197: Add a test case to cover whitespace-only "tool" inputs:
extend the tests slice in tool_docker_mounts_test.go (the tests variable) to
include an entry where tool is a whitespace-only string (e.g., "   " or "\t  ")
and wantErr is true, so the test verifies that validate/processing of the tool
argument (the logic exercised by the existing table-driven test for tool)
returns an error for whitespace-only inputs just like the empty-string case.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 43d21fb5-6143-4ebc-8129-16fd2b04931b

📥 Commits

Reviewing files that changed from the base of the PR and between 2df82b1 and 24153d6.

📒 Files selected for processing (2)
  • v3/internal/commands/tool_docker_mounts.go
  • v3/internal/commands/tool_docker_mounts_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • v3/internal/commands/tool_docker_mounts.go

Replaces `wails3 tool has-cc` with `wails3 tool has cc` — a generic
subcommand that accepts the capability name as a positional argument.
Easier to extend for future capability checks without adding new subcommands.

- Rename HasCCOptions → HasOptions with pos:"1" Tool field
- Rename ToolHasCC → ToolHas, dispatch on opts.Tool with error on unknown
- Update main.go registration from "has-cc" to "has"
- Update linux Taskfile template to use `wails3 tool has cc`
- Update test to cover both the cc case and unknown-tool error path
Instead of erroring on unrecognised tool names, do a plain exec.LookPath
so `wails3 tool has git`, `wails3 tool has node`, etc. all work without
needing explicit cases.  "cc" keeps its special logic (gcc OR clang).
Restores `wails3 tool has-cc` as a thin wrapper around `ToolHas` so
existing scripts and Taskfiles outside the generated templates continue
to work. The implementation simply calls ToolHas(&HasOptions{Tool: "cc"}).
Replace the hardcoded "cc" alias with a generic pipe-separated syntax:
`wails3 tool has gcc|clang` checks for gcc OR clang in PATH.

- Remove the "cc" switch case; split on "|" and LookPath each alternative
- Update has-cc alias to forward to gcc|clang instead of cc
- Update Taskfile template to use `wails3 tool has gcc|clang`
- Update descriptions and tests accordingly
Introduces internal/buildwarnings: a lightweight file-based channel that
lets subprocess tool commands (e.g. wails3 tool has-cc) append warnings
that are then printed together at the end of the build.

How it works:
- wrapTask() creates a temp file and sets WAILS_WARNINGS_FILE in the
  process environment before running any task. Child processes inherit it.
- buildwarnings.Add(source, message) appends a tab-separated record to
  the file. No-ops when WAILS_WARNINGS_FILE is unset.
- buildwarnings.FlushAndPrint() reads, pretty-prints, and removes the file.
  Called in wrapTask's defer (success path) and in fatal() before os.Exit
  (failure path), so warnings surface regardless of build outcome.

ToolHasCC now calls buildwarnings.Add("tool has-cc", "...") before
forwarding to ToolHas, so any project still using wails3 tool has-cc
will see a deprecation notice at the end of their next build.

Docs: add tool has, tool has-cc (deprecated), tool lipo, tool capabilities,
and tool docker-mounts to the CLI reference.
…cutable

Address Copilot review comments:
- Return an error when the tool argument is empty or whitespace-only,
  so `wails3 tool has` (missing arg) fails clearly rather than
  silently printing "false" and exiting 0.
- Rewrite TestToolHas to create a stub executable in a temp dir and
  prepend it to PATH, so every assertion checks the exact output
  ("true"/"false") against a controlled environment rather than
  relying on whatever tools happen to be installed on the host.
os.Setenv is process-wide; without a restore the env var leaks across
back-to-back wrapTask calls (visible in tests). Capture the prior value
with os.LookupEnv before setting and restore (Setenv/Unsetenv) in the
same deferred closure that calls FlushAndPrint.
The empty-Tool check was already added; extend the same condition to
cover a nil opts pointer so ToolHas never reaches opts.Tool on a nil
receiver.
The alias check previously only asserted out1 == out2 without asserting
the actual value — still the same pattern flagged by the review comment.
Add a gcc stub to the same temp dir so both ToolHasCC and
ToolHas("gcc|clang") are guaranteed to output exactly "true", regardless
of what the host has installed.
@leaanthony leaanthony force-pushed the feat/tool-has-command branch from 6c0a4e1 to 094b08f Compare June 3, 2026 13:18
@leaanthony leaanthony merged commit 0464978 into master Jun 13, 2026
21 of 25 checks passed
@leaanthony leaanthony deleted the feat/tool-has-command branch June 13, 2026 23:00
leaanthony added a commit that referenced this pull request Jun 14, 2026
#5600)

* fix(v3/ci): quote pipe in 'wails3 tool has gcc|clang' Taskfile command

The shell in Task's `sh:` var interprets the bare `|` as a pipe, running
`wails3 tool has gcc` and piping its output to `clang`. clang exits 1
with "no input files", failing all Linux template builds.

Fix: wrap the argument in shell double-quotes so the pipe is passed
literally to the Go program, which splits on `|` to check each tool.

Regressed in #5533 (0464978).

* fix(v3/generator): disable workspace mode when loading packages for binding generation

Go 1.25 changed behaviour for modules nested inside a Go workspace but not
listed as workspace members: packages.Load returns the package with errors,
leaving TypesInfo.Instances empty. The binding generator then finds zero
services, produces no output, and the frontend vite build fails with
'Cannot find module ../bindings/<pkg>'.

Fix: set GOWORK=off in the packages.Config.Env for both ResolvePatterns
and LoadPackages. The binding generator analyses source code in isolation
and never needs workspace-level module routing; the module's own go.mod
replace directives are still honoured when GOWORK=off.

Fixes all Test Templates CI failures on ubuntu/macos/windows.

* fix(v3/ci): register generated template project in workspace before build

Go 1.25 rejects packages in a module that is nested under the workspace
root but not listed in go.work — packages.Load returns errors that leave
TypesInfo.Instances empty, causing the bindings generator to find zero
services and produce no frontend/bindings/ output.

The template test step creates a new project inside the repo tree (which
is a Go workspace), so the project module is nested but unlisted. Fix by
running 'go work use .' in the generated project directory before
'wails3 build'. This registers the project as a proper workspace member
so Go 1.25 loads its packages correctly and bindings are generated.

Revert the earlier GOWORK=off approach in load.go — disabling workspace
mode in the generator would break local development workflows where
go.work ties v3 and webview2 changes together.

* ci: re-trigger CI run (artifact unavailable after re-run)
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.

2 participants