enhance build process to handle locked artifacts and ensure directory creation

This commit is contained in:
Ross
2025-11-24 13:43:15 +00:00
parent f0f50381ec
commit b40e802627
+51 -4
View File
@@ -4,6 +4,8 @@ from pathlib import Path
import PyInstaller.__main__ import PyInstaller.__main__
import typer import typer
from rich import print from rich import print
import time
from datetime import datetime
app = typer.Typer() app = typer.Typer()
@@ -70,17 +72,62 @@ def build(build: bool = True, copy: bool = True, test: bool = False, dest: str |
except Exception as e: except Exception as e:
print(f"Warning: couldn't locate pythonnet runtime: {e}") print(f"Warning: couldn't locate pythonnet runtime: {e}")
# Ensure dist/work/spec directories exist
dist_dir = project_root / "dist" / "test"
work_dir = project_root / "build" / "test"
spec_dir = project_root / "build" / "specs"
dist_dir.mkdir(parents=True, exist_ok=True)
work_dir.mkdir(parents=True, exist_ok=True)
spec_dir.mkdir(parents=True, exist_ok=True)
# Decide build name and try to remove any locked previous artifact.
base_name = "Uploader_test"
output_exe = dist_dir / f"{base_name}.exe"
def try_remove_with_retries(path: Path, retries: int = 5, delay: float = 0.5) -> bool:
"""Try to remove a file with retries and backoff. Returns True if removed or not present."""
if not path.exists():
return True
for attempt in range(retries):
try:
path.unlink()
print(f"Removed existing file: {path}")
return True
except PermissionError:
# Try to move/rename it out of the way
try:
backup = path.with_suffix(f".old.{int(time.time())}")
path.rename(backup)
print(f"Renamed locked file to: {backup}")
return True
except Exception:
pass
print(f"File locked, retrying in {delay} seconds ({attempt+1}/{retries})")
time.sleep(delay)
delay *= 1.5
except Exception as e:
print(f"Failed to remove existing file {path}: {e}")
return False
return False
name_used = base_name
if not try_remove_with_retries(output_exe):
# If the previous artifact is locked, fall back to a unique name to avoid build failure
ts = datetime.now().strftime("%Y%m%dT%H%M%S")
name_used = f"{base_name}_{ts}"
print(f"Previous artifact appears locked; building as {name_used} to avoid PermissionError")
PyInstaller.__main__.run([ PyInstaller.__main__.run([
str(project_root / "nice.py"), str(project_root / "nice.py"),
"--onefile", "--onefile",
"--name", "--name",
"Uploader_test", name_used,
"--distpath", "--distpath",
str(project_root / "dist" / "test"), str(dist_dir),
"--workpath", "--workpath",
str(project_root / "build" / "test"), str(work_dir),
"--specpath", "--specpath",
str(project_root / "build" / "specs"), str(spec_dir),
] + add_data_args + add_binary_args + [ ] + add_data_args + add_binary_args + [
# add some common hidden imports that PyInstaller sometimes misses # add some common hidden imports that PyInstaller sometimes misses
"--hidden-import", "--hidden-import",