@@ -83,17 +83,53 @@ fn filter_install_command(cmd: &str) -> String {
8383 "apt-get" , "apt " , "dpkg" , "yum " , "dnf " , "pacman " , "apk " ,
8484 ] ;
8585
86+ // Runtime packages that are already installed by runtime_install_command.
87+ // Strip these apt-get install commands to avoid "held broken packages" conflicts.
88+ let redundant_runtime_packages = [
89+ "golang" , "nodejs" , "npm" , "node" , "default-jdk" , "openjdk" ,
90+ ] ;
91+
8692 let parts: Vec < & str > = cmd. split ( "&&" ) . collect ( ) ;
8793 let processed: Vec < String > = parts
8894 . iter ( )
89- . map ( |p| {
95+ . filter_map ( |p| {
9096 let trimmed = p. trim ( ) ;
97+ if trimmed. is_empty ( ) {
98+ return None ;
99+ }
100+ let lower = trimmed. to_lowercase ( ) ;
101+ // Skip corepack enable (yarn/pnpm already installed globally by runtime)
102+ if lower. starts_with ( "corepack enable" ) || lower. starts_with ( "sudo corepack" ) {
103+ return None ;
104+ }
105+ // Skip redundant apt-get install of runtimes already handled
106+ if ( lower. contains ( "apt-get install" ) || lower. contains ( "apt install" ) )
107+ && redundant_runtime_packages. iter ( ) . any ( |pkg| lower. contains ( pkg) )
108+ // Keep if it also installs other packages (heuristic: >3 packages)
109+ && !lower. contains ( "build-essential" )
110+ {
111+ // Check if this ONLY installs runtime packages
112+ let non_runtime = trimmed. split_whitespace ( )
113+ . filter ( |w| !w. starts_with ( '-' ) && !redundant_runtime_packages. iter ( ) . any ( |pkg| w. to_lowercase ( ) . contains ( pkg) ) )
114+ . filter ( |w| ![ "sudo" , "apt-get" , "apt" , "install" , "update" , "&&" , "-y" , "-qq" ] . contains ( w) )
115+ . count ( ) ;
116+ if non_runtime == 0 {
117+ return None ; // pure runtime install, skip it
118+ }
119+ }
120+ // Also skip apt-get update if it's standalone (already done by runtime install)
121+ if lower == "sudo apt-get update" || lower == "apt-get update"
122+ || lower == "sudo apt-get update -qq" || lower == "apt-get update -qq"
123+ {
124+ return None ;
125+ }
126+
91127 if trimmed. starts_with ( "sudo " ) {
92- fix_pip_pep668 ( trimmed)
128+ Some ( fix_pip_pep668 ( trimmed) )
93129 } else if root_prefixes. iter ( ) . any ( |prefix| trimmed. starts_with ( prefix) ) {
94- fix_pip_pep668 ( & format ! ( "sudo {}" , trimmed) )
130+ Some ( fix_pip_pep668 ( & format ! ( "sudo {}" , trimmed) ) )
95131 } else {
96- fix_pip_pep668 ( trimmed)
132+ Some ( fix_pip_pep668 ( trimmed) )
97133 }
98134 } )
99135 . collect ( ) ;
@@ -717,6 +753,34 @@ async fn run_task_on_basilica(
717753 }
718754
719755 result. status = TaskStatus :: InstallingDeps ;
756+
757+ // Install base build tools + ensure python/pip/pytest are on PATH
758+ let base_tools = format ! (
759+ "sudo apt-get update -qq && \
760+ sudo apt-get install -y -qq git curl build-essential python3 python3-pip python3-venv unzip > /dev/null 2>&1 && \
761+ sudo ln -sf $(command -v python3) /usr/local/bin/python 2>/dev/null; \
762+ sudo ln -sf $(command -v pip3) /usr/local/bin/pip 2>/dev/null; \
763+ sudo python3 -m pip install --break-system-packages pytest 2>/dev/null; true"
764+ ) ;
765+ let ( _, _, exit) = ssh_exec ( host, port, user, & base_tools, timeout, ssh_key) . await ?;
766+ if exit != 0 {
767+ warn ! ( "[{}] Base tools install failed (exit {})" , task. id, exit) ;
768+ }
769+
770+ // Run runtime install (not filtered - installs Go/Node/Rust/Java from official sources)
771+ if let Some ( ref runtime_cmd) = task. workspace . runtime_install {
772+ info ! ( "[{}] Installing runtime on container: {}" , task. id, & runtime_cmd[ ..runtime_cmd. len( ) . min( 120 ) ] ) ;
773+ let cmd = format ! ( "cd {work_dir}/repo && {runtime_cmd}" ) ;
774+ let ( _, stderr, exit) = ssh_exec ( host, port, user, & cmd, timeout, ssh_key) . await ?;
775+ if exit != 0 {
776+ warn ! (
777+ "[{}] Runtime install failed on container (exit {}): {}" ,
778+ task. id, exit, & stderr[ ..stderr. len( ) . min( 500 ) ]
779+ ) ;
780+ }
781+ }
782+
783+ // Run project install commands (filtered for sudo/pip)
720784 if let Some ( ref install_cmds) = task. workspace . install {
721785 for cmd in install_cmds {
722786 let effective_cmd = filter_install_command ( cmd) ;
0 commit comments