Skip to content

Commit 244a449

Browse files
Make flet build work in CI environment (#4993)
* Do not force terminal in CI environment * Use sh/cmd.exe with "yes" to run sdk manager * Install more Android SDKs and tools * Fix Windows android installation * Fix windows Android SDK installation * Fix Windows android installation, again * Fix again * Another try * Finally fixed? * encoding="utf-8" * Try echo y * Remove input from processes.run * Output plain-text status in non-terminal * Flet version bumped to 0.27.3 * Escape sdk manager path
1 parent 1dc015d commit 244a449

File tree

6 files changed

+73
-47
lines changed

6 files changed

+73
-47
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Flet changelog
22

3+
## 0.27.3
4+
5+
* Fixes to make `flet build` work in CI environment ([#4993](https://github.com/flet-dev/flet/issues/4993))
6+
37
## 0.27.2
48

59
* Error on second flet build run "Because {app} depends on flet_{package} from path which doesn't exist" ([#4955](https://github.com/flet-dev/flet/issues/4955))

packages/flet/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 0.27.3
2+
3+
* Fixes to make `flet build` work in CI environment ([#4993](https://github.com/flet-dev/flet/issues/4993))
4+
15
# 0.27.2
26

37
* Error on second flet build run "Because {app} depends on flet_{package} from path which doesn't exist" ([#4955](https://github.com/flet-dev/flet/issues/4955))

packages/flet/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: flet
22
description: Write entire Flutter app in Python or add server-driven UI experience into existing Flutter app.
33
homepage: https://flet.dev
44
repository: https://github.com/flet-dev/flet/packages/flet
5-
version: 0.27.2
5+
version: 0.27.3
66

77
# This package supports all platforms listed below.
88
platforms:

sdk/python/packages/flet-cli/src/flet_cli/commands/build.py

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,15 @@
3838

3939
MINIMAL_FLUTTER_VERSION = version.Version("3.27.4")
4040

41+
no_rich_output = get_bool_env_var("FLET_CLI_NO_RICH_OUTPUT")
42+
4143
error_style = Style(color="red", bold=True)
4244
warning_style = Style(color="yellow", bold=True)
43-
console = Console(log_path=False, theme=Theme({"log.message": "green bold"}))
45+
console = Console(
46+
log_path=False,
47+
theme=Theme({"log.message": "green bold"}),
48+
force_terminal=not no_rich_output,
49+
)
4450
verbose1_style = Style(dim=True, bold=False)
4551
verbose2_style = Style(color="bright_black", bold=False)
4652

@@ -79,7 +85,7 @@ def __init__(self, parser: argparse.ArgumentParser) -> None:
7985
self.flutter_packages_temp_dir = None
8086
self.flutter_exe = None
8187
self.skip_flutter_doctor = get_bool_env_var("FLET_CLI_SKIP_FLUTTER_DOCTOR")
82-
self.no_rich_output = get_bool_env_var("FLET_CLI_NO_RICH_OUTPUT")
88+
self.no_rich_output = no_rich_output
8389
self.current_platform = platform.system()
8490
self.platforms = {
8591
"windows": {
@@ -725,7 +731,7 @@ def flutter_version_valid(self):
725731
return False
726732

727733
def install_flutter(self):
728-
self.status.update(
734+
self.update_status(
729735
f"[bold blue]Installing Flutter {MINIMAL_FLUTTER_VERSION}..."
730736
)
731737
from flet_cli.utils.flutter import install_flutter
@@ -773,7 +779,7 @@ def install_flutter(self):
773779
def install_jdk(self):
774780
from flet_cli.utils.jdk import install_jdk
775781

776-
self.status.update(f"[bold blue]Installing JDK...")
782+
self.update_status(f"[bold blue]Installing JDK...")
777783
jdk_dir = install_jdk(self.log_stdout, progress=self.progress)
778784
self.env["JAVA_HOME"] = jdk_dir
779785

@@ -806,7 +812,7 @@ def install_jdk(self):
806812
def install_android_sdk(self):
807813
from flet_cli.utils.android_sdk import AndroidSDK
808814

809-
self.status.update(f"[bold blue]Installing Android SDK...")
815+
self.update_status(f"[bold blue]Installing Android SDK...")
810816
self.env["ANDROID_HOME"] = AndroidSDK(
811817
self.env["JAVA_HOME"], self.log_stdout, progress=self.progress
812818
).install()
@@ -1207,7 +1213,7 @@ def create_flutter_project(self, second_pass=False):
12071213
# create a new Flutter bootstrap project directory, if non-existent
12081214
if not second_pass:
12091215
self.flutter_dir.mkdir(parents=True, exist_ok=True)
1210-
self.status.update(
1216+
self.update_status(
12111217
f'[bold blue]Creating Flutter bootstrap project from {template_url} with ref "{template_ref}"...'
12121218
)
12131219

@@ -1262,7 +1268,7 @@ def register_flutter_extensions(self):
12621268
shutil.move(self.flutter_packages_temp_dir, self.flutter_packages_dir)
12631269

12641270
if self.flutter_packages_dir.exists():
1265-
self.status.update(f"[bold blue]Registering Flutter user extensions...")
1271+
self.update_status(f"[bold blue]Registering Flutter user extensions...")
12661272

12671273
for fp in os.listdir(self.flutter_packages_dir):
12681274
if (self.flutter_packages_dir / fp / "pubspec.yaml").exists():
@@ -1401,7 +1407,7 @@ def customize_icons(self):
14011407
if hash.has_changed():
14021408

14031409
if copy_ops:
1404-
self.status.update(f"[bold blue]Customizing app icons...")
1410+
self.update_status(f"[bold blue]Customizing app icons...")
14051411
for op in copy_ops:
14061412
if self.verbose > 0:
14071413
console.log(
@@ -1416,7 +1422,7 @@ def customize_icons(self):
14161422
]
14171423
self.save_yaml(self.pubspec_path, updated_pubspec)
14181424

1419-
self.status.update(f"[bold blue]Generating app icons...")
1425+
self.update_status(f"[bold blue]Generating app icons...")
14201426

14211427
# icons
14221428
icons_result = self.run(
@@ -1632,7 +1638,7 @@ def customize_splash_images(self):
16321638
if hash.has_changed():
16331639

16341640
if copy_ops:
1635-
self.status.update(f"[bold blue]Customizing app splash images...")
1641+
self.update_status(f"[bold blue]Customizing app splash images...")
16361642
for op in copy_ops:
16371643
if self.verbose > 0:
16381644
console.log(
@@ -1646,7 +1652,7 @@ def customize_splash_images(self):
16461652
self.save_yaml(self.pubspec_path, updated_pubspec)
16471653

16481654
# splash screens
1649-
self.status.update(f"[bold blue]Generating splash screens...")
1655+
self.update_status(f"[bold blue]Generating splash screens...")
16501656
splash_result = self.run(
16511657
[
16521658
self.dart_exe,
@@ -1690,7 +1696,7 @@ def package_python_app(self):
16901696

16911697
hash = HashStamp(self.build_dir / ".hash" / "package")
16921698

1693-
self.status.update(f"[bold blue]Packaging Python app...")
1699+
self.update_status(f"[bold blue]Packaging Python app...")
16941700
package_args = [
16951701
self.dart_exe,
16961702
"run",
@@ -1905,7 +1911,7 @@ def flutter_build(self):
19051911
assert self.get_pyproject
19061912
assert self.template_data
19071913

1908-
self.status.update(
1914+
self.update_status(
19091915
f"[bold blue]Building [cyan]{self.platforms[self.options.target_platform]['status_text']}[/cyan]..."
19101916
)
19111917
# flutter build
@@ -2021,7 +2027,7 @@ def copy_build_output(self):
20212027
assert self.out_dir
20222028
assert self.assets_path
20232029

2024-
self.status.update(
2030+
self.update_status(
20252031
f"[bold blue]Copying build to [cyan]{self.rel_out_dir}[/cyan] directory...",
20262032
)
20272033
arch = platform.machine().lower()
@@ -2148,6 +2154,12 @@ def run_flutter_doctor(self):
21482154
if flutter_doctor.returncode == 0 and flutter_doctor.stdout:
21492155
console.log(flutter_doctor.stdout, style=verbose1_style)
21502156

2157+
def update_status(self, status):
2158+
if self.no_rich_output:
2159+
console.log(status)
2160+
else:
2161+
self.status.update(status)
2162+
21512163
def log_stdout(self, message):
21522164
if self.verbose > 0:
21532165
console.log(

sdk/python/packages/flet-cli/src/flet_cli/utils/android_sdk.py

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,26 @@ def _install_package(self, home_dir: Path, package_name: str) -> int:
159159
return 0
160160

161161
self.log(f'Installing Android SDK package "{package_name}"')
162+
162163
p = self.run(
163-
[self.sdkmanager_exe(home_dir), package_name],
164+
(
165+
[
166+
"sh",
167+
"-c",
168+
f'yes | "{self.sdkmanager_exe(home_dir)}" "{package_name}"',
169+
]
170+
if platform.system() != "Windows"
171+
else [
172+
"cmd.exe",
173+
"/C",
174+
"echo",
175+
"y",
176+
"|",
177+
self.sdkmanager_exe(home_dir),
178+
package_name,
179+
]
180+
),
164181
env={"ANDROID_HOME": str(home_dir)},
165-
input="y\n" * 10,
166182
capture_output=False,
167183
)
168184
if p.returncode != 0:
@@ -172,13 +188,22 @@ def _install_package(self, home_dir: Path, package_name: str) -> int:
172188

173189
def _accept_licenses(self, home_dir: Path):
174190
self.log("Accepting Android SDK licenses")
191+
175192
p = self.run(
176-
[
177-
self.sdkmanager_exe(home_dir),
178-
"--licenses",
179-
],
193+
(
194+
["sh", "-c", f'yes | "{self.sdkmanager_exe(home_dir)}" --licenses']
195+
if platform.system() != "Windows"
196+
else [
197+
"cmd.exe",
198+
"/C",
199+
"echo",
200+
"y",
201+
"|",
202+
self.sdkmanager_exe(home_dir),
203+
"--licenses",
204+
]
205+
),
180206
env={"ANDROID_HOME": str(home_dir)},
181-
input="y\n" * 20,
182207
capture_output=False,
183208
)
184209
if p.returncode != 0:
@@ -199,7 +224,7 @@ def get_installed_packages(self, home_dir: Path):
199224
)
200225
return p.stdout
201226

202-
def run(self, args, env=None, cwd=None, input=None, capture_output=True):
227+
def run(self, args, env=None, cwd=None, capture_output=True):
203228

204229
self.log(f"Run subprocess: {args}")
205230

@@ -214,7 +239,6 @@ def run(self, args, env=None, cwd=None, input=None, capture_output=True):
214239
args,
215240
cwd if cwd else os.getcwd(),
216241
env=cmd_env,
217-
input=input,
218242
capture_output=capture_output,
219243
log=self.log,
220244
)

sdk/python/packages/flet-cli/src/flet_cli/utils/processes.py

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@
88
from ctypes import windll
99

1010

11-
def run(
12-
args, cwd, env: Optional[dict] = None, input=None, capture_output=True, log=None
13-
):
11+
def run(args, cwd, env: Optional[dict] = None, capture_output=True, log=None):
1412
if is_windows():
1513
# Source: https://stackoverflow.com/a/77374899/1435891
1614
# Save the current console output code page and switch to 65001 (UTF-8)
@@ -29,9 +27,9 @@ def run(
2927
cwd=cwd,
3028
capture_output=True,
3129
text=True,
32-
encoding="utf8",
30+
encoding="utf-8",
3331
env=cmd_env,
34-
errors="replace"
32+
errors="replace",
3533
)
3634
else:
3735
process = subprocess.Popen(
@@ -41,15 +39,9 @@ def run(
4139
stdout=subprocess.PIPE,
4240
stderr=subprocess.STDOUT,
4341
text=True,
44-
encoding="utf8",
42+
encoding="utf-8",
4543
env=cmd_env,
46-
errors="replace"
47-
)
48-
49-
input_iterator = (
50-
iter(input)
51-
if isinstance(input, list)
52-
else iter(input.split("\n")) if isinstance(input, str) else iter([])
44+
errors="replace",
5345
)
5446

5547
try:
@@ -60,16 +52,6 @@ def run(
6052
if stdout_line and log:
6153
log(stdout_line.rstrip())
6254

63-
# Check if process is waiting for input
64-
if process.poll() is None and process.stdin:
65-
try:
66-
next_input = next(input_iterator) + "\n"
67-
process.stdin.write(next_input)
68-
process.stdin.flush()
69-
except StopIteration:
70-
# If no more input, close stdin to signal end
71-
process.stdin.close()
72-
7355
# Break when the process ends and buffers are empty
7456
if not stdout_line and process.poll() is not None:
7557
break

0 commit comments

Comments
 (0)