From c8b12f37e453069b13e9aecc4055df708c5c6f5e Mon Sep 17 00:00:00 2001 From: busya Date: Fri, 23 Oct 2026 15:57:53 +0300 Subject: [PATCH] build: standardize runtime on Python 3.13 --- .python-version | 1 + AGENTS.md | 4 +- INSTALL.md | 6 +- backend/pyproject.toml | 2 +- docker/all-in-one.Dockerfile | 4 +- docker/backend.Dockerfile | 4 +- docker/backend.entrypoint.sh | 2 +- run.sh | 120 ++++++++++++++++++++--------------- scripts/mcp_proxy_smoke.py | 2 +- 9 files changed, 84 insertions(+), 61 deletions(-) create mode 100644 .python-version diff --git a/.python-version b/.python-version new file mode 100644 index 000000000..24ee5b1be --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/AGENTS.md b/AGENTS.md index 20361e441..154c5bdc7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,6 +15,8 @@ Your architecture uses Causal Attention (you predict the next token based only o ## Development Environment - Рабочий виртуальный окружение (`.venv`) находится внутри `backend/`: `backend/.venv`. +- Backend требует Python 3.13 или новее; `.python-version` выбирает ветку 3.13 без закрепления patch-версии. +- Существующее `backend/.venv` на Python ниже 3.13 нужно пересоздать явно; `run.sh` откажет до чтения `.env`, записи файлов и подключения к БД. ## Тестовый стенд и запуск @@ -39,7 +41,7 @@ healthcheck после запуска, поэтому первое открыт При старте скрипт: -1. Проверяет `python3 >= 3.9` и `npm`. +1. Проверяет `python3 >= 3.13` и `npm`. 2. Загружает `backend/.env` до database preflight. 3. Берет URL БД из `DATABASE_URL` либо использует локальный PostgreSQL: `postgresql+psycopg2://postgres:postgres@localhost:5432/ss_tools`. diff --git a/INSTALL.md b/INSTALL.md index 82be5dfb7..306453e7f 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -20,7 +20,7 @@ ## Требования - **Docker (рекомендуется):** Docker Engine 24+, Docker Compose v2, 4 GB RAM -- **Локальная разработка:** Python 3.9+, Node.js 18+, npm, 2 GB RAM, 5 GB диска +- **Локальная разработка:** Python 3.13+, Node.js 18+, npm, 2 GB RAM, 5 GB диска ## Архитектура @@ -75,7 +75,7 @@ superset-tools/ ## Технологический стек -**Backend:** Python 3.9+ (FastAPI 0.126, SQLAlchemy 2.0, APScheduler 3.11), PostgreSQL 16, Authlib, JWT, OpenAI API, GitPython, Playwright, lingua-language-detector +**Backend:** Python 3.13+ (FastAPI 0.126, SQLAlchemy 2.0, APScheduler 3.11), PostgreSQL 16, Authlib, JWT, OpenAI API, GitPython, Playwright, lingua-language-detector **Frontend:** Svelte 5 (Runes), SvelteKit 2.49, Vite 7, Tailwind CSS 3, Vitest 4.1, Playwright 1.60 @@ -120,7 +120,7 @@ docker compose -f dist/docker/docker-compose.light.yml up -d ```bash cd backend -python3 -m venv .venv +python3.13 -m venv .venv source .venv/bin/activate pip install -r requirements-backend.txt python3 -m uvicorn src.app:app --reload --port 8000 diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 21771fd09..71ca650a2 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta" [project] name = "superset-tools-backend" version = "0.0.0" -requires-python = ">=3.11" +requires-python = ">=3.13" [tool.setuptools] include-package-data = true diff --git a/docker/all-in-one.Dockerfile b/docker/all-in-one.Dockerfile index 5af8f51f7..8b9953036 100644 --- a/docker/all-in-one.Dockerfile +++ b/docker/all-in-one.Dockerfile @@ -6,7 +6,7 @@ # # Stages: # 1. frontend-builder — node:20-alpine, npm ci + build, discarded -# 2. runtime — python:3.11-slim, backend deps (no playwright), +# 2. runtime — python:3.13-slim, backend deps (no playwright), # copies frontend build, uvicorn serves both SPA + API on :8000 # ── Stage 1: Build Frontend ──────────────────────────────── @@ -26,7 +26,7 @@ COPY frontend/ ./ RUN npm run build # ── Stage 2: Runtime ─────────────────────────────────────── -FROM python:3.11-slim AS runtime +FROM python:3.13-slim AS runtime ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ diff --git a/docker/backend.Dockerfile b/docker/backend.Dockerfile index 4ff3990ee..0fc7ca3c6 100644 --- a/docker/backend.Dockerfile +++ b/docker/backend.Dockerfile @@ -1,12 +1,12 @@ # #region docker.backend.Dockerfile [C:3] [TYPE Module] [SEMANTICS docker,backend,build] -# @BRIEF Backend Dockerfile — Python 3.11 slim + Playwright + entrypoint с установкой сертификатов. +# @BRIEF Backend Dockerfile — Python 3.13 slim + Playwright + entrypoint с установкой сертификатов. # @LAYER Infrastructure # @RELATION DEPENDS_ON -> [EXT:path:docker/backend.entrypoint.sh] # @RELATION DEPENDS_ON -> [EXT:path:backend/requirements-backend.txt] # @PRE Docker builder context — корень проекта. backend/, docker/ доступны. # @POST Образ с backend API, Playwright, entrypoint для bootstrap admin. -FROM python:3.11-slim +FROM python:3.13-slim ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 diff --git a/docker/backend.entrypoint.sh b/docker/backend.entrypoint.sh index d4d465452..541c4edc0 100755 --- a/docker/backend.entrypoint.sh +++ b/docker/backend.entrypoint.sh @@ -200,7 +200,7 @@ install_ca_to_nss() { # @RATIONALE Без wait-for-db enterprise-деплой с внешним PostgreSQL падает # мгновенно — entrypoint интерпретирует connection refused как "пустая БД". # @REJECTED Использование pg_isready напрямую отвергнуто — клиент psql может -# отсутствовать в python:3.11-slim образе. SQLAlchemy-проверка универсальна. +# отсутствовать в python:3.13-slim образе. SQLAlchemy-проверка универсальна. wait_for_db() { local max_attempts="${DB_WAIT_ATTEMPTS:-30}" local delay="${DB_WAIT_DELAY:-2}" diff --git a/run.sh b/run.sh index b0d9e6d9b..fee25b3e3 100755 --- a/run.sh +++ b/run.sh @@ -10,6 +10,76 @@ set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$SCRIPT_DIR" + +# #region Tooling.Run.Arguments [C:2] [TYPE Function] +# @POST Help and invalid arguments return before interpreter checks or startup side effects. +SKIP_INSTALL=false + +# Help message +show_help() { + echo "Usage: ./run.sh [options]" + echo "" + echo "Options:" + echo " --help Show this help message" + echo " --skip-install Skip dependency checks and installation" + echo "" + echo "Environment Variables:" + echo " DEV_MODE Hot-reload mode (true/false). Default: false" + echo " Enables uvicorn --reload" + echo " BACKEND_PORT Port for the backend server (default: 8000)" + echo " FRONTEND_PORT Port for the frontend server (default: 5173)" +} + +# Parse arguments +while [[ "$#" -gt 0 ]]; do + case $1 in + --help) show_help; exit 0 ;; + --skip-install) SKIP_INSTALL=true ;; + *) echo "Unknown parameter passed: $1"; show_help; exit 1 ;; + esac + shift +done + +# #endregion Tooling.Run.Arguments + +# #region Tooling.Run.ValidateEnvironment [C:3] [TYPE Function] +# @PRE Validate Python before reading configuration, creating storage, generating secrets or probing the database. +# @POST Both the host and an existing backend virtual environment require Python 3.13 or newer. +# @REJECTED Checking only the host would let --skip-install keep using an existing Python 3.11 virtual environment. +validate_env() { + echo "Validating environment..." + + if ! command -v python3 &> /dev/null; then + echo "Error: python3 is not installed." + exit 1 + fi + + if ! python3 -c 'import sys; exit(0) if sys.version_info >= (3, 13) else exit(1)'; then + PYTHON_VERSION=$(python3 -c 'import sys; print(".".join(map(str, sys.version_info[:2])))') + echo "Error: python3 version 3.13 or higher is required. Found $PYTHON_VERSION" + exit 1 + fi + + local backend_python="$PROJECT_ROOT/backend/.venv/bin/python" + if [ -d "$PROJECT_ROOT/backend/.venv" ]; then + if [ ! -x "$backend_python" ] || ! "$backend_python" -c 'import sys; exit(0) if sys.version_info >= (3, 13) else exit(1)'; then + echo "Error: backend/.venv must use Python 3.13 or higher. Recreate it with a supported Python before starting." + exit 1 + fi + fi + + if ! command -v npm &> /dev/null; then + echo "Error: npm is not installed." + exit 1 + fi + + PYTHON_VERSION=$(python3 -c 'import sys; print(".".join(map(str, sys.version_info[:2])))') + echo "Environment validation passed (Python $PYTHON_VERSION, npm $(npm -v))" +} + +# #endregion Tooling.Run.ValidateEnvironment + +validate_env source "$SCRIPT_DIR/scripts/source_repository_identity_env.sh" # Parse KEY=VALUE dotenv files without executing their contents. Existing process @@ -51,7 +121,6 @@ load_dotenv "$PROJECT_ROOT/backend/.env" DEV_MODE="${DEV_MODE:-false}" BACKEND_PORT=${BACKEND_PORT:-8000} FRONTEND_PORT=${FRONTEND_PORT:-5173} -SKIP_INSTALL=false # Service-to-service shared secret validated by the backend for service # principals (MCP service tokens, internal integrations). When unset, a random @@ -79,58 +148,9 @@ fi mkdir -p "$STORAGE_ROOT_PATH/repositories" "$STORAGE_ROOT_PATH/backups" "$STORAGE_ROOT_PATH/drafts" export STORAGE_ROOT_PATH -# Help message -show_help() { - echo "Usage: ./run.sh [options]" - echo "" - echo "Options:" - echo " --help Show this help message" - echo " --skip-install Skip dependency checks and installation" - echo "" - echo "Environment Variables:" - echo " DEV_MODE Hot-reload mode (true/false). Default: false" - echo " Enables uvicorn --reload" - echo " BACKEND_PORT Port for the backend server (default: 8000)" - echo " FRONTEND_PORT Port for the frontend server (default: 5173)" -} - -# Parse arguments -while [[ "$#" -gt 0 ]]; do - case $1 in - --help) show_help; exit 0 ;; - --skip-install) SKIP_INSTALL=true ;; - *) echo "Unknown parameter passed: $1"; show_help; exit 1 ;; - esac - shift -done echo "Starting Project Launch Script..." -# Environment validation -validate_env() { - echo "Validating environment..." - - if ! command -v python3 &> /dev/null; then - echo "Error: python3 is not installed." - exit 1 - fi - - if ! python3 -c 'import sys; exit(0) if sys.version_info >= (3, 9) else exit(1)'; then - PYTHON_VERSION=$(python3 -c 'import sys; print(".".join(map(str, sys.version_info[:2])))') - echo "Error: python3 version 3.9 or higher is required. Found $PYTHON_VERSION" - exit 1 - fi - - if ! command -v npm &> /dev/null; then - echo "Error: npm is not installed." - exit 1 - fi - - PYTHON_VERSION=$(python3 -c 'import sys; print(".".join(map(str, sys.version_info[:2])))') - echo "Environment validation passed (Python $PYTHON_VERSION, npm $(npm -v))" -} - -validate_env # ── backend/.env was safely loaded before configuration defaults ── if [ -f "backend/.env" ]; then diff --git a/scripts/mcp_proxy_smoke.py b/scripts/mcp_proxy_smoke.py index 948cbc40e..a99c4f584 100644 --- a/scripts/mcp_proxy_smoke.py +++ b/scripts/mcp_proxy_smoke.py @@ -28,7 +28,7 @@ def main() -> None: docker( "run", "-d", "--name", backend, "--network", network, "--network-alias", "backend", "-v", f"{root / 'scripts/mcp_proxy_fixture.py'}:/fixture.py:ro", - "python:3.12-alpine", "python", "/fixture.py", + "python:3.13-alpine", "python", "/fixture.py", ) docker( "run", "-d", "--name", frontend, "--network", network,