log refactor

This commit is contained in:
2026-05-12 19:30:15 +03:00
parent 1d59df2233
commit b17b5333c7
84 changed files with 5827 additions and 3908 deletions

View File

@@ -16,7 +16,10 @@ from typing import Any, Dict, List, Optional
from git import Repo
from git.exc import InvalidGitRepositoryError, NoSuchPathError
from fastapi import HTTPException
from src.core.logger import logger, belief_scope
from src.core.logger import belief_scope
from src.core.cot_logger import MarkerLogger
log = MarkerLogger("GitBase")
from src.models.git import GitRepository
from src.models.config import AppConfigRecord
from src.core.database import SessionLocal
@@ -51,9 +54,7 @@ class GitServiceBase:
try:
base.mkdir(parents=True, exist_ok=True)
except (PermissionError, OSError) as e:
logger.warning(
f"[_ensure_base_path_exists][Coherence:Failed] Cannot create Git repositories base path: {self.base_path}. Error: {e}"
)
log.explore("Cannot create Git repositories base path", payload={"base_path": self.base_path}, error=str(e))
raise ValueError(f"Cannot create Git repositories base path: {self.base_path}. {e}")
# [/DEF:_ensure_base_path_exists:Function]
@@ -88,7 +89,7 @@ class GitServiceBase:
return str(repo_root.resolve())
return str((root / repo_root).resolve())
except Exception as e:
logger.warning(f"[_resolve_base_path][Coherence:Failed] Falling back to default path: {e}")
log.explore("Falling back to default base path", error=str(e))
return fallback_path
# [/DEF:_resolve_base_path:Function]
@@ -122,7 +123,7 @@ class GitServiceBase:
finally:
session.close()
except Exception as e:
logger.warning(f"[_update_repo_local_path][Coherence:Failed] {e}")
log.explore("Failed to update repo local path", error=str(e))
# [/DEF:_update_repo_local_path:Function]
# [DEF:_migrate_repo_directory:Function]
@@ -136,7 +137,7 @@ class GitServiceBase:
if source_abs == target_abs:
return source_abs
if os.path.exists(target_abs):
logger.warning(f"[_migrate_repo_directory][Action] Target already exists, keeping source path: {target_abs}")
log.explore(f"Target already exists, keeping source path: {target_abs}", error="Target path exists")
return source_abs
Path(target_abs).parent.mkdir(parents=True, exist_ok=True)
try:
@@ -144,9 +145,7 @@ class GitServiceBase:
except OSError:
shutil.move(source_abs, target_abs)
self._update_repo_local_path(dashboard_id, target_abs)
logger.info(
f"[_migrate_repo_directory][Coherence:OK] Repository migrated for dashboard {dashboard_id}: {source_abs} -> {target_abs}"
)
log.reflect(f"Repository migrated for dashboard {dashboard_id}: {source_abs} -> {target_abs}")
return target_abs
# [/DEF:_migrate_repo_directory:Function]
@@ -187,7 +186,7 @@ class GitServiceBase:
return self._migrate_repo_directory(dashboard_id, db_path, target_path)
return db_path
except Exception as e:
logger.warning(f"[_get_repo_path][Coherence:Failed] Could not resolve local_path from DB: {e}")
log.explore("Could not resolve local_path from DB", error=str(e))
legacy_id_path = os.path.join(self.legacy_base_path, str(dashboard_id))
if os.path.exists(legacy_id_path) and not os.path.exists(target_path):
return self._migrate_repo_directory(dashboard_id, legacy_id_path, target_path)
@@ -213,11 +212,11 @@ class GitServiceBase:
else:
auth_url = remote_url
if os.path.exists(repo_path):
logger.info(f"[init_repo][Action] Opening existing repo at {repo_path}")
log.reason(f"Opening existing repo at {repo_path}")
try:
repo = Repo(repo_path)
except (InvalidGitRepositoryError, NoSuchPathError):
logger.warning(f"[init_repo][Action] Existing path is not a Git repository, recreating: {repo_path}")
log.explore(f"Existing path is not a Git repository, recreating: {repo_path}", error="Not a git repository")
stale_path = Path(repo_path)
if stale_path.exists():
shutil.rmtree(stale_path, ignore_errors=True)
@@ -229,7 +228,7 @@ class GitServiceBase:
repo = Repo.clone_from(auth_url, repo_path)
self._ensure_gitflow_branches(repo, dashboard_id)
return repo
logger.info(f"[init_repo][Action] Cloning {remote_url} to {repo_path}")
log.reason(f"Cloning {remote_url} to {repo_path}")
repo = Repo.clone_from(auth_url, repo_path)
self._ensure_gitflow_branches(repo, dashboard_id)
return repo
@@ -271,7 +270,7 @@ class GitServiceBase:
raise
except Exception as e:
session.rollback()
logger.error(f"[delete_repo][Coherence:Failed] Failed to delete repository for dashboard {dashboard_id}: {e}")
log.explore(f"Failed to delete repository for dashboard {dashboard_id}", error=str(e))
raise HTTPException(status_code=500, detail=f"Failed to delete repository: {str(e)}")
finally:
session.close()
@@ -286,12 +285,12 @@ class GitServiceBase:
with belief_scope("GitService.get_repo"):
repo_path = self._get_repo_path(dashboard_id)
if not os.path.exists(repo_path):
logger.error(f"[get_repo][Coherence:Failed] Repository for dashboard {dashboard_id} does not exist")
log.explore(f"Repository for dashboard {dashboard_id} does not exist", error="Repository not found")
raise HTTPException(status_code=404, detail=f"Repository for dashboard {dashboard_id} not found")
try:
return Repo(repo_path)
except Exception as e:
logger.error(f"[get_repo][Coherence:Failed] Failed to open repository at {repo_path}: {e}")
log.explore(f"Failed to open repository at {repo_path}", error=str(e))
raise HTTPException(status_code=500, detail="Failed to open local Git repository")
# [/DEF:get_repo:Function]
@@ -310,9 +309,9 @@ class GitServiceBase:
with repo.config_writer(config_level="repository") as config_writer:
config_writer.set_value("user", "name", normalized_username)
config_writer.set_value("user", "email", normalized_email)
logger.info("[configure_identity][Action] Applied repository-local git identity for dashboard %s", dashboard_id)
log.reason(f"Applied repository-local git identity for dashboard {dashboard_id}")
except Exception as e:
logger.error(f"[configure_identity][Coherence:Failed] Failed to configure git identity: {e}")
log.explore("Failed to configure git identity", error=str(e))
raise HTTPException(status_code=500, detail=f"Failed to configure git identity: {str(e)}")
# [/DEF:configure_identity:Function]
# [/DEF:GitServiceBase:Class]

View File

@@ -11,7 +11,10 @@ from datetime import datetime
from git import Repo
from git.exc import GitCommandError
from fastapi import HTTPException
from src.core.logger import logger, belief_scope
from src.core.logger import belief_scope
from src.core.cot_logger import MarkerLogger
log = MarkerLogger("GitBranch")
# [DEF:GitServiceBranchMixin:Class]
@@ -34,26 +37,20 @@ class GitServiceBranchMixin:
if "main" in local_heads:
base_commit = local_heads["main"].commit
if base_commit is None:
logger.warning(
f"[_ensure_gitflow_branches][Action] Skipping branch bootstrap for dashboard {dashboard_id}: repository has no commits"
)
log.explore("Branch bootstrap skipped - no commits", payload={"dashboard_id": dashboard_id}, error="Repository has no initial commit to branch from")
return
if "main" not in local_heads:
local_heads["main"] = repo.create_head("main", base_commit)
logger.info(f"[_ensure_gitflow_branches][Action] Created local branch main for dashboard {dashboard_id}")
log.reason("Created local branch main", payload={"dashboard_id": dashboard_id})
for branch_name in ("dev", "preprod"):
if branch_name in local_heads:
continue
local_heads[branch_name] = repo.create_head(branch_name, local_heads["main"].commit)
logger.info(
f"[_ensure_gitflow_branches][Action] Created local branch {branch_name} for dashboard {dashboard_id}"
)
log.reason("Created local branch", payload={"branch_name": branch_name, "dashboard_id": dashboard_id})
try:
origin = repo.remote(name="origin")
except ValueError:
logger.info(
f"[_ensure_gitflow_branches][Action] Remote origin is not configured for dashboard {dashboard_id}; skipping remote branch creation"
)
log.reason("Remote origin not configured; skipping remote branch creation", payload={"dashboard_id": dashboard_id})
return
remote_branch_names = set()
try:
@@ -63,26 +60,24 @@ class GitServiceBranchMixin:
if remote_head:
remote_branch_names.add(str(remote_head))
except Exception as e:
logger.warning(f"[_ensure_gitflow_branches][Action] Failed to fetch origin refs: {e}")
log.explore("Failed to fetch origin refs", error=str(e))
for branch_name in required_branches:
if branch_name in remote_branch_names:
continue
try:
origin.push(refspec=f"{branch_name}:{branch_name}")
logger.info(
f"[_ensure_gitflow_branches][Action] Pushed branch {branch_name} to origin for dashboard {dashboard_id}"
)
log.reason("Pushed branch to origin", payload={"branch_name": branch_name, "dashboard_id": dashboard_id})
except Exception as e:
logger.error(f"[_ensure_gitflow_branches][Coherence:Failed] Failed to push branch {branch_name} to origin: {e}")
log.explore("Failed to push branch to origin", error=str(e))
raise HTTPException(
status_code=500,
detail=f"Failed to create default branch '{branch_name}' on remote: {str(e)}",
)
try:
repo.git.checkout("dev")
logger.info(f"[_ensure_gitflow_branches][Action] Checked out default branch dev for dashboard {dashboard_id}")
log.reason("Checked out default branch dev", payload={"dashboard_id": dashboard_id})
except Exception as e:
logger.warning(f"[_ensure_gitflow_branches][Action] Could not checkout dev branch for dashboard {dashboard_id}: {e}")
log.explore("Could not checkout dev branch", payload={"dashboard_id": dashboard_id}, error=str(e))
# [/DEF:_ensure_gitflow_branches:Function]
# [DEF:list_branches:Function]
@@ -93,7 +88,7 @@ class GitServiceBranchMixin:
def list_branches(self, dashboard_id: int) -> List[dict]:
with belief_scope("GitService.list_branches"):
repo = self.get_repo(dashboard_id)
logger.info(f"[list_branches][Action] Listing branches for {dashboard_id}. Refs: {repo.refs}")
log.reason("Listing branches", payload={"dashboard_id": dashboard_id})
branches = []
for ref in repo.refs:
try:
@@ -107,7 +102,7 @@ class GitServiceBranchMixin:
"last_updated": datetime.fromtimestamp(ref.commit.committed_date) if hasattr(ref, 'commit') else datetime.utcnow()
})
except Exception as e:
logger.warning(f"[list_branches][Action] Skipping ref {ref}: {e}")
log.explore("Skipping ref", payload={"ref": str(ref)}, error=str(e))
try:
active_name = repo.active_branch.name
if not any(b['name'] == active_name for b in branches):
@@ -116,7 +111,7 @@ class GitServiceBranchMixin:
"is_remote": False, "last_updated": datetime.utcnow()
})
except Exception as e:
logger.warning(f"[list_branches][Action] Could not determine active branch: {e}")
log.explore("Could not determine active branch", error=str(e))
if not branches:
branches.append({
"name": "dev", "commit_hash": "0000000",
@@ -134,9 +129,9 @@ class GitServiceBranchMixin:
def create_branch(self, dashboard_id: int, name: str, from_branch: str = "main"):
with belief_scope("GitService.create_branch"):
repo = self.get_repo(dashboard_id)
logger.info(f"[create_branch][Action] Creating branch {name} from {from_branch}")
log.reason("Creating branch", payload={"name": name, "from_branch": from_branch})
if not repo.heads and not repo.remotes:
logger.warning("[create_branch][Action] Repository is empty. Creating initial commit to enable branching.")
log.explore("Repository is empty; creating initial commit to enable branching", error="No branches or remotes exist; initializing from scratch")
readme_path = os.path.join(repo.working_dir, "README.md")
if not os.path.exists(readme_path):
with open(readme_path, "w") as f:
@@ -146,13 +141,13 @@ class GitServiceBranchMixin:
try:
repo.commit(from_branch)
except Exception:
logger.warning(f"[create_branch][Action] Source branch {from_branch} not found, using HEAD")
log.explore("Source branch not found, using HEAD", payload={"from_branch": from_branch}, error=f"Branch '{from_branch}' does not exist, falling back to HEAD")
from_branch = repo.head
try:
new_branch = repo.create_head(name, from_branch)
return new_branch
except Exception as e:
logger.error(f"[create_branch][Coherence:Failed] {e}")
log.explore("Failed to create branch", error=str(e))
raise
# [/DEF:create_branch:Function]
@@ -163,7 +158,7 @@ class GitServiceBranchMixin:
def checkout_branch(self, dashboard_id: int, name: str):
with belief_scope("GitService.checkout_branch"):
repo = self.get_repo(dashboard_id)
logger.info(f"[checkout_branch][Action] Checking out branch {name}")
log.reason("Checking out branch", payload={"name": name})
repo.git.checkout(name)
# [/DEF:checkout_branch:Function]
@@ -177,16 +172,16 @@ class GitServiceBranchMixin:
with belief_scope("GitService.commit_changes"):
repo = self.get_repo(dashboard_id)
if not repo.is_dirty(untracked_files=True) and not files:
logger.info(f"[commit_changes][Action] No changes to commit for dashboard {dashboard_id}")
log.reason("No changes to commit", payload={"dashboard_id": dashboard_id})
return
if files:
logger.info(f"[commit_changes][Action] Staging files: {files}")
log.reason("Staging files", payload={"files": files})
repo.index.add(files)
else:
logger.info("[commit_changes][Action] Staging all changes")
log.reason("Staging all changes")
repo.git.add(A=True)
repo.index.commit(message)
logger.info(f"[commit_changes][Coherence:OK] Committed changes with message: {message}")
log.reflect("Committed changes", payload={"message": message})
# [/DEF:commit_changes:Function]
# [/DEF:GitServiceBranchMixin:Class]
# [/DEF:GitServiceBranchMixin:Module]

View File

@@ -9,7 +9,10 @@ import httpx
from typing import Any, Dict, List, Optional
from urllib.parse import quote
from fastapi import HTTPException
from src.core.logger import logger, belief_scope
from src.core.cot_logger import MarkerLogger
from src.core.logger import belief_scope
log = MarkerLogger("GitGitea")
from src.models.git import GitProvider
@@ -26,13 +29,13 @@ class GitServiceGiteaMixin:
async def test_connection(self, provider: GitProvider, url: str, pat: str) -> bool:
with belief_scope("GitService.test_connection"):
if ".local" in url or "localhost" in url:
logger.info("[test_connection][Action] Local/Offline mode detected for URL")
log.reason("Local/Offline mode detected for URL")
return True
if not url.startswith(('http://', 'https://')):
logger.error(f"[test_connection][Coherence:Failed] Invalid URL protocol: {url}")
log.explore(f"Invalid URL protocol: {url}", error="Invalid URL protocol")
return False
if not pat or not pat.strip():
logger.error("[test_connection][Coherence:Failed] Git PAT is missing or empty")
log.explore("Git PAT is missing or empty", error="Git PAT is missing or empty")
return False
pat = pat.strip()
try:
@@ -52,10 +55,10 @@ class GitServiceGiteaMixin:
else:
return False
if resp.status_code != 200:
logger.error(f"[test_connection][Coherence:Failed] Git connection test failed for {provider} at {api_url}. Status: {resp.status_code}")
log.explore(f"Git connection test failed for {provider} at {api_url}. Status: {resp.status_code}", error="Git connection test failed")
return resp.status_code == 200
except Exception as e:
logger.error(f"[test_connection][Coherence:Failed] Error testing git connection: {e}")
log.explore(f"Error testing git connection: {e}", error=str(e))
return False
# [/DEF:test_connection:Function]
@@ -91,7 +94,7 @@ class GitServiceGiteaMixin:
async with httpx.AsyncClient(timeout=20.0) as client:
response = await client.request(method=method, url=url, headers=headers, json=payload)
except Exception as e:
logger.error(f"[gitea_request][Coherence:Failed] Network error: {e}")
log.explore(f"Network error: {e}", error=str(e))
raise HTTPException(status_code=503, detail=f"Gitea API is unavailable: {str(e)}")
if response.status_code >= 400:
detail = response.text
@@ -100,7 +103,7 @@ class GitServiceGiteaMixin:
detail = parsed.get("message") or parsed.get("error") or detail
except Exception:
pass
logger.error(f"[gitea_request][Coherence:Failed] method={method} endpoint={endpoint} status={response.status_code} detail={detail}")
log.explore(f"Gitea API error ({endpoint})", payload={"method": method, "status": response.status_code}, error=detail)
raise HTTPException(status_code=response.status_code, detail=f"Gitea API error: {detail}")
if response.status_code == 204:
return None
@@ -223,10 +226,7 @@ class GitServiceGiteaMixin:
exc.status_code == 404 and fallback_url and fallback_url != normalized_primary
)
if should_retry_with_fallback:
logger.warning(
"[create_gitea_pull_request][Action] Primary Gitea URL not found, retrying with remote host: %s",
fallback_url,
)
log.explore(f"Primary Gitea URL not found, retrying with remote host: {fallback_url}", error=fallback_url)
active_server_url = fallback_url
try:
data = await self._gitea_request("POST", active_server_url, pat, endpoint, payload=req_payload)

View File

@@ -8,7 +8,10 @@
from typing import Any, Dict, List
from datetime import datetime
from git import Repo
from src.core.logger import logger, belief_scope
from src.core.cot_logger import MarkerLogger
from src.core.logger import belief_scope
log = MarkerLogger("GitStatus")
# [DEF:GitServiceStatusMixin:Class]
@@ -31,7 +34,7 @@ class GitServiceStatusMixin:
try:
output = repo.git.status("--porcelain")
except Exception:
logger.warning("[_parse_status_porcelain][Coherence:Failed] git status --porcelain failed")
log.explore("git status --porcelain failed", error="git status --porcelain command failed")
return staged, modified, untracked
for line in output.split("\n"):
if not line:
@@ -156,7 +159,7 @@ class GitServiceStatusMixin:
"files_changed": list(commit.stats.files.keys())
})
except Exception as e:
logger.warning(f"[get_commit_history][Action] Could not retrieve commit history for dashboard {dashboard_id}: {e}")
log.explore(f"Could not retrieve commit history for dashboard {dashboard_id}: {e}", error=str(e))
return []
return commits
# [/DEF:get_commit_history:Function]

View File

@@ -12,7 +12,10 @@ from git import Repo
from git.exc import GitCommandError
from fastapi import HTTPException
from src.core.database import SessionLocal
from src.core.logger import logger, belief_scope
from src.core.logger import belief_scope
from src.core.cot_logger import MarkerLogger
log = MarkerLogger("GitSync")
from src.models.git import GitRepository, GitServerConfig
@@ -28,12 +31,12 @@ class GitServiceSyncMixin:
with belief_scope("GitService.push_changes"):
repo = self.get_repo(dashboard_id)
if not repo.heads:
logger.warning(f"[push_changes][Coherence:Failed] No local branches to push for dashboard {dashboard_id}")
log.explore("No local branches to push", payload={"dashboard_id": dashboard_id}, error="Repository has no local branch heads to push")
return
try:
origin = repo.remote(name='origin')
except ValueError:
logger.error(f"[push_changes][Coherence:Failed] Remote 'origin' not found for dashboard {dashboard_id}")
log.explore("Remote 'origin' not found", payload={"dashboard_id": dashboard_id}, error="Git remote 'origin' is not configured for this repository")
raise HTTPException(status_code=400, detail="Remote 'origin' not configured")
try:
origin_urls = list(origin.urls)
@@ -63,10 +66,7 @@ class GitServiceSyncMixin:
finally:
session.close()
except Exception as diag_error:
logger.warning(
"[push_changes][Action] Failed to load repository binding diagnostics for dashboard %s: %s",
dashboard_id, diag_error,
)
log.explore("Failed to load repository binding diagnostics", payload={"dashboard_id": dashboard_id}, error=str(diag_error))
realigned_origin_url = self._align_origin_host_with_config(
dashboard_id=dashboard_id,
origin=origin,
@@ -78,13 +78,17 @@ class GitServiceSyncMixin:
origin_urls = list(origin.urls)
except Exception:
origin_urls = []
logger.info(
"[push_changes][Action] Push diagnostics dashboard=%s config_id=%s config_url=%s binding_remote_url=%s origin_urls=%s origin_realigned=%s",
dashboard_id, binding_config_id, binding_config_url, binding_remote_url, origin_urls, bool(realigned_origin_url),
log.reason(
"Push diagnostics",
payload={
"dashboard_id": dashboard_id, "config_id": binding_config_id,
"config_url": binding_config_url, "binding_remote_url": binding_remote_url,
"origin_urls": origin_urls, "origin_realigned": bool(realigned_origin_url),
},
)
try:
current_branch = repo.active_branch
logger.info(f"[push_changes][Action] Pushing branch {current_branch.name} to origin")
log.reason("Pushing branch", payload={"branch": current_branch.name, "origin": True})
tracking_branch = None
try:
tracking_branch = current_branch.tracking_branch()
@@ -96,7 +100,7 @@ class GitServiceSyncMixin:
push_info = origin.push(refspec=f'{current_branch.name}:{current_branch.name}')
for info in push_info:
if info.flags & info.ERROR:
logger.error(f"[push_changes][Coherence:Failed] Error pushing ref {info.remote_ref_string}: {info.summary}")
log.explore("Error pushing ref", payload={"ref": info.remote_ref_string, "summary": info.summary}, error=f"Git push error: {info.summary}")
raise Exception(f"Git push error for {info.remote_ref_string}: {info.summary}")
except GitCommandError as e:
details = str(e)
@@ -106,10 +110,10 @@ class GitServiceSyncMixin:
status_code=409,
detail="Push rejected: remote branch contains newer commits. Run Pull first, resolve conflicts if any, then push again.",
)
logger.error(f"[push_changes][Coherence:Failed] Failed to push changes: {e}")
log.explore("Failed to push changes", error=str(e))
raise HTTPException(status_code=500, detail=f"Git push failed: {details}")
except Exception as e:
logger.error(f"[push_changes][Coherence:Failed] Failed to push changes: {e}")
log.explore("Failed to push changes", error=str(e))
raise HTTPException(status_code=500, detail=f"Git push failed: {str(e)}")
# [/DEF:push_changes:Function]
@@ -123,11 +127,14 @@ class GitServiceSyncMixin:
merge_head_path = os.path.join(repo.git_dir, "MERGE_HEAD")
if os.path.exists(merge_head_path):
payload = self._build_unfinished_merge_payload(repo)
logger.warning(
"[pull_changes][Action] Unfinished merge detected for dashboard %s (repo_path=%s git_dir=%s branch=%s merge_head=%s merge_msg=%s)",
dashboard_id, payload["repository_path"], payload["git_dir"],
payload["current_branch"], payload["merge_head"], payload["merge_message_preview"],
)
log.explore("Unfinished merge detected", error="Unfinished merge state found",
payload={
"dashboard_id": dashboard_id,
"repo_path": payload["repository_path"],
"git_dir": payload["git_dir"],
"branch": payload["current_branch"],
"merge_head": payload["merge_head"],
})
raise HTTPException(status_code=409, detail=payload)
try:
origin = repo.remote(name='origin')
@@ -136,26 +143,36 @@ class GitServiceSyncMixin:
origin_urls = list(origin.urls)
except Exception:
origin_urls = []
logger.info(
"[pull_changes][Action] Pull diagnostics dashboard=%s repo_path=%s branch=%s origin_urls=%s",
dashboard_id, repo.working_tree_dir, current_branch, origin_urls,
log.reason(
"Pull diagnostics",
payload={
"dashboard_id": dashboard_id,
"repo_path": repo.working_tree_dir,
"branch": current_branch,
"origin_urls": origin_urls,
},
)
origin.fetch(prune=True)
remote_ref = f"origin/{current_branch}"
has_remote_branch = any(ref.name == remote_ref for ref in repo.refs)
logger.info(
"[pull_changes][Action] Pull remote branch check dashboard=%s branch=%s remote_ref=%s exists=%s",
dashboard_id, current_branch, remote_ref, has_remote_branch,
log.reason(
"Pull remote branch check",
payload={
"dashboard_id": dashboard_id,
"branch": current_branch,
"remote_ref": remote_ref,
"exists": has_remote_branch,
},
)
if not has_remote_branch:
raise HTTPException(
status_code=409,
detail=f"Remote branch '{current_branch}' does not exist yet. Push this branch first.",
)
logger.info(f"[pull_changes][Action] Pulling changes from origin/{current_branch}")
log.reason("Pulling changes", payload={"branch": current_branch})
repo.git.pull("--no-rebase", "origin", current_branch)
except ValueError:
logger.error(f"[pull_changes][Coherence:Failed] Remote 'origin' not found for dashboard {dashboard_id}")
log.explore("Remote 'origin' not found", payload={"dashboard_id": dashboard_id}, error="Git remote 'origin' is not configured for this repository")
raise HTTPException(status_code=400, detail="Remote 'origin' not configured")
except GitCommandError as e:
details = str(e)
@@ -165,12 +182,12 @@ class GitServiceSyncMixin:
status_code=409,
detail="Pull requires conflict resolution. Resolve conflicts in repository and repeat operation.",
)
logger.error(f"[pull_changes][Coherence:Failed] Failed to pull changes: {e}")
log.explore("Failed to pull changes", error=str(e))
raise HTTPException(status_code=500, detail=f"Git pull failed: {details}")
except HTTPException:
raise
except Exception as e:
logger.error(f"[pull_changes][Coherence:Failed] Failed to pull changes: {e}")
log.explore("Failed to pull changes", error=str(e))
raise HTTPException(status_code=500, detail=f"Git pull failed: {str(e)}")
# [/DEF:pull_changes:Function]
# [/DEF:GitServiceSyncMixin:Class]

View File

@@ -12,7 +12,10 @@ from typing import Any, Dict, List, Optional
from urllib.parse import quote, urlparse
from fastapi import HTTPException
from src.core.database import SessionLocal
from src.core.logger import logger, belief_scope
from src.core.cot_logger import MarkerLogger
from src.core.logger import belief_scope
log = MarkerLogger("GitUrl")
from src.models.git import GitRepository, GitServerConfig
# [DEF:GitServiceUrlMixin:Class]
@@ -118,17 +121,11 @@ class GitServiceUrlMixin:
aligned_url = self._replace_host_in_url(source_origin_url, config_url)
if not aligned_url:
return None
logger.warning(
"[_align_origin_host_with_config][Action] Host mismatch for dashboard %s: config_host=%s origin_host=%s, applying origin.set_url",
dashboard_id, config_host, origin_host,
)
log.explore(f"Host mismatch for dashboard {dashboard_id}: config_host={config_host} origin_host={origin_host}, applying origin.set_url", error=f"Host mismatch for dashboard {dashboard_id}")
try:
origin.set_url(aligned_url)
except Exception as e:
logger.warning(
"[_align_origin_host_with_config][Coherence:Failed] Failed to set origin URL for dashboard %s: %s",
dashboard_id, e,
)
log.explore(f"Failed to set origin URL for dashboard {dashboard_id}: {e}", error=str(e))
return None
try:
session = SessionLocal()
@@ -144,10 +141,7 @@ class GitServiceUrlMixin:
finally:
session.close()
except Exception as e:
logger.warning(
"[_align_origin_host_with_config][Action] Failed to persist aligned remote_url for dashboard %s: %s",
dashboard_id, e,
)
log.explore(f"Failed to persist aligned remote_url for dashboard {dashboard_id}: {e}", error=str(e))
return aligned_url
# [/DEF:_align_origin_host_with_config:Function]