rename ss-tools to superset-tools across the entire project
- Replace all occurrences of 'ss-tools' with 'superset-tools' in 104 files - Rename git bundle file ss-tools.bundle → superset-tools.bundle - Update .gitignore pattern accordingly - Preserve variable names (hasSsTools etc.) and code identifiers
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# [DEF:ADR-0001:ADR]
|
||||
# @STATUS ACTIVE
|
||||
# @PURPOSE Define the canonical project directory layout, module boundaries, and naming conventions for the ss-tools repository. This ADR is the root structural authority — all other ADRs and feature plans derive their file placement from it.
|
||||
# @PURPOSE Define the canonical project directory layout, module boundaries, and naming conventions for the superset-tools repository. This ADR is the root structural authority — all other ADRs and feature plans derive their file placement from it.
|
||||
# @RELATION CALLS -> [ADR-0002:ADR]
|
||||
# @RELATION CALLS -> [ADR-0003:ADR]
|
||||
# @RELATION CALLS -> [ADR-0004:ADR]
|
||||
@@ -15,7 +15,7 @@
|
||||
The repository uses a **two‑platform, top‑level separation**:
|
||||
|
||||
```
|
||||
ss-tools/ # Repository root
|
||||
superset-tools/ # Repository root
|
||||
├── backend/ # Python 3.13+ / FastAPI application
|
||||
│ ├── src/
|
||||
│ │ ├── api/ # FastAPI route modules (one file per route group)
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
# [DEF:ADR-0003:ADR]
|
||||
# @STATUS ACTIVE
|
||||
# @PURPOSE Definitively establish ss-tools as a standalone orchestrator service operating *above* Apache Superset environments rather than integrating into them. This is a repo‑shaping architectural decision that governs deployment topology, security boundary, release cycle independence, and technology stack freedom.
|
||||
# @PURPOSE Definitively establish superset-tools as a standalone orchestrator service operating *above* Apache Superset environments rather than integrating into them. This is a repo‑shaping architectural decision that governs deployment topology, security boundary, release cycle independence, and technology stack freedom.
|
||||
# @RELATION DEPENDS_ON -> [ADR-0001:ADR]
|
||||
# @RELATION CALLS -> [ADR-0004:ADR]
|
||||
# @RELATION CALLS -> [ADR-0005:ADR]
|
||||
# @RATIONALE The core value proposition of ss-tools is multi‑environment orchestration: moving dashboards, datasets, and configurations between independent Superset instances (Dev → Stage → Prod). Embedding this logic inside any single Superset instance would immediately create a "master controller" dependency — if that instance fails, all environment management is lost. An external orchestrator treats all Superset instances as equal endpoints.
|
||||
# @RATIONALE Technology stack mismatch is irreversible: Superset uses Flask + React, ss-tools uses FastAPI + SvelteKit. Integration would require rewriting the entire Svelte frontend into React components and refactoring FastAPI dependency injection into Flask-AppBuilder patterns — a multi‑month effort with zero business value and high regression risk.
|
||||
# @RATIONALE Release cycle independence is non‑negotiable: Superset has a slow, complex release cadence. ss-tools must ship LLM plugins, Git integrations, and backup features on its own schedule without waiting for upstream Superset releases or maintaining a fork with perpetual merge conflicts.
|
||||
# @RATIONALE Security isolation: ss-tools manages DevOps privileges (deployment, backup, migration) while Superset manages BI privileges (data viewing, chart creation). Mixing these in one system expands the blast radius of any security incident.
|
||||
# @RATIONALE The core value proposition of superset-tools is multi‑environment orchestration: moving dashboards, datasets, and configurations between independent Superset instances (Dev → Stage → Prod). Embedding this logic inside any single Superset instance would immediately create a "master controller" dependency — if that instance fails, all environment management is lost. An external orchestrator treats all Superset instances as equal endpoints.
|
||||
# @RATIONALE Technology stack mismatch is irreversible: Superset uses Flask + React, superset-tools uses FastAPI + SvelteKit. Integration would require rewriting the entire Svelte frontend into React components and refactoring FastAPI dependency injection into Flask-AppBuilder patterns — a multi‑month effort with zero business value and high regression risk.
|
||||
# @RATIONALE Release cycle independence is non‑negotiable: Superset has a slow, complex release cadence. superset-tools must ship LLM plugins, Git integrations, and backup features on its own schedule without waiting for upstream Superset releases or maintaining a fork with perpetual merge conflicts.
|
||||
# @RATIONALE Security isolation: superset-tools manages DevOps privileges (deployment, backup, migration) while Superset manages BI privileges (data viewing, chart creation). Mixing these in one system expands the blast radius of any security incident.
|
||||
# @REJECTED Integration as a Superset plugin/extension — rejected for the four reasons above (orchestrator topology break, 100% frontend rewrite, Superset release cycle coupling, privilege boundary collapse).
|
||||
# @REJECTED Superset fork with ss-tools baked in — rejected because maintaining a fork requires rebase on every Superset release, creating perpetual merge conflicts and making security patch adoption dangerously slow.
|
||||
# @REJECTED Shared database with Superset — rejected because it couples ss-tools migrations to Superset's Alembic migration chain, preventing independent schema evolution and creating a single point of failure for both systems.
|
||||
# @REJECTED Superset fork with superset-tools baked in — rejected because maintaining a fork requires rebase on every Superset release, creating perpetual merge conflicts and making security patch adoption dangerously slow.
|
||||
# @REJECTED Shared database with Superset — rejected because it couples superset-tools migrations to Superset's Alembic migration chain, preventing independent schema evolution and creating a single point of failure for both systems.
|
||||
|
||||
## Decision
|
||||
|
||||
ss-tools operates as a **standalone orchestrator microservice** with these defined boundaries:
|
||||
superset-tools operates as a **standalone orchestrator microservice** with these defined boundaries:
|
||||
|
||||
### Deployment Topology
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ ss-tools │ ← FastAPI + SvelteKit
|
||||
│ superset-tools │ ← FastAPI + SvelteKit
|
||||
│ PostgreSQL │ ← Own database
|
||||
└──────┬──────┘
|
||||
│ REST API calls
|
||||
@@ -47,7 +47,7 @@ ss-tools operates as a **standalone orchestrator microservice** with these defin
|
||||
### Consequences
|
||||
|
||||
- **Positive:** Fast independent development, modern stack, no Superset coupling, clear security boundary.
|
||||
- **Negative:** Users have two separate UIs (Superset for BI, ss-tools for DevOps). Mitigated by consistent UX design and cross‑linking.
|
||||
- **Negative:** Users have two separate UIs (Superset for BI, superset-tools for DevOps). Mitigated by consistent UX design and cross‑linking.
|
||||
- **Risk:** API compatibility if Superset changes its REST API. Mitigated by versioned API client with automated compatibility tests.
|
||||
|
||||
## Migration from Existing Document
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# [DEF:ADR-0004:ADR]
|
||||
# @STATUS ACTIVE
|
||||
# @PURPOSE Define the plugin architecture for ss-tools — the loading mechanism, lifecycle contract, isolation guarantees, and the boundary between core services and pluggable extensions.
|
||||
# @PURPOSE Define the plugin architecture for superset-tools — the loading mechanism, lifecycle contract, isolation guarantees, and the boundary between core services and pluggable extensions.
|
||||
# @RELATION DEPENDS_ON -> [ADR-0001:ADR]
|
||||
# @RELATION DEPENDS_ON -> [ADR-0003:ADR]
|
||||
# @RELATION CALLS -> [ADR-0005:ADR]
|
||||
@@ -15,7 +15,7 @@
|
||||
### Plugin Architecture
|
||||
|
||||
```
|
||||
ss-tools Core
|
||||
superset-tools Core
|
||||
├── core/plugin_loader.py # Plugin discovery, loading, lifecycle
|
||||
├── core/plugin_executor.py # Subprocess execution, timeout, error boundary
|
||||
├── core/plugin_registry.py # Registered plugins, metadata, health
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# [DEF:ADR-0005:ADR]
|
||||
# @STATUS ACTIVE
|
||||
# @PURPOSE Define the authentication and authorization architecture for ss-tools: local auth, optional ADFS SSO federation, RBAC model, session management, and the security boundary between ss-tools (DevOps privileges) and Superset (BI privileges).
|
||||
# @PURPOSE Define the authentication and authorization architecture for superset-tools: local auth, optional ADFS SSO federation, RBAC model, session management, and the security boundary between superset-tools (DevOps privileges) and Superset (BI privileges).
|
||||
# @RELATION DEPENDS_ON -> [ADR-0001:ADR]
|
||||
# @RELATION DEPENDS_ON -> [ADR-0003:ADR]
|
||||
# @RELATION CALLS -> [ADR-0004:ADR]
|
||||
# @RATIONALE ss-tools manages operations that can modify production Superset instances (dashboard migration, backup, deployment). Unauthenticated or under‑authorized access to these operations is a critical security risk. A dedicated RBAC system ensures that DevOps privileges (manage deployments) are cleanly separated from BI privileges (view dashboards) and that actions are auditable.
|
||||
# @RATIONALE Local auth (bcrypt + JWT) is the primary path because ss-tools must work in air‑gapped enterprise deployments where external identity providers are unavailable. ADFS SSO is an optional federation layer for organizations that already have Active Directory.
|
||||
# @RATIONALE superset-tools manages operations that can modify production Superset instances (dashboard migration, backup, deployment). Unauthenticated or under‑authorized access to these operations is a critical security risk. A dedicated RBAC system ensures that DevOps privileges (manage deployments) are cleanly separated from BI privileges (view dashboards) and that actions are auditable.
|
||||
# @RATIONALE Local auth (bcrypt + JWT) is the primary path because superset-tools must work in air‑gapped enterprise deployments where external identity providers are unavailable. ADFS SSO is an optional federation layer for organizations that already have Active Directory.
|
||||
# @RATIONALE Role‑Based Access Control (RBAC) was chosen over Attribute‑Based Access Control (ABAC) because: (a) the system has a small, well‑defined set of operations (deploy, backup, migrate, view), (b) RBAC maps naturally to organizational roles (admin, analyst, operator), (c) ABAC adds complexity without proportional benefit for this scope.
|
||||
# @REJECTED Delegating all auth to Superset — rejected because ss-tools must operate when Superset is down, and Superset's auth model is designed for BI users, not DevOps operators with cross‑environment privileges.
|
||||
# @REJECTED Delegating all auth to Superset — rejected because superset-tools must operate when Superset is down, and Superset's auth model is designed for BI users, not DevOps operators with cross‑environment privileges.
|
||||
# @REJECTED OAuth2 social login (Google, GitHub) as primary path — rejected because enterprise deployments require air‑gapped operation. External OAuth providers are unavailable in offline mode.
|
||||
# @REJECTED Simple API key (no RBAC) — rejected because it cannot express granular permissions (admin vs analyst vs viewer), making auditability and least‑privilege impossible.
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# [DEF:ADR-0006:ADR]
|
||||
# @STATUS ACTIVE
|
||||
# @PURPOSE Define the frontend architecture for ss-tools: Svelte 5 runes reactivity model, SvelteKit routing, component composition rules, state management patterns (incl. Screen Models), design token system, UI atom reuse, API client conventions, and UX contract expectations for C4/C5 components.
|
||||
# @PURPOSE Define the frontend architecture for superset-tools: Svelte 5 runes reactivity model, SvelteKit routing, component composition rules, state management patterns (incl. Screen Models), design token system, UI atom reuse, API client conventions, and UX contract expectations for C4/C5 components.
|
||||
# @RELATION DEPENDS_ON -> [ADR-0001:ADR]
|
||||
# @RELATION DEPENDS_ON -> [ADR-0002:ADR]
|
||||
# @RELATION DEPENDS_ON -> [ADR-0010:ADR]
|
||||
# @RATIONALE Svelte 5 introduces a fundamentally different reactivity model (runes: `$state`, `$derived`, `$effect`, `$props`) compared to Svelte 4's `$:` reactive statements. This ADR locks in the Svelte 5 runes approach and prevents backsliding into legacy patterns when new developers or AI agents contribute code.
|
||||
# @RATIONALE SvelteKit with static adapter (`@sveltejs/adapter-static`) was chosen over SvelteKit SSR because: (a) ss-tools is a Docker‑deployed SPA behind nginx — server‑side rendering provides no latency benefit, (b) static SPA simplifies Docker deployment (no Node.js server needed, just nginx serving static files), (c) all data is fetched via REST API, not server‑side load functions.
|
||||
# @RATIONALE SvelteKit with static adapter (`@sveltejs/adapter-static`) was chosen over SvelteKit SSR because: (a) superset-tools is a Docker‑deployed SPA behind nginx — server‑side rendering provides no latency benefit, (b) static SPA simplifies Docker deployment (no Node.js server needed, just nginx serving static files), (c) all data is fetched via REST API, not server‑side load functions.
|
||||
# @RATIONALE Svelte 5 runes (`$state`, `$derived`, `$effect`) are mandated over Svelte 4 `$:` reactivity and `writable` stores because: (a) runes are the forward path — Svelte 4 patterns are deprecated, (b) runes provide fine‑grained reactivity without subscription boilerplate, (c) `$state` can be used outside `.svelte` files in `.svelte.js` modules, enabling reusable reactive logic.
|
||||
# @RATIONALE Design tokens (semantic colors in `tailwind.config.js`) were introduced in 2026‑06‑02 (PR 0‑1) to eliminate raw Tailwind classes (`bg‑blue‑600`, `text‑gray‑900`) from page‑level code. This prevents visual drift and gives AI agents a single source of truth for color choices. See §"Design Token System" below.
|
||||
# @RATIONALE Screen Model pattern (`[TYPE Model]` in `.svelte.ts` files) was formalised in 2026‑06‑02 (PR 3‑4) to extract cross‑widget state from page files. Models reduce page files from 2700+ lines to <1400 lines and enable unit‑testing of invariants without DOM render (~10ms). See §"State Management Pattern" and ADR‑0010.
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
# ADR-0007: REJECTED — `fromStore` + multiple `$derived` in Svelte 5
|
||||
|
||||
## Status
|
||||
REJECTED — pattern forbidden in ss-tools frontend.
|
||||
REJECTED — pattern forbidden in superset-tools frontend.
|
||||
|
||||
## Context
|
||||
`fromStore(store)` returns a reactive object whose `.current` property
|
||||
@@ -16,7 +16,7 @@ reflects the underlying Svelte writable store. Using it with multiple
|
||||
`$derived(runState.current?.xxx)` values creates persistent `render_effect`
|
||||
instances via Svelte's `createSubscriber` on every reactive re-evaluation.
|
||||
|
||||
### Observed failure (ss-tools, May 2026)
|
||||
### Observed failure (superset-tools, May 2026)
|
||||
`TranslationRunGlobalIndicator` used 6 `$derived` reading `runState.current`.
|
||||
Each `$derived` re-evaluation (triggered by store update) called `subscribe()`
|
||||
which called `render_effect()` inside `createSubscriber`. The `render_effect`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# [DEF:ADR-0009:ADR]
|
||||
# @STATUS ACTIVE
|
||||
# @PURPOSE Define the strategy for corporate SSL certificate management across all LLM HTTP clients in ss-tools (httpx, requests, openai), covering system CA store, NSS database for Chromium/Playwright, and the LLM_SSL_VERIFY escape hatch.
|
||||
# @PURPOSE Define the strategy for corporate SSL certificate management across all LLM HTTP clients in superset-tools (httpx, requests, openai), covering system CA store, NSS database for Chromium/Playwright, and the LLM_SSL_VERIFY escape hatch.
|
||||
# @RELATION DEPENDS_ON -> [ADR-0001:ADR]
|
||||
# @RELATION DEPENDS_ON -> [ADR-0004:ADR]
|
||||
# @RELATION CALLS -> [docker/backend.entrypoint.sh]
|
||||
@@ -8,7 +8,7 @@
|
||||
# @RELATION CALLS -> [backend/src/plugins/translate/_llm_http.py]
|
||||
# @RELATION CALLS -> [backend/src/plugins/translate/preview_llm_client.py]
|
||||
# @RELATION CALLS -> [scripts/check_llm_certs.py]
|
||||
# @RATIONALE ss-tools operates in corporate environments with internal Certificate Authorities.
|
||||
# @RATIONALE superset-tools operates in corporate environments with internal Certificate Authorities.
|
||||
# Three separate HTTP stacks are used: httpx (AsyncOpenAI in llm_analysis plugin),
|
||||
# requests (sync translate plugin), and Playwright Chromium (dashboard screenshots).
|
||||
# Each has its own CA trust store, requiring different installation strategies.
|
||||
@@ -121,7 +121,7 @@ intermediate CA in OpenSSL 3.x. `verify=<capath_dir>` works correctly.
|
||||
### On the server, after container restart:
|
||||
|
||||
```bash
|
||||
docker cp scripts/check_llm_certs.py ss-tools-backend-1:/tmp/
|
||||
docker cp scripts/check_llm_certs.py superset-tools-backend-1:/tmp/
|
||||
|
||||
docker compose -f docker-compose.enterprise-clean.yml \
|
||||
--env-file .env.enterprise-clean exec backend \
|
||||
@@ -167,7 +167,7 @@ grep -c "BEGIN CERTIFICATE" /etc/ssl/certs/ca-certificates.crt
|
||||
`requests` and `httpx` use `certifi` CA bundle by default. Corporate CA certs installed into `/etc/ssl/certs/` are invisible to Python HTTP clients unless explicitly pointed to the system bundle.
|
||||
|
||||
### Finding 2: Three separate HTTP stacks
|
||||
ss-tools has three LLM HTTP clients (httpx for async, requests for sync, Playwright for screenshots), each with independent CA trust configuration.
|
||||
superset-tools has three LLM HTTP clients (httpx for async, requests for sync, Playwright for screenshots), each with independent CA trust configuration.
|
||||
|
||||
### Finding 3: .pem extension ignored by update-ca-certificates
|
||||
On Debian Bookworm (python:3.11-slim), `update-ca-certificates` only processes `.crt` files.
|
||||
@@ -213,8 +213,8 @@ Fix: pass `input=""` or `echo | openssl s_client ...`.
|
||||
|
||||
```bash
|
||||
# On target server:
|
||||
xz -dc ss-tools-backend.0.1.7.tar.xz | docker load
|
||||
xz -dc ss-tools-frontend.0.1.7.tar.xz | docker load
|
||||
xz -dc superset-tools-backend.0.1.7.tar.xz | docker load
|
||||
xz -dc superset-tools-frontend.0.1.7.tar.xz | docker load
|
||||
|
||||
# Enable capath-based verification (remove LLM_SSL_VERIFY=false)
|
||||
sed -i '/LLM_SSL_VERIFY=false/d' .env.enterprise-clean
|
||||
@@ -226,7 +226,7 @@ docker compose -f docker-compose.enterprise-clean.yml \
|
||||
--env-file .env.enterprise-clean up -d
|
||||
|
||||
# Verify
|
||||
docker cp scripts/check_llm_certs.py ss-tools-backend-1:/tmp/
|
||||
docker cp scripts/check_llm_certs.py superset-tools-backend-1:/tmp/
|
||||
docker compose -f docker-compose.enterprise-clean.yml \
|
||||
--env-file .env.enterprise-clean exec backend \
|
||||
python3 /tmp/check_llm_certs.py --target https://lite.ai.rusal.com
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# [DEF:ADR-0011:ADR]
|
||||
# @STATUS ACTIVE
|
||||
# @PURPOSE Документировать архитектурное решение о полном переходе backend на async-first архитектуру: замена синхронного `requests.Session` на `httpx.AsyncClient`, введение глобальных per‑env семафоров, bounded executors и полный переход Task Manager на asyncio.
|
||||
# @RATIONALE ss-tools одновременно взаимодействует с несколькими внешними системами (Superset REST API, LLM API, SMTP, Telegram, Slack) и выполняет блокирующие операции (Git, файловый I/O, SQLAlchemy). При одном воркере uvicorn синхронные блокирующие вызовы останавливают все входящие HTTP-запросы. Единственный способ обеспечить конкурентность — сделать весь I/O неблокирующим.
|
||||
# @RATIONALE superset-tools одновременно взаимодействует с несколькими внешними системами (Superset REST API, LLM API, SMTP, Telegram, Slack) и выполняет блокирующие операции (Git, файловый I/O, SQLAlchemy). При одном воркере uvicorn синхронные блокирующие вызовы останавливают все входящие HTTP-запросы. Единственный способ обеспечить конкурентность — сделать весь I/O неблокирующим.
|
||||
# @REJECTED aiohttp — отвергнут в пользу httpx, который уже был в зависимостях (0.28.1) и имеет лучший API для async HTTP.
|
||||
# @REJECTED Полный переход на async SQLAlchemy — потребовал бы переписывания всех моделей и репозиториев, что выходит за рамки этой фичи. `run_blocking` с bounded executor достаточен.
|
||||
# @REJECTED Dual-stack (sync + async) — потребовал бы поддержки двух транспортов, увеличивая surface для ошибок и усложняя код.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# @PURPOSE Зафиксировать архитектурное решение об использовании Testcontainers для запуска Apache Superset в интеграционных тестах. Описать двухконтейнерную архитектуру (init + web), расследование проблем аутентификации, выбор версии 4.1.2, решение проблемы JWT-авторизации через psycopg2 + superset_config.py.
|
||||
# @RELATION DEPENDS_ON -> [ADR-0005-auth-rbac]
|
||||
# @RELATION DEPENDS_ON -> [ADR-0001-module-layout]
|
||||
# @RATIONALE Проект ss-tools интенсивно взаимодействует с Superset REST API (SupersetClient, SupersetSqlLabExecutor, translate-плагины). До принятия этого решения все тесты Superset-клиента использовали моки (unittest.mock.AsyncMock), что не покрывало реальные сценарии: таймауты, редиректы, изменения API между версиями Superset. Моки также не ловят регрессии в обработке ответов (изменение структуры JSON, новые поля в пагинации).
|
||||
# @RATIONALE Проект superset-tools интенсивно взаимодействует с Superset REST API (SupersetClient, SupersetSqlLabExecutor, translate-плагины). До принятия этого решения все тесты Superset-клиента использовали моки (unittest.mock.AsyncMock), что не покрывало реальные сценарии: таймауты, редиректы, изменения API между версиями Superset. Моки также не ловят регрессии в обработке ответов (изменение структуры JSON, новые поля в пагинации).
|
||||
# @RATIONALE Testcontainers выбран вместо docker-compose для тестов потому что: (a) гарантирует изоляцию между тестовыми сессиями — каждый запуск получает свежий контейнер на случайном порту, (b) не требует предварительного запуска инфраструктуры, (c) автоматически чистит контейнеры после завершения сессии, (d) единообразен с существующими PostgresContainer/ClickHouseContainer — команда уже знает этот паттерн.
|
||||
# @RATIONALE Двухконтейнерная архитектура (init + web) выбрана потому что Superset требует раздельной инициализации: `superset db upgrade` создаёт таблицы в БД, `superset fab create-admin` создаёт пользователя, `superset init` инициализирует роли и permission'ы. Только после этого можно запускать веб-сервер. Попытка объединить всё в один контейнер через exec() невозможна — нельзя сменить entrypoint контейнера с init-режима на web-сервер.
|
||||
# @REJECTED Docker Compose для тестов — отвергнут, так как требует предварительного `docker compose up`, порты фиксированы и могут конфликтовать, изоляция между сессиями слабее.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# @RELATION DEPENDS_ON -> [ADR-0006-frontend-architecture]
|
||||
# @RELATION DEPENDS_ON -> [ADR-0011-async-backend]
|
||||
# @RELATION DEPENDS_ON -> [ADR-0012-superset-testcontainers]
|
||||
# @RATIONALE Проект ss-tools состоит из двух независимых стеков (Python/FastAPI backend, Svelte frontend), каждый со своим инструментом покрытия (coverage.py, vitest/v8). Разработчику приходится запускать их по отдельности и вручную сопоставлять результаты. Без единого скрипта: (a) покрытие проверяется нерегулярно, (b) регрессии покрытия остаются незамеченными до CI, (c) новые разработчики тратят время на изучение двух разных команд.
|
||||
# @RATIONALE Проект superset-tools состоит из двух независимых стеков (Python/FastAPI backend, Svelte frontend), каждый со своим инструментом покрытия (coverage.py, vitest/v8). Разработчику приходится запускать их по отдельности и вручную сопоставлять результаты. Без единого скрипта: (a) покрытие проверяется нерегулярно, (b) регрессии покрытия остаются незамеченными до CI, (c) новые разработчики тратят время на изучение двух разных команд.
|
||||
# @RATIONALE Единый скрипт `scripts/coverage-summary.sh` решает эти проблемы: (a) одна команда для полного цикла, (b) сводный HTML с визуальным статусом каждого стека, (c) парсинг результатов тестов и процентов покрытия в машиночитаемом виде, (d) детализированные HTML-отчёты coverage по каждому стеку.
|
||||
|
||||
## Решение
|
||||
|
||||
Reference in New Issue
Block a user