""" Build helpers for the Prole installer (root-level package). UI-agnostic command composition for the Prole macOS app build. """ from __future__ import annotations from pathlib import Path from typing import Callable from .milestone import Milestone from .state import InstallerState def get_build_command(project_root: Path, env: str | None) -> str: """Return the Prole app build command with an env comment suffix. Example output: cd "/path/to/repo" && PROLE_VERBOSE=1 bash -lc 'export PROLE_HOME="${PROLE_HOME:-$HOME/.prole}"; "$PROLE_HOME/env.sh" ./prole-tools-app/build.sh build --verbose' # Dev """ env_label = (env or "Dev").strip().title() prole_root = str(project_root) # Ensure we apply the stable bash environment via the executable env.sh wrapper # Avoid static analyzers tripping on $PROLE_HOME by breaking the token env_default = '"${' + 'PROLE_HOME:-$HOME/.prole}"' prole_home_token = '"$' + 'PROLE_HOME"' cmd = f"cd \"{prole_root}\" && PROLE_VERBOSE=1 bash -lc 'export PROLE_HOME={env_default}; {prole_home_token}/env.sh ./prole-tools-app/build.sh build --verbose' # {env_label}" return cmd class BuildMilestone(Milestone): """UI-agnostic build milestone.""" def __init__( self, project_root: Path, env: str | None = None, next_id: str | None = None ): super().__init__("build", "Build") self.project_root = Path(project_root) self.env = env self._next_id = next_id def validate(self, state: InstallerState) -> list[str] | None: if not self.project_root.exists(): return [f"Project root not found: {self.project_root}"] return None def execute( self, state: InstallerState, progress: Callable[[str, float | None], None] | None = None, ) -> None: cmd = get_build_command(self.project_root, self.env) state.data["build.command"] = cmd if progress: progress("Build command prepared", 1.0) def next(self, state: InstallerState) -> str | None: return self._next_id # ---------------- Screen (UI) helpers ---------------- def create_build_page(app): """Create the Build page UI and register it via knoe.main.""" import tkinter as tk from tkinter import ttk, scrolledtext from . import main as inst_main f = ttk.Frame(app.page_area) f.place(x=0, y=0, relwidth=1, relheight=1) ttk.Label(f, text="Build", style="Title.TLabel").pack( anchor="w", padx=24, pady=(24, 6) ) ttk.Label( f, text="Choose a target and build the artifacts.", style="Body.TLabel" ).pack(anchor="w", padx=24) wrap = ttk.Frame(f) wrap.pack(anchor="w", padx=24, pady=12) ttk.Label(wrap, text="Target Environment:", style="Body.TLabel").pack(side="left") app.deploy_env_var = tk.StringVar(value="Dev") ttk.Combobox( wrap, textvariable=app.deploy_env_var, values=["Dev", "Service", "Prod"], state="readonly", width=18, ).pack(side="left", padx=10) # Build output console app.build_output = scrolledtext.ScrolledText( f, height=12, bg="#fafafa", fg="#1d1d1f" ) app.build_output.pack(fill="both", expand=True, padx=24, pady=12) inst_main.register_page(app, "build", f) return f