66import datetime
77import json
88import os
9+ import platform
910import pprint
1011import shutil
1112import subprocess
@@ -168,6 +169,94 @@ def notify_dockerhub_secrets() -> None:
168169 print ("=" * 70 + "\n " )
169170
170171
172+ def ensure_uv_installed () -> None :
173+ """Opportunistically ensure uv is installed on the system."""
174+ try :
175+ # Check if uvx is already available
176+ if shutil .which ("uvx" ):
177+ LOG .info ("uvx is already available in PATH" )
178+ return
179+
180+ # Check if uv is installed but uvx might not be in PATH
181+ if shutil .which ("uv" ):
182+ LOG .info ("uv is available but uvx might not be in PATH" )
183+ return
184+
185+ print ("\n " + "=" * 70 )
186+ print ("Installing uv package manager..." )
187+ print ("=" * 70 )
188+
189+ system = platform .system ()
190+
191+ if system in ["Linux" , "Darwin" ]: # Unix-like systems (Linux and macOS)
192+ # Use the standalone installer for Unix-like systems
193+ install_cmd = "curl -LsSf https://astral.sh/uv/install.sh | sh"
194+ subprocess .run (install_cmd , shell = True , check = True , capture_output = True , timeout = 30 )
195+
196+ # Add to PATH for current session
197+ home = Path .home ()
198+ uv_bin = home / ".local" / "bin"
199+ if uv_bin .exists ():
200+ os .environ ["PATH" ] = f"{ uv_bin } :{ os .environ .get ('PATH' , '' )} "
201+
202+ elif system == "Windows" :
203+ # Use PowerShell for Windows
204+ install_cmd = [
205+ "powershell" ,
206+ "-ExecutionPolicy" ,
207+ "ByPass" ,
208+ "-c" ,
209+ "irm https://astral.sh/uv/install.ps1 | iex" ,
210+ ]
211+ subprocess .run (install_cmd , check = True , capture_output = True , timeout = 30 )
212+
213+ # Add to PATH for current session on Windows
214+ home = Path .home ()
215+ uv_bin = home / ".local" / "bin"
216+ if uv_bin .exists ():
217+ os .environ ["PATH" ] = f"{ uv_bin } ;{ os .environ .get ('PATH' , '' )} "
218+ else :
219+ LOG .info (f"Unsupported platform for automatic uv installation: { system } " )
220+ return
221+
222+ print ("uv has been successfully installed" )
223+ print ("=" * 70 + "\n " )
224+
225+ except Exception as e :
226+ # Log the error but don't fail - this is opportunistic
227+ LOG .info (f"Could not install uv automatically (this is optional): { e } " )
228+ # Don't print anything to the user - this is an optional step
229+
230+
231+ def install_zenable_mcp () -> None :
232+ """Opportunistically install zenable-mcp using uvx."""
233+ try :
234+ # Try to use uvx first
235+ if shutil .which ("uvx" ):
236+ print ("\n " + "=" * 70 )
237+ print ("Installing zenable-mcp..." )
238+ print ("=" * 70 )
239+ subprocess .run (["uvx" , "zenable-mcp@latest" , "install" ], check = True , timeout = 60 )
240+ print ("zenable-mcp has been successfully installed" )
241+ print ("=" * 70 + "\n " )
242+ # Fallback to uv run if uvx is not available but uv is
243+ elif shutil .which ("uv" ):
244+ print ("\n " + "=" * 70 )
245+ print ("Installing zenable-mcp..." )
246+ print ("=" * 70 )
247+ subprocess .run (["uv" , "run" , "--with" , "zenable-mcp" , "zenable-mcp" , "install" ], check = True , timeout = 60 )
248+ print ("zenable-mcp has been successfully installed" )
249+ print ("=" * 70 + "\n " )
250+ else :
251+ # No uv/uvx available, silently skip
252+ LOG .info ("Neither uvx nor uv found in PATH. Skipping zenable-mcp installation." )
253+
254+ except Exception as e :
255+ # Log the error but don't fail - this is opportunistic
256+ LOG .info (f"Could not install zenable-mcp automatically (this is optional): { e } " )
257+ # Don't print error messages to the user - this is an optional step
258+
259+
171260def run_post_gen_hook ():
172261 """Run post generation hook"""
173262 try :
@@ -185,6 +274,10 @@ def run_post_gen_hook():
185274
186275 subprocess .run (["git" , "init" , "--initial-branch=main" ], capture_output = True , check = True )
187276
277+ # Ensure uv is installed and install zenable-mcp
278+ ensure_uv_installed ()
279+ install_zenable_mcp ()
280+
188281 # This is important for testing project generation for CI
189282 if (
190283 os .environ .get ("GITHUB_ACTIONS" ) == "true"
0 commit comments