Files
plex-playlist/Dockerfile.cicd-base
copilotcoder 696db6ddb9
All checks were successful
CICD Start / Sanity and Base Decision (pull_request) Successful in 18s
fix(ci): install playwright linux deps and pin integration runner
2026-06-17 11:30:10 -04:00

225 lines
8.4 KiB
Docker

# CICD Base Setup - System dependencies and language runtimes only
ARG PLAYWRIGHT_BROWSERS_IMAGE=mcr.microsoft.com/playwright:v1.56.1-jammy
FROM ${PLAYWRIGHT_BROWSERS_IMAGE} AS playwright-browsers
FROM ubuntu:22.04
# Build args for cache busting (base dependencies change rarely)
ARG BASE_IMAGE_VERSION=v1.0.0
ARG BASE_IMAGE_HASH=unknown
ENV BASE_IMAGE_VERSION=${BASE_IMAGE_VERSION}
LABEL darkhelm.cicd-base.hash=${BASE_IMAGE_HASH}
LABEL org.opencontainers.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 \
# Playwright Chromium runtime dependencies (Linux)
libnspr4 \
libnss3 \
libatk1.0-0 \
libatspi2.0-0 \
libxcomposite1 \
libxdamage1 \
libxfixes3 \
libxrandr2 \
libgbm1 \
libxkbcommon0 \
libasound2 \
tzdata \
&& rm -rf /var/lib/apt/lists/*
# Install Python 3.14 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.14..." && \
timeout 300 apt-fast install -y \
python3.14 \
python3.14-venv \
python3.14-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 without requiring GHCR pulls
RUN set -eu && \
curl -LsSf https://astral.sh/uv/install.sh -o /tmp/uv-install.sh && \
sh /tmp/uv-install.sh && \
rm -f /tmp/uv-install.sh && \
cp /root/.local/bin/uv /usr/local/bin/uv && \
chmod +x /usr/local/bin/uv && \
uv --version
# 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.56.1 \
typescript@5.3.3 \
eslint@9.33.0 \
prettier@3.6.2 \
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"
# Keep browser binaries in a deterministic location so E2E runs do not re-download them.
ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
# Copy preinstalled browsers from the official Playwright image to avoid flaky CDN downloads.
COPY --from=playwright-browsers /ms-playwright /ms-playwright
RUN echo "=== Verifying preinstalled Playwright Chromium Browser ===" && \
chromium_count=$(find "${PLAYWRIGHT_BROWSERS_PATH}" -maxdepth 1 -type d -name 'chromium-*' | wc -l) && \
echo "playwright_chromium_dir_count=${chromium_count} path=${PLAYWRIGHT_BROWSERS_PATH}" && \
if [ "${chromium_count}" -eq 0 ]; then \
echo "❌ No Chromium browser directories found in preinstalled Playwright cache"; \
exit 1; \
fi && \
ls -la "${PLAYWRIGHT_BROWSERS_PATH}" && \
echo "✓ Playwright Chromium preinstalled at ${PLAYWRIGHT_BROWSERS_PATH}"
# 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 kankali.darkhelm.lan >> ~/.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.14 --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"]