Skip to content

fix(v3/darwin): strip template stubs from old-format Info.plist on update-build-assets - #5312

Merged
leaanthony merged 9 commits into
masterfrom
agent/engineer-mac/8d616a3b
May 10, 2026
Merged

leaanthony merged 9 commits into
masterfrom
agent/engineer-mac/8d616a3b

Conversation

@leaanthony

@leaanthony leaanthony commented May 3, 2026 •

Copy link
Copy Markdown
Member

Problem

wails3 update build-assets doesn't fully process older-format Info.plist templates. The outer {{if}}{{range}}{{end}} directives are stripped (treated as XML text nodes by the plist parser), but inner field literals like {{.Ext}}, {{.IconName}}, {{.Name}}, {{.Role}}, {{.Scheme}} survive as real string values and appear as garbage in the merged output.

Anyone who scaffolded a project on an older alpha and runs update:build-assets gets these stubs silently injected, resulting in an Info.plist that registers nonsense file associations and URL schemes.

Closes #5259

Fix

Added sanitizePlistDict / sanitizePlistValue helpers in v3/internal/commands/build-assets.go that recursively walk the parsed backup plist dict and discard any string value containing {{. Called in mergeBackupPlists immediately after plist.Unmarshal on the backup.

This removes template stubs while preserving real user-added keys (e.g. NSCameraUsageDescription).

Test

New TestOldFormatPlistMigration in v3/internal/commands/build-assets_test.go:

  • Feeds an old-format v2 Info.plist (with full {{if .Info.FileAssociations}}…{{range}}…{{end}} blocks) through UpdateBuildAssets
  • Asserts none of {{.Ext}}, {{.Name}}, {{.Role}}, {{.IconName}}, {{.Scheme}} appear in the output
  • Asserts custom non-template key NSCameraUsageDescription is preserved

All existing TestNestedPlistMerge subtests continue to pass.

Summary by CodeRabbit

  • Bug Fixes

    • Removed legacy template placeholder artifacts from generated configuration/plist files during updates, while preserving your custom values.
  • Tests

    • Added coverage to verify legacy placeholder removal and correct handling of containers that should remain or be dropped after sanitization.

Review Change Stack

…date-build-assets

Older wails projects (v2 / early v3 alpha) stored darwin/Info.plist as a
raw Go template with directives like {{if .Info.FileAssociations}} and inner
field references like {{.Ext}}, {{.Name}}, {{.Role}} embedded directly in
<string> elements. When update-build-assets merges the backed-up plist via
the XML plist parser, block-level directives are silently dropped as text
nodes but the inner <string>{{.Ext}}</string> values survive as literal
garbage strings, which then appear in the shipped Info.plist.

Fix: after parsing the backup plist dict, recursively sanitize it by
discarding any string value that contains "{{". This removes template stubs
while preserving real user-added keys (e.g. NSCameraUsageDescription).

Fixes #5259
Copilot AI review requested due to automatic review settings May 3, 2026 03:59
@coderabbitai

coderabbitai Bot commented May 3, 2026 •

Copy link
Copy Markdown
Contributor

Walkthrough

Sanitizes parsed backup macOS Info.plist data to drop Go-template stub strings before merging, adds recursive helpers for maps/arrays that prune containers emptied by sanitation, and includes tests verifying template-stub removal and container-preservation behavior.

Changes

Plist Template Sanitization

Layer / File(s) Summary
Sanitization Logic
v3/internal/commands/build-assets.go
Added sanitizePlistDict and sanitizePlistValue helper functions that recursively traverse plist maps and arrays, filtering out string entries containing Go-template syntax ({{) and pruning containers that become empty.
Integration
v3/internal/commands/build-assets.go
mergeBackupPlists now calls sanitization on the parsed backup dictionary before merging, removing template stubs from older-format plists.
Tests / Imports
v3/internal/commands/build-assets_test.go
Added strings import and tests: TestOldFormatPlistMigration verifies template placeholders like {{.Ext}}/{{.Scheme}} are removed while preserving real keys, and TestPreserveOriginallyEmptyContainers checks that originally-empty containers remain while containers emptied by sanitization are dropped.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

  • wailsapp/wails#4682: Modifies plist merge logic in v3/internal/commands/build-assets.go, including mergeBackupPlists and related merge/backup flow, so overlaps in the same function being enhanced here.

Suggested labels

size:M

Poem

🐰 I hopped through plists and found a nest of braces,
Stripped the old stubs out of hidden places,
Recursed with care through array and key,
Dropped empty shells, kept what should be—
Now the Info.plist sings clean new traces.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% 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 clearly summarizes the main change: stripping template stubs from old-format Info.plist during build-assets update. It directly reflects the core problem being solved.
Description check ✅ Passed The description is comprehensive and follows the template well, including problem statement, fix details, and test coverage. Most required sections are filled (Description, Fix, Test), though the explicit 'Type of change' checklist and 'Tested' platform checkboxes remain unchecked.
Linked Issues check ✅ Passed The PR fully addresses all objectives from issue #5259: sanitizes template stubs while preserving legitimate keys, provides reliable migration, and includes comprehensive tests to verify the fix prevents template syntax from surviving the migration.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the issue: modifications to mergeBackupPlists with new sanitization helpers, corresponding tests for old-format plist migration, and preservation of originally empty containers as specified.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/engineer-mac/8d616a3b

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.1)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


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

Fixes macOS Info.plist migration during wails3 update build-assets by sanitizing older raw-template stubs (e.g. {{.Ext}}) that can otherwise be merged into the generated plist and register nonsense file associations / URL schemes (issue #5259).

Changes:

  • Sanitize parsed backup plist values to drop string literals containing Go-template syntax before merging.
  • Add a regression test that runs UpdateBuildAssets on an old-format Info.plist and asserts template stubs are removed while user keys are preserved.

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.go Sanitizes backup plist dictionaries after unmarshal to strip Go-template stub strings before merge.
v3/internal/commands/build-assets_test.go Adds TestOldFormatPlistMigration to validate stub removal and preservation of real user-added keys.

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

Comment on lines +444 to +472
result := make(map[string]any, len(d))
for k, v := range d {
if sanitized, keep := sanitizePlistValue(v); keep {
result[k] = sanitized
}
}
return result
}

func sanitizePlistValue(v any) (any, bool) {
switch val := v.(type) {
case string:
if strings.Contains(val, "{{") {
return nil, false
}
return val, true
case map[string]any:
sanitized := sanitizePlistDict(val)
return sanitized, len(sanitized) > 0
case []any:
var result []any
for _, item := range val {
if sanitized, keep := sanitizePlistValue(item); keep {
result = append(result, sanitized)
}
}
return result, len(result) > 0
default:
return v, true

@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 (2)
v3/internal/commands/build-assets_test.go (1)

734-740: 💤 Low value

Consider widening the stub assertion to catch any {{ survivor, not just named fields.

The per-stub list covers the known template fields but would miss any new field references added to old templates in the future, and also wouldn't catch block-level directives (e.g. {{if, {{range}) if they somehow survived parsing. A single strings.Contains(contentStr, "{{") check would be a stricter, future-proof guard:

♻️ Proposed improvement
-// No template stub should survive in the output.
-stubs := []string{"{{.Ext}}", "{{.Name}}", "{{.Role}}", "{{.IconName}}", "{{.Scheme}}"}
-for _, stub := range stubs {
-    if strings.Contains(contentStr, stub) {
-        t.Errorf("Output Info.plist still contains template stub %q — old-format template was not sanitized correctly", stub)
-    }
-}
+// No Go template syntax should survive in the output.
+if strings.Contains(contentStr, "{{") {
+    t.Errorf("Output Info.plist still contains Go template syntax — old-format template was not sanitized correctly:\n%s", contentStr)
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@v3/internal/commands/build-assets_test.go` around lines 734 - 740, Replace
the per-stub loop check with a single assertion that fails if any template
delimiter remains: instead of iterating over stubs and calling
strings.Contains(contentStr, stub), call strings.Contains(contentStr, "{{") to
detect any surviving template markers (covers fields and block directives like
{{if}}/{{range}}); update the t.Errorf message in the test
(build-assets_test.go) to reflect a generic "{{" survivor rather than specific
named fields and keep referencing contentStr and the test's sanitization intent.
v3/internal/commands/build-assets.go (1)

460-470: 💤 Low value

Legitimate empty dicts/arrays in the backup plist will be silently dropped.

Both the map[string]any and []any cases use len(...) > 0 as the keep signal, which correctly drops containers that became empty because all their entries were stubs. However, it also drops containers that were already empty in the original plist (a valid, if unusual, construct). A user with <dict/> or <array/> entries unrelated to templates would lose those keys.

A minimal fix is to always keep the sanitized container regardless of whether it is empty — the important sanitization already happened on the individual entries:

🛠️ Proposed fix
 case map[string]any:
     sanitized := sanitizePlistDict(val)
-    return sanitized, len(sanitized) > 0
+    return sanitized, true
 case []any:
     var result []any
     for _, item := range val {
         if sanitized, keep := sanitizePlistValue(item); keep {
             result = append(result, sanitized)
         }
     }
-    return result, len(result) > 0
+    if result == nil {
+        result = []any{}
+    }
+    return result, true
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@v3/internal/commands/build-assets.go` around lines 460 - 470,
sanitizePlistValue currently drops containers (map[string]any and []any) when
the sanitized result is empty, which also removes legitimately empty dict/array
nodes from the original plist; change both container branches in
sanitizePlistValue to return the sanitized container with keep=true
unconditionally (i.e., return sanitized, true for the map[string]any case and
return result, true for the []any case) so that originally-empty containers are
preserved while individual stub entries remain sanitized via sanitizePlistDict
and the element loop.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@v3/internal/commands/build-assets_test.go`:
- Around line 734-740: Replace the per-stub loop check with a single assertion
that fails if any template delimiter remains: instead of iterating over stubs
and calling strings.Contains(contentStr, stub), call
strings.Contains(contentStr, "{{") to detect any surviving template markers
(covers fields and block directives like {{if}}/{{range}}); update the t.Errorf
message in the test (build-assets_test.go) to reflect a generic "{{" survivor
rather than specific named fields and keep referencing contentStr and the test's
sanitization intent.

In `@v3/internal/commands/build-assets.go`:
- Around line 460-470: sanitizePlistValue currently drops containers
(map[string]any and []any) when the sanitized result is empty, which also
removes legitimately empty dict/array nodes from the original plist; change both
container branches in sanitizePlistValue to return the sanitized container with
keep=true unconditionally (i.e., return sanitized, true for the map[string]any
case and return result, true for the []any case) so that originally-empty
containers are preserved while individual stub entries remain sanitized via
sanitizePlistDict and the element loop.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 74a04e64-16e6-4a23-bd7b-109c62dc8389

📥 Commits

Reviewing files that changed from the base of the PR and between 134217c and 0ac0304.

📒 Files selected for processing (2)
  • v3/internal/commands/build-assets.go
  • v3/internal/commands/build-assets_test.go

@leaanthony

Copy link
Copy Markdown
Member Author

Addressed review feedback from Copilot and CodeRabbit — two changes:

1. sanitizePlistValue — preserve legitimately empty containers (build-assets.go)

Both map[string]any and []any branches now return keep=true unconditionally. Only individual string entries containing {{ are dropped; a container that was already empty in the original plist (e.g. <array/>) is no longer silently removed.

case map[string]any:
    sanitized := sanitizePlistDict(val)
    return sanitized, true
case []any:
    result := make([]any, 0, len(val))
    for _, item := range val {
        if sanitized, keep := sanitizePlistValue(item); keep {
            result = append(result, sanitized)
        }
    }
    return result, true

2. Widen stub assertion in test (build-assets_test.go)

Replaced the per-field stub list with a single strings.Contains(contentStr, "{{") guard, which also covers block directives and any future template fields:

// No Go template syntax should survive in the output.
if strings.Contains(contentStr, "{{") {
    t.Errorf("Output Info.plist still contains Go template syntax — old-format template was not sanitized correctly:\n%s", contentStr)
}

All tests pass locally (TestOldFormatPlistMigration, TestNestedPlistMerge). The branch could not be force-updated via the fleet service (non-fast-forward rejection); please apply the two hunks above directly to the branch or force-push.

@leaanthony
leaanthony enabled auto-merge (rebase) May 3, 2026 10:01
@leaanthony

Copy link
Copy Markdown
Member Author

This PR is behind the master branch. Please rebase on the latest master before testing.

To rebase:

git fetch upstream master
git rebase upstream/master
git push --force-with-lease

@leaanthony leaanthony added Bug Something isn't working go Pull requests that update Go code v3 labels May 6, 2026
leaanthony and others added 3 commits May 6, 2026 23:42
Fixes docstring coverage error in PR #5312 by adding missing docstring
to the sanitizePlistValue helper function.

Co-authored-by: multica-agent <github@multica.ai>
…ation

The sanitizePlistValue function was dropping ALL empty dict/array
values, including those that were originally empty in user-provided
plists. This went beyond the stated goal of only stripping Go-template
stub strings.

Changes:
- Added checks to preserve containers that were originally empty
- Containers that become empty due to template removal are still dropped
- Updated docstring to clarify the new behavior
- Added comprehensive test coverage

Fixes PR #5312 review comment about preserving user-provided empty
containers.

Co-authored-by: multica-agent <github@multica.ai>

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

734-740: ⚡ Quick win

Inconsistency: Test checks specific stubs rather than any template syntax.

The PR objectives state the test was "widened to assert no Go-template syntax remains anywhere in the output by checking for any {{", but the implementation still checks only five specific template field stubs ({{.Ext}}, {{.Name}}, {{.Role}}, {{.IconName}}, {{.Scheme}}).

A broader check would be more robust and catch block directives ({{if}}, {{range}}, {{end}}) and any future template fields not in this list.

🔍 Suggested broader check
-	// No template stub should survive in the output.
-	stubs := []string{"{{.Ext}}", "{{.Name}}", "{{.Role}}", "{{.IconName}}", "{{.Scheme}}"}
-	for _, stub := range stubs {
-		if strings.Contains(contentStr, stub) {
-			t.Errorf("Output Info.plist still contains template stub %q — old-format template was not sanitized correctly", stub)
-		}
-	}
+	// No template syntax should survive in the output.
+	if strings.Contains(contentStr, "{{") {
+		t.Errorf("Output Info.plist still contains Go template syntax — old-format template was not sanitized correctly.\nContent: %s", contentStr)
+	}
🤖 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_test.go` around lines 734 - 740, The test
currently only checks specific template stubs in the stubs slice ({{.Ext}},
{{.Name}}, {{.Role}}, {{.IconName}}, {{.Scheme}}) against contentStr, which
misses other Go-template syntax like block directives; update the assertion to
search for any remaining "{{" (or a regex matching "{{.*}}"/"{{\\s*\\w") in
contentStr instead of iterating stubs so the test fails if any Go-template
syntax (e.g., {{if}}, {{range}}, {{end}} or new fields) remains; modify the code
that builds the stubs check (the stubs variable/loop) in build-assets_test.go to
a single containment/assertion against "{{" (or equivalent regex) with a clear
failure message.
🤖 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_test.go`:
- Around line 734-740: The test currently only checks specific template stubs in
the stubs slice ({{.Ext}}, {{.Name}}, {{.Role}}, {{.IconName}}, {{.Scheme}})
against contentStr, which misses other Go-template syntax like block directives;
update the assertion to search for any remaining "{{" (or a regex matching
"{{.*}}"/"{{\\s*\\w") in contentStr instead of iterating stubs so the test fails
if any Go-template syntax (e.g., {{if}}, {{range}}, {{end}} or new fields)
remains; modify the code that builds the stubs check (the stubs variable/loop)
in build-assets_test.go to a single containment/assertion against "{{" (or
equivalent regex) with a clear failure message.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 26498b5e-2b2a-4b3d-abc1-b0569731d5a0

📥 Commits

Reviewing files that changed from the base of the PR and between 0ac0304 and a1f1d6f.

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

@taliesin-ai

Copy link
Copy Markdown
Collaborator

Review feedback addressed

Both CodeRabbit/Copilot threads are now resolved. Here is a summary of what was changed and where to find the patch.

sanitizePlistValue drops legitimately-empty containers

Was (bug):

case map[string]any:
    sanitized := sanitizePlistDict(val)
    return sanitized, len(sanitized) > 0   // drops legitimately-empty user dicts

case []any:
    var result []any
    for _, item := range val {
        if sanitized, keep := sanitizePlistValue(item); keep {
            result = append(result, sanitized)
        }
    }
    return result, len(result) > 0         // drops legitimately-empty user arrays

Fixed:

case map[string]any:
    sanitized := sanitizePlistDict(val)
    return sanitized, true                 // always preserve containers

case []any:
    result := make([]any, 0, len(val))
    for _, item := range val {
        if sanitized, keep := sanitizePlistValue(item); keep {
            result = append(result, sanitized)
        }
    }
    return result, true                    // always preserve containers

Test assertion widened

The per-stub list ({{.Ext}}, {{.Name}}, etc.) was replaced with a single strings.Contains(contentStr, "{{") guard that catches any future template syntax automatically.

Cloudflare Pages failure

The Cloudflare Pages: wails-v3-site check failure is pre-existing and unrelated — this PR only touches build-assets.go and build-assets_test.go (no docs changes). The same failure appears on other open PRs that modify no docs.

Patch branch

The full fix (2 commits) is at taliesin-ai/wails:fix/pr5312-review-feedback-v2 if you want to cherry-pick or compare directly.


Taliesin is an AI agent. CC @leaanthony

@taliesin-ai

Copy link
Copy Markdown
Collaborator

Review feedback addressed

Both issues raised in the Copilot review have been fixed and verified.

Fix 1 — sanitizePlistValue drops legitimately empty containers

sanitizePlistValue was returning keep=false for any empty <dict/> or <array/> — it discarded user-written empty containers that contained no template stubs at all. Fixed by returning true unconditionally for both the map[string]any and []any cases:

 	case map[string]any:
 		sanitized := sanitizePlistDict(val)
-		return sanitized, len(sanitized) > 0
+		return sanitized, true
 	case []any:
-		var result []any
+		result := make([]any, 0, len(val))
 		for _, item := range val {
 			if sanitized, keep := sanitizePlistValue(item); keep {
 				result = append(result, sanitized)
 			}
 		}
-		return result, len(result) > 0
+		return result, true

Fix 2 — Test assertion only checked five hardcoded stub names

The test guarded against {{.Ext}}, {{.Name}}, {{.Role}}, {{.IconName}}, and {{.Scheme}} individually, but any other surviving {{…}} token would pass undetected. Broadened to a single strings.Contains(contentStr, "{{") check:

-	// No template stub should survive in the output.
-	stubs := []string{"{{.Ext}}", "{{.Name}}", "{{.Role}}", "{{.IconName}}", "{{.Scheme}}"}
-	for _, stub := range stubs {
-		if strings.Contains(contentStr, stub) {
-			t.Errorf("Output Info.plist still contains template stub %q — old-format template was not sanitized correctly", stub)
-		}
+	// No Go template syntax should survive in the output.
+	if strings.Contains(contentStr, "{{") {
+		t.Errorf("Output Info.plist still contains Go template syntax — old-format template was not sanitized correctly:\n%s", contentStr)
 	}

Test results (macOS Darwin 25.4.0)

=== RUN   TestOldFormatPlistMigration
--- PASS: TestOldFormatPlistMigration (0.01s)
--- PASS: TestNestedPlistMerge/simple_overwrite (0.00s)
--- PASS: TestNestedPlistMerge/preserve_existing_keys (0.00s)
--- PASS: TestNestedPlistMerge/nested_dict_merge (0.00s)
--- PASS: TestNestedPlistMerge/deeply_nested_merge (0.00s)
--- PASS: TestNestedPlistMerge/mixed_types_-_new_dict_replaces_non-dict (0.00s)
--- PASS: TestNestedPlistMerge/mixed_types_-_new_non-dict_replaces_dict (0.00s)
ok  	github.com/wailsapp/wails/v3/internal/commands	0.682s

Cloudflare Pages: wails-v3-site — pre-existing failure

This check fails on recently merged PRs (#5354, #5355, #5356) that contain only i18n changes with no Go code. It predates and is unrelated to this PR.


The two fixup commits are at 2bedcf3 and can be cherry-picked onto this branch.

CC @leaanthony


Taliesin is an AI agent. CC @leaanthony

@leaanthony
leaanthony disabled auto-merge May 10, 2026 14:12
@leaanthony
leaanthony merged commit 921e329 into master May 10, 2026
17 of 22 checks passed
@leaanthony
leaanthony deleted the agent/engineer-mac/8d616a3b branch May 10, 2026 14:12
fbbdev pushed a commit to fbbdev/wails that referenced this pull request May 10, 2026
…): strip template stubs from old-format Info.plist on update-build-assets
@taliesin-ai

Copy link
Copy Markdown
Collaborator

Addressing the unresolved review thread from @Copilot:

sanitizePlistValue currently drops all empty dict/array values by returning keep=false when len(sanitized)==0 / len(result)==0. That means a user-provided empty array/dict in the backup plist (with no template stubs) will be removed during migration...

This was fixed in commit a1f1d6f90c ("fix(v3/darwin): preserve originally empty containers in plist sanitization"), which was merged as part of this PR.

The current code in master follows exactly the approach Copilot suggested — originally-empty containers are preserved via an early guard, while containers that become empty only after stub removal are dropped (since they contained nothing but template garbage):

case map[string]any:
    if len(val) == 0 {
        return val, true  // originally empty → keep
    }
    sanitized := sanitizePlistDict(val)
    return sanitized, len(sanitized) > 0  // became empty after stub removal → drop

case []any:
    if len(val) == 0 {
        return val, true  // originally empty → keep
    }
    var result []any
    for _, item := range val {
        if sanitized, keep := sanitizePlistValue(item); keep {
            result = append(result, sanitized)
        }
    }
    return result, len(result) > 0  // became empty after stub removal → drop

The review concern is fully resolved. No further changes needed.

CC @leaanthony


Taliesin is an AI agent. CC @leaanthony

@taliesin-ai

Copy link
Copy Markdown
Collaborator

CI failure root cause — stale PR #5381

The "Run Go Tests v3" failures being flagged against this PR are caused by PR #5381, which is still open and stale after this PR was merged.

When CI runs PR #5381's virtual merge commit it picks up TestPreserveOriginallyEmptyContainers from master (added here in this PR's squash), but applies PR #5381's older mapsEqual that uses av != bv (not reflect.DeepEqual). Comparing []any{} with == panics at runtime, taking down the entire internal/commands package test run on every platform.

This PR itself is clean. Master currently has all the correct fixes:

I've posted a close request on PR #5381 to remove the CI blocker.

CC @leaanthony


Taliesin is an AI agent. CC @leaanthony

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

Labels

Bug Something isn't working go Pull requests that update Go code v3

Projects

None yet

Development

Successfully merging this pull request may close these issues.

wails3 update build-assets leaves stub {{.Ext}}/{{.Role}}/{{.Scheme}} literals when migrating older-format Info.plist

3 participants