From 5593cca2a28de7d0638e3eb9598a296e522748a9 Mon Sep 17 00:00:00 2001 From: Gregor Sturm Date: Mon, 29 Jun 2026 09:13:09 +0200 Subject: [PATCH] Reorganize runner setup scripts --- packer/cirun-runner.pkr.hcl | 17 ++- packer/scripts/01_setup-system.sh | 57 +++++++++ packer/scripts/02_install-docker.sh | 33 +++++ packer/scripts/03_install-nvidia.sh | 86 +++++++++++++ packer/scripts/04_install-ci-tools.sh | 52 ++++++++ packer/scripts/99_cleanup.sh | 13 ++ packer/scripts/disable-upgrades.sh | 35 ------ packer/scripts/install-docker.sh | 42 ------- packer/scripts/install-nvidia-drivers.sh | 148 ----------------------- packer/scripts/preinstall-tools.sh | 60 --------- 10 files changed, 248 insertions(+), 295 deletions(-) create mode 100755 packer/scripts/01_setup-system.sh create mode 100755 packer/scripts/02_install-docker.sh create mode 100755 packer/scripts/03_install-nvidia.sh create mode 100755 packer/scripts/04_install-ci-tools.sh create mode 100755 packer/scripts/99_cleanup.sh delete mode 100644 packer/scripts/disable-upgrades.sh delete mode 100644 packer/scripts/install-docker.sh delete mode 100755 packer/scripts/install-nvidia-drivers.sh delete mode 100644 packer/scripts/preinstall-tools.sh diff --git a/packer/cirun-runner.pkr.hcl b/packer/cirun-runner.pkr.hcl index f89f094..16d65c7 100644 --- a/packer/cirun-runner.pkr.hcl +++ b/packer/cirun-runner.pkr.hcl @@ -100,28 +100,25 @@ build { "source.amazon-ebs.ubuntu" ] + # System preparation and shared prerequisites must run first so the later + # installers never hit a missing tool (unzip, gcc, gnupg, ...). provisioner "shell" { - script = "scripts/disable-upgrades.sh" + script = "scripts/01_setup-system.sh" } provisioner "shell" { - script = "scripts/install-docker.sh" + script = "scripts/02_install-docker.sh" } provisioner "shell" { - script = "scripts/install-nvidia-drivers.sh" + script = "scripts/03_install-nvidia.sh" } provisioner "shell" { - script = "scripts/preinstall-tools.sh" + script = "scripts/04_install-ci-tools.sh" } provisioner "shell" { - inline = [ - "sudo apt-get update", - "sudo apt-get upgrade -y", - "sudo apt-get autoremove -y", - "sudo apt-get autoclean" - ] + script = "scripts/99_cleanup.sh" } } \ No newline at end of file diff --git a/packer/scripts/01_setup-system.sh b/packer/scripts/01_setup-system.sh new file mode 100755 index 0000000..62f4647 --- /dev/null +++ b/packer/scripts/01_setup-system.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +# Prepare the base system: disable unattended upgrades and install every +# common package the later provisioning steps rely on. Installing all shared +# prerequisites up front keeps the individual installer scripts from failing +# on missing tools (e.g. unzip, gcc) and gives us a single apt update/upgrade. +set -euo pipefail +export DEBIAN_FRONTEND=noninteractive + +echo "==> Disabling automatic upgrades and updates" +# Stop, disable and mask the periodic apt units so they cannot race with our +# provisioning (which would hold the dpkg lock) or mutate the image post-build. +apt_units=(apt-daily.timer apt-daily-upgrade.timer apt-daily.service apt-daily-upgrade.service) +for unit in "${apt_units[@]}"; do + sudo systemctl stop "$unit" 2>/dev/null || true + sudo systemctl disable "$unit" 2>/dev/null || true + sudo systemctl mask "$unit" 2>/dev/null || true +done + +sudo apt-get remove -y unattended-upgrades || true +sudo tee /etc/apt/apt.conf.d/20auto-upgrades > /dev/null <<'EOF' +APT::Periodic::Update-Package-Lists "0"; +APT::Periodic::Unattended-Upgrade "0"; +APT::Periodic::Download-Upgradeable-Packages "0"; +APT::Periodic::AutocleanInterval "0"; +EOF + +echo "==> Updating the package index and upgrading the base image" +# The Ubuntu 24.04 base AMI ships with an older snapshot of packages (notably +# the gnupg/libksba8 stack). Upgrading first avoids "unmet dependencies" +# errors when later steps pull in newer packages. +sudo apt-get update +sudo apt-get upgrade -y + +echo "==> Installing common prerequisites" +sudo apt-get install -y \ + apt-transport-https \ + build-essential \ + ca-certificates \ + curl \ + git \ + gnupg \ + jq \ + "linux-headers-$(uname -r)" \ + lsb-release \ + pipx \ + python3-pip \ + python3-venv \ + software-properties-common \ + unzip \ + wget \ + xvfb \ + zip + +# Shared keyring directory for the third-party apt repositories added later. +sudo install -m 0755 -d /etc/apt/keyrings + +echo "==> System preparation complete" diff --git a/packer/scripts/02_install-docker.sh b/packer/scripts/02_install-docker.sh new file mode 100755 index 0000000..34fdb24 --- /dev/null +++ b/packer/scripts/02_install-docker.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# Install Docker Engine plus the buildx and compose plugins from Docker's +# official apt repository. Prerequisites (curl, gnupg, ca-certificates, +# lsb-release and /etc/apt/keyrings) are provided by setup-system.sh. +set -euo pipefail +export DEBIAN_FRONTEND=noninteractive + +echo "==> Adding Docker's official apt repository" +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \ + sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg +sudo chmod a+r /etc/apt/keyrings/docker.gpg + +echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ + $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + +echo "==> Installing Docker Engine" +sudo apt-get update +sudo apt-get install -y \ + containerd.io \ + docker-buildx-plugin \ + docker-ce \ + docker-ce-cli \ + docker-compose-plugin + +# Allow the default user to use Docker without sudo. +sudo usermod -aG docker ubuntu + +sudo systemctl enable docker +sudo systemctl start docker + +docker --version +echo "==> Docker installation complete" diff --git a/packer/scripts/03_install-nvidia.sh b/packer/scripts/03_install-nvidia.sh new file mode 100755 index 0000000..ba06b1d --- /dev/null +++ b/packer/scripts/03_install-nvidia.sh @@ -0,0 +1,86 @@ +#!/usr/bin/env bash +# Install the NVIDIA driver, the CUDA toolkit and the NVIDIA Container Toolkit. +# build-essential and the matching linux-headers come from setup-system.sh; +# Docker (configured here for the NVIDIA runtime) comes from install-docker.sh. +set -euo pipefail +export DEBIAN_FRONTEND=noninteractive + +# This AMI targets Ubuntu 24.04 exclusively. +DISTRO="ubuntu2404" + +echo "==> System information" +uname -r +lspci | grep -i nvidia || echo "Note: no NVIDIA GPU visible in the build environment" + +UBUNTU_VERSION="$(lsb_release -rs)" +if [[ "$UBUNTU_VERSION" != "24.04" ]]; then + echo "WARNING: expected Ubuntu 24.04 but found ${UBUNTU_VERSION}; continuing with ${DISTRO} repositories" +fi + +echo "==> Installing the recommended NVIDIA driver" +sudo apt-get install -y ubuntu-drivers-common +sudo ubuntu-drivers autoinstall + +# Fall back to a known-good driver version if autoinstall did not provide one. +if ! command -v nvidia-smi >/dev/null 2>&1; then + echo "==> autoinstall provided no driver; falling back to nvidia-driver-535" + sudo apt-get install -y nvidia-driver-535 nvidia-utils-535 +fi + +echo "==> Installing the CUDA toolkit" +# Best effort: the CUDA toolkit is large and occasionally unavailable. A +# driver-only image is still usable, so do not fail the build if it errors. +if ! command -v nvcc >/dev/null 2>&1; then + keyring="$(mktemp -d)/cuda-keyring.deb" + for attempt in 1 2 3; do + if wget -O "$keyring" \ + "https://developer.download.nvidia.com/compute/cuda/repos/${DISTRO}/x86_64/cuda-keyring_1.1-1_all.deb"; then + break + fi + echo "CUDA keyring download attempt ${attempt} failed; retrying in 5s..." + sleep 5 + done + sudo dpkg -i "$keyring" + rm -f "$keyring" + + for attempt in 1 2 3; do + sudo apt-get update && break + echo "apt-get update attempt ${attempt} failed; retrying in 10s..." + sleep 10 + done + + sudo apt-get install -y cuda-toolkit || \ + echo "WARNING: CUDA toolkit installation failed; continuing with driver only" +fi + +echo "==> Configuring the CUDA environment" +# Expose CUDA on PATH for all login shells (replaces the previous per-user +# .bashrc / /etc/environment edits with a single system-wide profile drop-in). +CUDA_DIR="$(ls -d /usr/local/cuda-* 2>/dev/null | head -1 || true)" +CUDA_DIR="${CUDA_DIR:-/usr/local/cuda}" +sudo tee /etc/profile.d/cuda.sh > /dev/null < Installing the NVIDIA Container Toolkit" +# Best effort, but uses the official repository so it installs cleanly when the +# network is healthy. +curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \ + sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg +curl -fsSL https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \ + sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \ + sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list > /dev/null + +if sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit; then + sudo nvidia-ctk runtime configure --runtime=docker + sudo systemctl restart docker || echo "Docker will pick up the NVIDIA runtime on next start" +else + echo "WARNING: NVIDIA Container Toolkit installation failed; continuing without it" +fi + +echo "==> Verifying installation" +command -v nvcc || echo "nvcc not yet on PATH (available after re-login / reboot)" +command -v nvidia-smi || echo "nvidia-smi not found (driver loads after reboot)" + +echo "==> NVIDIA installation complete (a reboot may be required for the driver)" diff --git a/packer/scripts/04_install-ci-tools.sh b/packer/scripts/04_install-ci-tools.sh new file mode 100755 index 0000000..210a4ba --- /dev/null +++ b/packer/scripts/04_install-ci-tools.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# Install the tooling the CI runners expect that is not in the base repos: +# the runnerx service account, AWS CLI v2, GitHub CLI, uv, Node.js/npm and +# Miniconda. Common utilities (jq, git, unzip, python3-pip/venv, pipx, ...) +# are installed by setup-system.sh. +set -euo pipefail +export DEBIAN_FRONTEND=noninteractive + +echo "==> Creating the runnerx service account" +if ! id runnerx &>/dev/null; then + sudo useradd -m -s /bin/bash runnerx +fi +sudo usermod -aG docker runnerx + +echo "==> Installing Node.js and npm" +sudo apt-get install -y nodejs npm + +echo "==> Installing the GitHub CLI" +# gh is not in the default Ubuntu repos; add its official apt repository. +curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | \ + sudo gpg --dearmor -o /etc/apt/keyrings/githubcli-archive-keyring.gpg +sudo chmod a+r /etc/apt/keyrings/githubcli-archive-keyring.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | \ + sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null +sudo apt-get update +sudo apt-get install -y gh + +echo "==> Installing uv" +# uv is not packaged for apt; install it system-wide so every user can run it. +curl -LsSf https://astral.sh/uv/install.sh | sudo env UV_INSTALL_DIR=/usr/local/bin sh + +echo "==> Installing the AWS CLI v2" +tmp_dir="$(mktemp -d)" +curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "${tmp_dir}/awscliv2.zip" +unzip -q "${tmp_dir}/awscliv2.zip" -d "${tmp_dir}" +sudo "${tmp_dir}/aws/install" --update +rm -rf "${tmp_dir}" + +echo "==> Installing Miniconda for the runnerx user" +sudo -u runnerx bash -c ' + set -euo pipefail + wget -qO /home/runnerx/miniconda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh + bash /home/runnerx/miniconda.sh -b -p /home/runnerx/miniconda3 + rm -f /home/runnerx/miniconda.sh + echo "export PATH=\"/home/runnerx/miniconda3/bin:\$PATH\"" >> /home/runnerx/.bashrc +' + +echo "==> Creating the /opt/runnerx working directory" +sudo mkdir -p /opt/runnerx +sudo chown ubuntu:ubuntu /opt/runnerx + +echo "==> CI tools installation complete" diff --git a/packer/scripts/99_cleanup.sh b/packer/scripts/99_cleanup.sh new file mode 100755 index 0000000..1196597 --- /dev/null +++ b/packer/scripts/99_cleanup.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# Final pass: apply any remaining upgrades and trim cached package data so the +# resulting AMI is as small as possible. +set -euo pipefail +export DEBIAN_FRONTEND=noninteractive + +sudo apt-get update +sudo apt-get upgrade -y +sudo apt-get autoremove -y +sudo apt-get autoclean +sudo rm -rf /var/lib/apt/lists/* + +echo "==> Cleanup complete" diff --git a/packer/scripts/disable-upgrades.sh b/packer/scripts/disable-upgrades.sh deleted file mode 100644 index f414d8b..0000000 --- a/packer/scripts/disable-upgrades.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash -set -e - -echo "Disabling automatic upgrades and updates..." - -# Disable automatic upgrades -sudo systemctl disable apt-daily-upgrade.service -sudo systemctl disable apt-daily.service -sudo systemctl disable apt-daily-upgrade.timer -sudo systemctl disable apt-daily.timer - -# Mask them to prevent accidental starts -sudo systemctl mask apt-daily-upgrade.service -sudo systemctl mask apt-daily.service -sudo systemctl mask apt-daily-upgrade.timer -sudo systemctl mask apt-daily.timer - -# Stop any running services -sudo systemctl stop apt-daily-upgrade.service || true -sudo systemctl stop apt-daily.service || true -sudo systemctl stop apt-daily-upgrade.timer || true -sudo systemctl stop apt-daily.timer || true - -# Disable unattended upgrades -sudo apt-get remove -y unattended-upgrades || true - -# Create apt configuration to prevent automatic updates -sudo tee /etc/apt/apt.conf.d/20auto-upgrades > /dev/null <= 1.6.3), which fails with "unmet dependencies" -# unless the base packages are upgraded beforehand. -sudo apt-get update -sudo apt-get upgrade -y - -# Install packages to allow apt to use a repository over HTTPS -sudo apt-get install -y \ - ca-certificates \ - curl \ - gnupg \ - lsb-release - -# Add Docker's official GPG key -sudo mkdir -p /etc/apt/keyrings -curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg - -# Set up the repository -echo \ - "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ - $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null - -# Update package index again -sudo apt-get update - -# Install Docker Engine -sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin - -# Add ubuntu user to docker group -sudo usermod -aG docker ubuntu - -# Enable Docker service -sudo systemctl enable docker -sudo systemctl start docker - -# Verify installation -docker --version \ No newline at end of file diff --git a/packer/scripts/install-nvidia-drivers.sh b/packer/scripts/install-nvidia-drivers.sh deleted file mode 100755 index b322503..0000000 --- a/packer/scripts/install-nvidia-drivers.sh +++ /dev/null @@ -1,148 +0,0 @@ -#!/bin/bash -set -e - -echo "Installing NVIDIA drivers and CUDA toolkit following official guide..." - -# Pre-installation actions -echo "Performing pre-installation checks..." - -# Verify system requirements -echo "System information:" -hostnamectl || true -uname -r - -# Check for NVIDIA GPU (may not work in all environments) -lspci | grep -i nvidia || echo "Note: NVIDIA GPU check may not work in build environment" - -# Update package lists -sudo apt-get update - -# Install required packages for CUDA installation. build-essential provides -# gcc, which is needed to build the NVIDIA kernel modules, so it must be -# installed before the gcc verification below. -sudo apt-get install -y linux-headers-$(uname -r) build-essential - -# Verify gcc is installed -gcc --version - -# Force Ubuntu 24.04 repository (we must use Ubuntu 24.04) -echo "Detecting Ubuntu version..." -UBUNTU_VERSION=$(lsb_release -rs) -echo "Detected Ubuntu version: $UBUNTU_VERSION" - -# FORCE ubuntu2404 regardless of detection -DISTRO="ubuntu2404" -echo "FORCING Ubuntu 24.04 repository: $DISTRO" - -if [[ "$UBUNTU_VERSION" != "24.04" ]]; then - echo "ERROR: Expected Ubuntu 24.04 but got $UBUNTU_VERSION - AMI filter may be wrong!" - echo "Continuing with ubuntu2404 repository anyway..." -fi - -# Try Ubuntu's official NVIDIA packages first (more reliable) -echo "Installing NVIDIA drivers from Ubuntu repositories..." -sudo apt-get update - -# Install ubuntu-drivers-common to detect recommended driver -sudo apt-get install -y ubuntu-drivers-common - -# Install the recommended NVIDIA driver -echo "Installing recommended NVIDIA driver..." -sudo ubuntu-drivers autoinstall - -# If autoinstall fails, try specific driver version -if ! nvidia-smi --version 2>/dev/null; then - echo "Autoinstall failed, trying specific driver version..." - sudo apt-get install -y nvidia-driver-535 nvidia-utils-535 -fi - -# Install CUDA toolkit from NVIDIA repository as fallback -echo "Attempting to install CUDA toolkit..." -if ! command -v nvcc >/dev/null 2>&1; then - echo "Setting up NVIDIA CUDA repository..." - - # Download with retry logic - for i in {1..3}; do - if wget https://developer.download.nvidia.com/compute/cuda/repos/$DISTRO/x86_64/cuda-keyring_1.1-1_all.deb; then - break - fi - echo "Download attempt $i failed, retrying..." - sleep 5 - done - - sudo dpkg -i cuda-keyring_1.1-1_all.deb - - # Update with retry logic for repository sync issues - echo "Updating package lists (with retry for repository sync)..." - for i in {1..3}; do - if sudo apt-get update; then - break - fi - echo "apt update attempt $i failed, retrying in 10 seconds..." - sleep 10 - done - - # Install CUDA Toolkit - echo "Installing CUDA toolkit..." - sudo apt-get install -y cuda-toolkit || echo "CUDA toolkit installation failed, continuing with driver-only setup" -fi - -# Post-installation actions -echo "Setting up CUDA environment..." - -# Get the installed CUDA version for proper path setup -CUDA_VERSION=$(ls /usr/local/ | grep cuda- | head -1) -if [[ -z "$CUDA_VERSION" ]]; then - CUDA_VERSION="cuda" -fi - -echo "Found CUDA installation: $CUDA_VERSION" - -# Add CUDA to PATH properly by updating /etc/environment correctly -sudo bash -c "cat > /etc/environment << 'EOF' -PATH=\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/$CUDA_VERSION/bin\" -LD_LIBRARY_PATH=\"/usr/local/$CUDA_VERSION/lib64\" -EOF" - -# Also add to ubuntu user's bashrc for immediate use -echo "export PATH=\"/usr/local/$CUDA_VERSION/bin:\$PATH\"" >> /home/ubuntu/.bashrc -echo "export LD_LIBRARY_PATH=\"/usr/local/$CUDA_VERSION/lib64:\$LD_LIBRARY_PATH\"" >> /home/ubuntu/.bashrc - -# Set for current session -export PATH=/usr/local/$CUDA_VERSION/bin:$PATH -export LD_LIBRARY_PATH=/usr/local/$CUDA_VERSION/lib64:$LD_LIBRARY_PATH - -# Install NVIDIA Container Toolkit for Docker (using official method) -echo "Installing NVIDIA Container Toolkit..." - -# Use the new official installation method -curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg - -# Use ubuntu22.04 repository as it's more stable for container toolkit -echo "deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://nvidia.github.io/libnvidia-container/stable/deb/\$(ARCH) /" | \ - sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list - -sudo apt-get update -sudo apt-get install -y nvidia-container-toolkit || echo "Container toolkit installation failed, continuing without it" - -# Configure Docker to use NVIDIA runtime -sudo nvidia-ctk runtime configure --runtime=docker -sudo systemctl restart docker || echo "Docker restart will be handled by systemd" - -# Verify installation (basic checks) -echo "Performing basic installation verification..." -which nvcc || echo "nvcc not found in PATH yet (will be available after environment reload)" -which nvidia-smi || echo "nvidia-smi not found - may require reboot for driver to load" - -# Test nvidia-smi if available -if command -v nvidia-smi >/dev/null 2>&1; then - echo "Testing nvidia-smi:" - nvidia-smi || echo "nvidia-smi command exists but GPU not accessible (expected in build environment)" -fi - -# Clean up downloaded files -rm -f cuda-keyring_1.1-1_all.deb - - -echo "NVIDIA CUDA installation completed following official guide!" -echo "Note: System may need to be rebooted for full driver functionality" \ No newline at end of file diff --git a/packer/scripts/preinstall-tools.sh b/packer/scripts/preinstall-tools.sh deleted file mode 100644 index c52b004..0000000 --- a/packer/scripts/preinstall-tools.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash -set -e - -echo "Installing CI tools for cirun runners..." - -# Update package index -sudo apt-get update - -# Create runnerx user (matching CI runner environment) -sudo useradd -m -s /bin/bash runnerx -sudo usermod -aG docker runnerx - -# Install AWS CLI v2 -curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" -unzip awscliv2.zip -sudo ./aws/install -rm -rf awscliv2.zip aws/ - -# Install essential tools for CI runner -sudo apt-get install -y \ - jq \ - hub \ - xvfb \ - curl \ - wget \ - unzip \ - python3-pip \ - python3-venv \ - pipx \ - uv \ - git \ - build-essential \ - nodejs \ - npm \ - gh - -# # Remove conflicting packages first -# sudo apt-get remove -y nodejs npm libnode-dev nodejs-doc || true -# sudo apt-get autoremove -y - -# # Install Node.js 20 (version specified in workflow) -# curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - -# sudo apt-get install -y nodejs - -# Install miniconda for runnerx user (matching CI runner environment) -sudo -u runnerx wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /home/runnerx/miniconda.sh -sudo -u runnerx bash /home/runnerx/miniconda.sh -b -p /home/runnerx/miniconda3 -sudo rm /home/runnerx/miniconda.sh - -# Add conda to PATH for runnerx user -echo 'export PATH="/home/runnerx/miniconda3/bin:$PATH"' | sudo tee -a /home/runnerx/.bashrc - -# Install pipx for Python package management -sudo apt-get install -y python3-pip python3-venv pipx - -# Create necessary directories -sudo mkdir -p /opt/runnerx -sudo chown ubuntu:ubuntu /opt/runnerx - -echo "CI tools installation completed"