# CICD Base Setup - System dependencies and language runtimes only FROM ubuntu:22.04 # Build args for cache busting (base dependencies change rarely) ARG BASE_IMAGE_VERSION=v1.0.0 ENV BASE_IMAGE_VERSION=${BASE_IMAGE_VERSION} # Set timezone and make installs non-interactive ENV DEBIAN_FRONTEND=noninteractive ENV TZ=America/New_York # Configure timezone RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone # Install apt-fast with proper GPG handling RUN apt-get clean && \ rm -rf /var/lib/apt/lists/* && \ for i in 1 2 3; do \ echo "Attempt $i: Updating package lists..." && \ apt-get update && break || \ (echo "Update attempt $i failed, retrying..." && sleep 10); \ done && \ apt-get install -y \ software-properties-common \ gnupg \ ca-certificates \ curl \ wget \ && for i in 1 2 3; do \ echo "Attempt $i: Adding apt-fast PPA..." && \ add-apt-repository -y ppa:apt-fast/stable && \ apt-get update && \ apt-get install -y apt-fast && \ break || \ (echo "apt-fast installation attempt $i failed, retrying..." && sleep 10); \ done \ && rm -rf /var/lib/apt/lists/* # Configure apt-fast to use apt (not apt-get) with optimized settings RUN echo 'apt-fast apt-fast/maxdownloads string 10' | debconf-set-selections && \ echo 'apt-fast apt-fast/dlflag boolean true' | debconf-set-selections && \ echo 'apt-fast apt-fast/aptmanager string apt' | debconf-set-selections # Configure apt timeouts and retries RUN echo 'Acquire::Retries "3";' > /etc/apt/apt.conf.d/80retries && \ echo 'Acquire::http::Timeout "60";' >> /etc/apt/apt.conf.d/80retries && \ echo 'Acquire::https::Timeout "60";' >> /etc/apt/apt.conf.d/80retries && \ echo 'Acquire::ftp::Timeout "60";' >> /etc/apt/apt.conf.d/80retries # Install system dependencies using apt-fast RUN apt-fast update && apt-fast install -y \ git \ curl \ ca-certificates \ software-properties-common \ build-essential \ openssh-client \ tzdata \ && rm -rf /var/lib/apt/lists/* # Install Python 3.13 with retry and fallback mechanisms RUN for i in 1 2 3; do \ echo "Attempt $i: Adding deadsnakes PPA..." && \ add-apt-repository -y ppa:deadsnakes/ppa && \ apt-get update && \ break || \ (echo "Attempt $i failed, retrying in 10s..." && sleep 10); \ done RUN for i in 1 2 3; do \ echo "Attempt $i: Installing Python 3.13..." && \ timeout 300 apt-fast install -y \ python3.13 \ python3.13-venv \ python3.13-dev && \ break || \ (echo "Attempt $i failed, retrying in 15s..." && sleep 15); \ done && \ rm -rf /var/lib/apt/lists/* # Install Node.js 24 with retry mechanism RUN for i in 1 2 3; do \ echo "Attempt $i: Installing Node.js 24..." && \ curl -fsSL --connect-timeout 30 --max-time 300 \ https://deb.nodesource.com/setup_24.x | bash - && \ apt-fast update && \ timeout 300 apt-fast install -y nodejs && \ break || \ (echo "Attempt $i failed, retrying in 15s..." && sleep 15); \ done && \ rm -rf /var/lib/apt/lists/* # Enable corepack for yarn and set up Yarn Berry RUN corepack enable \ && corepack prepare yarn@stable --activate \ && yarn set version berry # Configure Yarn globally for CI performance RUN yarn config set httpTimeout 60000 && \ yarn config set enableGlobalCache false && \ yarn config set compressionLevel 0 && \ yarn config set nmMode hardlinks-local # Install uv package manager globally COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv # Install common development tools globally using npm (more reliable for global installs) RUN echo "=== Installing Global Development Tools ===" && \ # Use npm for global installations (works better than yarn global in Berry) npm install -g \ @playwright/test@1.40.0 \ typescript@5.3.3 \ eslint@9.33.0 \ prettier@3.3.3 \ vite@7.1.10 \ @types/node@20.16.0 && \ # Verify global tools are available which playwright && \ which tsc && \ which eslint && \ which prettier && \ echo "✓ Global Node.js development tools installed via npm" # Install Playwright browsers for E2E testing # This downloads ~400MB+ of browser binaries that will be cached RUN echo "=== Installing Playwright Browsers ===" && \ # Verify Playwright CLI is available playwright --version && \ # Install browsers with system dependencies (non-interactive) export PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=0 && \ playwright install --with-deps chromium firefox webkit && \ # Install system dependencies for browsers playwright install-deps && \ echo "✓ Playwright browsers installed and cached in base image" # Pre-install common Python development dependencies globally # These are stable tools that rarely change and take time to compile RUN echo "=== Pre-installing Common Python Dev Tools ===" && \ # Create a global uv environment with common dev tools uv venv /opt/python-dev-tools && \ # Use system uv to install packages into the virtual environment uv pip install --python /opt/python-dev-tools/bin/python \ ruff>=0.6.0 \ pyright>=1.1.380 \ pytest>=7.4.0 \ pytest-asyncio>=0.21.0 \ pytest-cov>=4.1.0 \ pytest-mock>=3.12.0 \ pre-commit>=3.0.0 \ pyyaml>=6.0 \ yamllint>=1.35.0 \ toml-sort>=0.23.0 \ xdoctest>=1.1.0 \ language-formatters-pre-commit-hooks>=2.14.0 \ poethepoet>=0.24.0 && \ echo "✓ Common Python dev tools pre-installed in /opt/python-dev-tools" # Create a script to set up SSH for git operations (using secrets mount) RUN echo '#!/bin/bash' > /usr/local/bin/setup-ssh && \ echo 'if [ -f /run/secrets/ssh_private_key ]; then' >> /usr/local/bin/setup-ssh && \ echo ' mkdir -p ~/.ssh' >> /usr/local/bin/setup-ssh && \ echo ' cp /run/secrets/ssh_private_key ~/.ssh/id_rsa' >> /usr/local/bin/setup-ssh && \ echo ' chmod 600 ~/.ssh/id_rsa' >> /usr/local/bin/setup-ssh && \ echo ' ssh-keyscan -H github.com >> ~/.ssh/known_hosts 2>/dev/null' >> /usr/local/bin/setup-ssh && \ echo ' ssh-keyscan -p 2222 -H dogar.darkhelm.org >> ~/.ssh/known_hosts 2>/dev/null' >> /usr/local/bin/setup-ssh && \ echo 'else' >> /usr/local/bin/setup-ssh && \ echo ' echo "No SSH key provided via secrets mount"' >> /usr/local/bin/setup-ssh && \ echo 'fi' >> /usr/local/bin/setup-ssh && \ chmod +x /usr/local/bin/setup-ssh # Verify that all base tools are working RUN echo "=== Base System Verification ===" && \ python3.13 --version && \ node --version && \ yarn --version && \ uv --version && \ git --version && \ echo "=== Global Development Tools Verification ===" && \ playwright --version && \ tsc --version && \ eslint --version && \ prettier --version && \ /opt/python-dev-tools/bin/ruff --version && \ /opt/python-dev-tools/bin/pyright --version && \ /opt/python-dev-tools/bin/pytest --version && \ /opt/python-dev-tools/bin/pre-commit --version && \ /opt/python-dev-tools/bin/poe --version && \ echo "✓ All base system and development tools verified successfully" # Set working directory WORKDIR /workspace # Default to bash SHELL ["/bin/bash", "-c"] CMD ["/bin/bash"]