fix(`flet build`)!: keep system directories on the Flutter subprocess PATH (#6815)
* fix(`flet build`): keep system directories on the Flutter subprocess PATH
While provisioning its own Flutter SDK, `install_flutter()` rebuilt the
`PATH` handed to every Flutter subprocess by deleting each directory that
merely contained a file named `flutter` or `dart` (or a `.bat`/`.cmd`
variant), rather than just prepending the SDK it had installed.
A `/usr/bin/dart` therefore cost the child environment all of `/usr/bin` -
and on a merged-`/usr` distribution `/bin` with it, since the check follows
symlinks. Flutter's launcher is a `#!/usr/bin/env bash` script, so with no
`bash` left to find the first build died with:
/usr/bin/env: 'bash': No such file or directory
Even where `bash` survived elsewhere, losing a system `bin` directory
stripped the `git`, `unzip` and `java` that Flutter's own `shared.sh` and
the Gradle build require. The failure cleared itself on the next run, which
re-used the installed SDK and skipped this code entirely - hence the
intermittent reports.
Prepend the managed SDK and leave the inherited `PATH` otherwise intact.
That is sufficient for it to win: `PATH` lookup is first-match, Flet invokes
`flutter`/`dart` by absolute path anyway, and the launcher resolves
`FLUTTER_ROOT` from its own script location rather than from `PATH`.
Also guard the empty-`PATH` case, which previously emitted a trailing
separator - an empty `PATH` entry, which resolves to the current directory.
Affects `flet build`, `flet debug`, `flet test`, `flet devices` and
`flet emulators`.
Closes #5118
* refactor!: remove `flet.utils.cleanup_path()`
It existed only to strip rival `flutter`/`dart` directories out of the
`PATH` given to Flutter subprocesses, which is the cause of #5118 and is no
longer done. Its single caller in `flet_cli` is gone, so remove the helper
and its `flet.utils` export.
BREAKING CHANGE: `flet.utils.cleanup_path()` is no longer available. It was
an internal helper with no replacement; nothing in a Flet app should call it.
* fix(`flet test`): never put the current directory on the test subprocess PATH
`_flutter_path_env()` prepends the provisioned Flutter SDK the same way
`install_flutter()` does, and had the same latent flaw: with an empty
inherited `PATH` the join emitted a trailing separator, and an empty `PATH`
entry resolves to the current working directory.
Unreachable in practice - a missing `PATH` makes the `flutter --version`
probe crash before provisioning completes, so `install_flutter()` runs and
supplies its own guarded value - but the two builders should not differ.
No changelog entry: the guarded case cannot be reached from a released code
path, so no user was affected.
* docs(changelog): link the 1.0.0 entries to their pull request
Both bullets now end with the canonical `([#NNNN](...)) by @author.` form the
rest of the section uses. The bug-fix bullet keeps its `#5118` reference in
prose rather than in the trailing slot, which belongs to the PR link.
* test(cli): keep the `flet test` PATH assertions OS-agnostic
`_flutter_path_env()` derives the SDK bin directory with
`str(Path(cmd.flutter_exe).parent)`, which yields backslash-separated paths
on Windows, so asserting against a hard-coded POSIX literal failed there.
Build the fixture paths from `os.sep` with `os.path.join` and assert against
that same constant, so the expectation is the test's own input rather than a
platform-specific literal. `TestFlutterPathEnv` was already safe: the code
and the assertion both go through `os.path.join`.
Only the unit-test job's Linux runner exercises these today, so nothing was
red - this keeps the suite green for contributors on Windows.
* fix(`Chip`): `delete_icon_tooltip` never reached the delete icon
The Dart side read the property as `delete_button_tooltip` while Python
defines and sends `delete_icon_tooltip`, so `getString` never found the
key, `InputChip.deleteButtonTooltipMessage` stayed null, and setting the
property did nothing.
Fixed on the Dart side: `delete_icon_tooltip` is the shipped public API
and pairs with `delete_icon`, so renaming the Python field would be a
breaking change for no gain. Each name occurred exactly once in the repo.
This is one instance of a broader class: the Python/Dart property contract
is untyped string keys, a mismatch is a silent no-op rather than an error,
and nothing tests it. A repo-wide scan finds 14 more broken keys across
Semantics, Tabs, CupertinoAppBar, DropdownM2, form fields, Rive, charts
and datatable2. T
TheEthicalBoy committed
f62ab7d67d680186dba4e241d8280fbe00a586f8
Parent: 06c519f
Committed by GitHub <noreply@github.com>
on 9/4/2026, 9:36:41 PM