Revert "feat: Enterprise DSS architecture implementation"
Some checks failed
DSS Project Analysis / dss-context-update (push) Has been cancelled
Some checks failed
DSS Project Analysis / dss-context-update (push) Has been cancelled
This reverts commit 9dbd56271e.
This commit is contained in:
@@ -3,14 +3,8 @@ DSS Configuration Module
|
||||
========================
|
||||
|
||||
Handles configuration management for the Design System Server (DSS) Claude Plugin.
|
||||
Supports local/remote/CI mode detection, persistent configuration storage, and
|
||||
Supports local/remote mode detection, persistent configuration storage, and
|
||||
environment variable overrides.
|
||||
|
||||
Enterprise Architecture:
|
||||
- LOCAL: Developer workstation, reads from .dss/ cache, advisory validation
|
||||
- REMOTE: Headless/server mode, full analysis, metrics upload
|
||||
- CI: CI/CD pipeline, authoritative enforcement, blocking validation
|
||||
- AUTO: Detect environment automatically (CI env vars -> CI, else LOCAL with cache)
|
||||
"""
|
||||
|
||||
import json
|
||||
@@ -19,7 +13,6 @@ import os
|
||||
import uuid
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
import aiohttp
|
||||
from pydantic import BaseModel, Field, ValidationError
|
||||
@@ -31,28 +24,14 @@ CONFIG_DIR = Path.home() / ".dss"
|
||||
CONFIG_FILE = CONFIG_DIR / "config.json"
|
||||
DEFAULT_REMOTE_URL = "https://dss.overbits.luz.uy"
|
||||
DEFAULT_LOCAL_URL = "http://localhost:6006"
|
||||
DEFAULT_DASHBOARD_URL = "https://dss.overbits.luz.uy/api/metrics"
|
||||
|
||||
# CI environment variables that indicate we're running in a pipeline
|
||||
CI_ENV_VARS = [
|
||||
"CI",
|
||||
"GITEA_ACTIONS",
|
||||
"GITHUB_ACTIONS",
|
||||
"GITLAB_CI",
|
||||
"JENKINS_URL",
|
||||
"CIRCLECI",
|
||||
"TRAVIS",
|
||||
"BUILDKITE",
|
||||
]
|
||||
|
||||
|
||||
class DSSMode(str, Enum):
|
||||
"""Operation modes for the DSS plugin."""
|
||||
|
||||
LOCAL = "local" # Developer workstation - advisory, uses cache
|
||||
REMOTE = "remote" # Headless server - full analysis
|
||||
CI = "ci" # CI/CD pipeline - authoritative enforcement
|
||||
AUTO = "auto" # Auto-detect based on environment
|
||||
LOCAL = "local"
|
||||
REMOTE = "remote"
|
||||
AUTO = "auto"
|
||||
|
||||
|
||||
class DSSConfig(BaseModel):
|
||||
@@ -63,21 +42,15 @@ class DSSConfig(BaseModel):
|
||||
mode (DSSMode): The configured operation mode (default: AUTO).
|
||||
remote_url (str): URL for the remote DSS API.
|
||||
local_url (str): URL for the local DSS API (usually localhost).
|
||||
dashboard_url (str): URL for metrics dashboard API.
|
||||
session_id (str): Unique identifier for this client instance.
|
||||
project_path (str): Current project path (for local analysis).
|
||||
rules_version (str): Pinned @dss/rules version for this project.
|
||||
"""
|
||||
|
||||
mode: DSSMode = Field(default=DSSMode.AUTO, description="Operation mode preference")
|
||||
remote_url: str = Field(default=DEFAULT_REMOTE_URL, description="Remote API endpoint")
|
||||
local_url: str = Field(default=DEFAULT_LOCAL_URL, description="Local API endpoint")
|
||||
dashboard_url: str = Field(default=DEFAULT_DASHBOARD_URL, description="Metrics dashboard API")
|
||||
session_id: str = Field(
|
||||
default_factory=lambda: str(uuid.uuid4()), description="Persistent session ID"
|
||||
)
|
||||
project_path: Optional[str] = Field(default=None, description="Current project path")
|
||||
rules_version: Optional[str] = Field(default=None, description="Pinned @dss/rules version")
|
||||
|
||||
class Config:
|
||||
validate_assignment = True
|
||||
@@ -128,75 +101,38 @@ class DSSConfig(BaseModel):
|
||||
Determine the actual runtime mode based on priority rules.
|
||||
|
||||
Priority:
|
||||
1. DSS_MODE environment variable (explicit override)
|
||||
2. CI environment detection (GITEA_ACTIONS, CI, GITHUB_ACTIONS, etc.)
|
||||
3. Configured 'mode' (if not AUTO)
|
||||
4. Auto-detection (check for .dss/ folder, ping local health)
|
||||
5. Fallback to LOCAL (developer-first)
|
||||
1. DSS_MODE environment variable
|
||||
2. Configured 'mode' (if not AUTO)
|
||||
3. Auto-detection (ping local health endpoint)
|
||||
4. Fallback to REMOTE
|
||||
|
||||
Returns:
|
||||
DSSMode: The resolved active mode (LOCAL, REMOTE, or CI).
|
||||
DSSMode: The resolved active mode (LOCAL or REMOTE).
|
||||
"""
|
||||
# 1. Check Environment Variable (explicit override)
|
||||
# 1. Check Environment Variable
|
||||
env_mode = os.getenv("DSS_MODE")
|
||||
if env_mode:
|
||||
try:
|
||||
resolved = DSSMode(env_mode.lower())
|
||||
logger.info(f"Mode set via DSS_MODE env var: {resolved.value}")
|
||||
return resolved
|
||||
# Normalize string to enum
|
||||
return DSSMode(env_mode.lower())
|
||||
except ValueError:
|
||||
logger.warning(f"Invalid DSS_MODE env var '{env_mode}', ignoring.")
|
||||
|
||||
# 2. Check CI environment variables
|
||||
if self._is_ci_environment():
|
||||
logger.info("CI environment detected. Using CI mode (authoritative enforcement).")
|
||||
return DSSMode.CI
|
||||
|
||||
# 3. Check Configuration (if explicit, not AUTO)
|
||||
# 2. Check Configuration (if explicit)
|
||||
if self.mode != DSSMode.AUTO:
|
||||
logger.info(f"Using configured mode: {self.mode.value}")
|
||||
return self.mode
|
||||
|
||||
# 4. Auto-detect based on environment
|
||||
# 3. Auto-detect
|
||||
logger.info("Auto-detecting DSS mode...")
|
||||
|
||||
# Check for local .dss/ folder (indicates project setup)
|
||||
if self._has_local_dss_folder():
|
||||
logger.info("Found .dss/ folder. Using LOCAL mode with cache.")
|
||||
return DSSMode.LOCAL
|
||||
|
||||
# Check if local server is running
|
||||
is_local_healthy = await self._check_local_health()
|
||||
|
||||
if is_local_healthy:
|
||||
logger.info(f"Local server detected at {self.local_url}. Using LOCAL mode.")
|
||||
logger.info(f"Local server detected at {self.local_url}. Switching to LOCAL mode.")
|
||||
return DSSMode.LOCAL
|
||||
|
||||
# 5. Fallback to LOCAL (developer-first, will use stale cache if available)
|
||||
logger.info("Fallback to LOCAL mode (offline-capable with cache).")
|
||||
return DSSMode.LOCAL
|
||||
|
||||
def _is_ci_environment(self) -> bool:
|
||||
"""Check if running in a CI/CD environment."""
|
||||
for env_var in CI_ENV_VARS:
|
||||
if os.getenv(env_var):
|
||||
logger.debug(f"CI detected via {env_var} env var")
|
||||
return True
|
||||
return False
|
||||
|
||||
def _has_local_dss_folder(self) -> bool:
|
||||
"""Check if current directory or project has .dss/ folder."""
|
||||
# Check current working directory
|
||||
cwd_dss = Path.cwd() / ".dss"
|
||||
if cwd_dss.exists() and cwd_dss.is_dir():
|
||||
return True
|
||||
|
||||
# Check configured project path
|
||||
if self.project_path:
|
||||
project_dss = Path(self.project_path) / ".dss"
|
||||
if project_dss.exists() and project_dss.is_dir():
|
||||
return True
|
||||
|
||||
return False
|
||||
else:
|
||||
logger.info("Local server unreachable. Fallback to REMOTE mode.")
|
||||
# 4. Fallback
|
||||
return DSSMode.REMOTE
|
||||
|
||||
async def _check_local_health(self) -> bool:
|
||||
"""
|
||||
@@ -225,46 +161,3 @@ class DSSConfig(BaseModel):
|
||||
if active_mode == DSSMode.LOCAL:
|
||||
return self.local_url
|
||||
return self.remote_url
|
||||
|
||||
def get_mode_behavior(self, active_mode: DSSMode) -> dict:
|
||||
"""
|
||||
Get behavior configuration for the active mode.
|
||||
|
||||
Returns dict with:
|
||||
- blocking: Whether validation errors block operations
|
||||
- upload_metrics: Whether to upload metrics to dashboard
|
||||
- use_cache: Whether to use local .dss/ cache
|
||||
- cache_ttl: Cache time-to-live in seconds
|
||||
"""
|
||||
behaviors = {
|
||||
DSSMode.LOCAL: {
|
||||
"blocking": False, # Advisory only
|
||||
"upload_metrics": False,
|
||||
"use_cache": True,
|
||||
"cache_ttl": 3600, # 1 hour
|
||||
"show_stale_warning": True,
|
||||
},
|
||||
DSSMode.REMOTE: {
|
||||
"blocking": True,
|
||||
"upload_metrics": True,
|
||||
"use_cache": False,
|
||||
"cache_ttl": 0,
|
||||
"show_stale_warning": False,
|
||||
},
|
||||
DSSMode.CI: {
|
||||
"blocking": True, # Authoritative enforcement
|
||||
"upload_metrics": True,
|
||||
"use_cache": False,
|
||||
"cache_ttl": 0,
|
||||
"show_stale_warning": False,
|
||||
},
|
||||
DSSMode.AUTO: {
|
||||
# AUTO resolves to another mode, shouldn't reach here
|
||||
"blocking": False,
|
||||
"upload_metrics": False,
|
||||
"use_cache": True,
|
||||
"cache_ttl": 3600,
|
||||
"show_stale_warning": True,
|
||||
},
|
||||
}
|
||||
return behaviors.get(active_mode, behaviors[DSSMode.LOCAL])
|
||||
|
||||
Reference in New Issue
Block a user