#!/usr/bin/env bash set -euo pipefail export PIP_DISABLE_PIP_VERSION_CHECK=1 export PIP_NO_CACHE_DIR=1 export PIP_NO_INPUT=1 export PYTHONDONTWRITEBYTECODE=1 project_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" python_bin="${project_root}/app/.venv/bin/python" ci_cache_dir="" cleanup_ci_cache() { if [[ -z "${ci_cache_dir}" || ! -d "${ci_cache_dir}" ]]; then return fi case "${ci_cache_dir}" in */dzentra-ci-pycache.*) rm -rf -- "${ci_cache_dir}" ;; *) printf 'Отказ от очистки неожиданного пути: %s\n' "${ci_cache_dir}" >&2 return 1 ;; esac } trap cleanup_ci_cache EXIT verify_environment() { if [[ ! -x "${python_bin}" ]]; then printf 'Не найден Python environment: %s\n' "${python_bin}" >&2 printf 'Установите app/requirements-dev.lock по инструкции CI gate.\n' >&2 return 1 fi local python_minor python_minor="$( "${python_bin}" -c \ 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' )" if [[ "${python_minor}" != "3.12" ]]; then printf 'Требуется Python 3.12, найден Python %s.\n' "${python_minor}" >&2 return 1 fi "${python_bin}" -m pip check } run_quality() { local ci_tmp_base ci_tmp_base="${TMPDIR:-/tmp}" ci_cache_dir="$( mktemp -d "${ci_tmp_base%/}/dzentra-ci-pycache.XXXXXX" )" "${project_root}/scripts/check_python_types.sh" "${python_bin}" \ "${project_root}/scripts/check_documentation_integrity.py" ( cd "${project_root}/app" "${python_bin}" -m pytest \ -q \ -p no:cacheprovider \ -W error::ResourceWarning \ tests/static ) PYTHONPYCACHEPREFIX="${ci_cache_dir}" \ "${python_bin}" -m compileall \ -q \ "${project_root}/app/src" \ "${project_root}/app/tests" \ "${project_root}/scripts" git -C "${project_root}" diff --check cleanup_ci_cache ci_cache_dir="" } run_offline_regression() { ( cd "${project_root}/app" "${python_bin}" -m pytest \ -q \ -p no:cacheprovider \ -W error::ResourceWarning ) } run_loopback_integration() { ( cd "${project_root}/app" "${python_bin}" -m pytest \ -q \ -p no:cacheprovider \ -W error::ResourceWarning \ -m integration \ tests/integration/market_data/acquisition/runtime ) } print_usage() { printf '%s\n' \ 'Использование: ./scripts/run_ci_gate.sh MODE' \ '' \ 'MODE:' \ ' quality Pyright, документация, static и compileall' \ ' offline-regression полная default offline-регрессия' \ ' loopback-integration локальная WebSocket integration-проверка' \ ' all все три режима последовательно' } main() { local mode="${1:-}" if [[ "$#" -ne 1 ]]; then print_usage >&2 return 2 fi verify_environment case "${mode}" in quality) run_quality ;; offline-regression) run_offline_regression ;; loopback-integration) run_loopback_integration ;; all) run_quality run_offline_regression run_loopback_integration ;; *) print_usage >&2 return 2 ;; esac } main "$@"