Fix git not found error crashing document uploads in container
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 3m13s

Install git in Docker image and wrap all subprocess git calls in
try/except so a missing or failing git binary never kills an upload
that already succeeded.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-14 12:38:40 +00:00
parent 5028f677f1
commit e698419faf
10 changed files with 106 additions and 91 deletions

View File

@@ -87,7 +87,7 @@ VALUES (
'752cebdd-6748-4a04-aacd-c7ab0294ef33', '752cebdd-6748-4a04-aacd-c7ab0294ef33',
'agent_completion', 'agent_completion',
'סוכן סיים משימה — נדרשת בדיקה והחלטה על הצעד הבא', 'סוכן סיים משימה — נדרשת בדיקה והחלטה על הצעד הבא',
'pending', 'queued',
'agent' 'agent'
);" );"
``` ```

View File

@@ -90,7 +90,7 @@ VALUES (
'752cebdd-6748-4a04-aacd-c7ab0294ef33', '752cebdd-6748-4a04-aacd-c7ab0294ef33',
'agent_completion', 'agent_completion',
'מייצא טיוטה סיים משימה — נדרשת בדיקה', 'מייצא טיוטה סיים משימה — נדרשת בדיקה',
'pending', 'agent' 'queued', 'agent'
);" );"
``` ```

View File

@@ -116,6 +116,6 @@ VALUES (
'752cebdd-6748-4a04-aacd-c7ab0294ef33', '752cebdd-6748-4a04-aacd-c7ab0294ef33',
'agent_completion', 'agent_completion',
'מגיה מסמכים סיים משימה — נדרשת בדיקה', 'מגיה מסמכים סיים משימה — נדרשת בדיקה',
'pending', 'agent' 'queued', 'agent'
);" );"
``` ```

View File

@@ -121,6 +121,6 @@ VALUES (
'752cebdd-6748-4a04-aacd-c7ab0294ef33', '752cebdd-6748-4a04-aacd-c7ab0294ef33',
'agent_completion', 'agent_completion',
'בודק איכות סיים משימה — נדרשת בדיקה', 'בודק איכות סיים משימה — נדרשת בדיקה',
'pending', 'agent' 'queued', 'agent'
);" );"
``` ```

View File

@@ -110,7 +110,7 @@ VALUES (
'752cebdd-6748-4a04-aacd-c7ab0294ef33', '752cebdd-6748-4a04-aacd-c7ab0294ef33',
'agent_completion', 'agent_completion',
'חוקר תקדימים סיים משימה — נדרשת בדיקה', 'חוקר תקדימים סיים משימה — נדרשת בדיקה',
'pending', 'agent' 'queued', 'agent'
);" );"
``` ```

View File

@@ -159,7 +159,7 @@ VALUES (
'752cebdd-6748-4a04-aacd-c7ab0294ef33', '752cebdd-6748-4a04-aacd-c7ab0294ef33',
'agent_completion', 'agent_completion',
'כותב החלטה סיים משימה — נדרשת בדיקה', 'כותב החלטה סיים משימה — נדרשת בדיקה',
'pending', 'agent' 'queued', 'agent'
);" );"
``` ```

View File

@@ -34,7 +34,7 @@ WORKDIR /app
# Install Node.js 20.x # Install Node.js 20.x
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \
curl ca-certificates \ curl ca-certificates git \
&& curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ && curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \ && apt-get install -y --no-install-recommends nodejs \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*

View File

@@ -106,7 +106,8 @@ async def case_create(
notes_file = case_dir / "notes.md" notes_file = case_dir / "notes.md"
notes_file.write_text(f"# הערות - תיק {case_number}\n\n{notes}\n") notes_file.write_text(f"# הערות - תיק {case_number}\n\n{notes}\n")
# Initialize git repo # Initialize git repo (best-effort)
try:
subprocess.run(["git", "init"], cwd=case_dir, capture_output=True) subprocess.run(["git", "init"], cwd=case_dir, capture_output=True)
subprocess.run(["git", "add", "."], cwd=case_dir, capture_output=True) subprocess.run(["git", "add", "."], cwd=case_dir, capture_output=True)
subprocess.run( subprocess.run(
@@ -117,6 +118,8 @@ async def case_create(
"GIT_COMMITTER_NAME": "Ezer Mishpati", "GIT_COMMITTER_EMAIL": "legal@local", "GIT_COMMITTER_NAME": "Ezer Mishpati", "GIT_COMMITTER_EMAIL": "legal@local",
"PATH": "/usr/bin:/bin"}, "PATH": "/usr/bin:/bin"},
) )
except Exception:
pass # git not available — non-critical
return json.dumps(case, default=str, ensure_ascii=False, indent=2) return json.dumps(case, default=str, ensure_ascii=False, indent=2)
@@ -199,7 +202,8 @@ async def case_update(
updated = await db.update_case(UUID(case["id"]), **fields) updated = await db.update_case(UUID(case["id"]), **fields)
# Git commit the update # Git commit the update (best-effort)
try:
case_dir = config.find_case_dir(case_number) case_dir = config.find_case_dir(case_number)
if case_dir.exists(): if case_dir.exists():
case_json = case_dir / "case.json" case_json = case_dir / "case.json"
@@ -213,6 +217,8 @@ async def case_update(
"GIT_COMMITTER_NAME": "Ezer Mishpati", "GIT_COMMITTER_EMAIL": "legal@local", "GIT_COMMITTER_NAME": "Ezer Mishpati", "GIT_COMMITTER_EMAIL": "legal@local",
"PATH": "/usr/bin:/bin"}, "PATH": "/usr/bin:/bin"},
) )
except Exception:
pass # git not available — non-critical
return json.dumps(updated, default=str, ensure_ascii=False, indent=2) return json.dumps(updated, default=str, ensure_ascii=False, indent=2)

View File

@@ -67,7 +67,8 @@ async def document_upload(
await db.update_document(UUID(doc["id"]), doc_type=classified_type) await db.update_document(UUID(doc["id"]), doc_type=classified_type)
doc["doc_type"] = classified_type doc["doc_type"] = classified_type
# Git commit # Git commit (best-effort — don't fail upload on git errors)
try:
repo_dir = config.find_case_dir(case_number) repo_dir = config.find_case_dir(case_number)
if repo_dir.exists(): if repo_dir.exists():
subprocess.run(["git", "add", "."], cwd=repo_dir, capture_output=True) subprocess.run(["git", "add", "."], cwd=repo_dir, capture_output=True)
@@ -92,6 +93,8 @@ async def document_upload(
"GIT_COMMITTER_NAME": "Ezer Mishpati", "GIT_COMMITTER_EMAIL": "legal@local", "GIT_COMMITTER_NAME": "Ezer Mishpati", "GIT_COMMITTER_EMAIL": "legal@local",
"PATH": "/usr/bin:/bin"}, "PATH": "/usr/bin:/bin"},
) )
except Exception:
pass # git not available in container — non-critical
return json.dumps({ return json.dumps({
"document": doc, "document": doc,

View File

@@ -2565,7 +2565,8 @@ async def _process_tagged_document(task_id: str, dest: Path, case_number: str, c
_progress[task_id] = {"status": "processing", "filename": display_name, "step": "extracting"} _progress[task_id] = {"status": "processing", "filename": display_name, "step": "extracting"}
result = await processor.process_document(doc_id, case_id) result = await processor.process_document(doc_id, case_id)
# Git commit + push # Git commit + push (best-effort — don't fail upload on git errors)
try:
repo_dir = config.find_case_dir(case_number) repo_dir = config.find_case_dir(case_number)
if repo_dir.exists(): if repo_dir.exists():
env = { env = {
@@ -2584,6 +2585,8 @@ async def _process_tagged_document(task_id: str, dest: Path, case_number: str, c
**env, **env,
"GIT_TERMINAL_PROMPT": "0", "GIT_TERMINAL_PROMPT": "0",
}) })
except Exception:
logger.warning("Git commit/push failed for %s (non-critical)", display_name)
_progress[task_id] = { _progress[task_id] = {
"status": "completed", "status": "completed",
@@ -2821,7 +2824,8 @@ async def _process_case_document(task_id: str, source: Path, req: ClassifyReques
_progress[task_id] = {"status": "processing", "filename": req.filename, "step": "extracting"} _progress[task_id] = {"status": "processing", "filename": req.filename, "step": "extracting"}
result = await processor.process_document(UUID(doc["id"]), case_id) result = await processor.process_document(UUID(doc["id"]), case_id)
# Git commit # Git commit (best-effort)
try:
repo_dir = config.find_case_dir(req.case_number) repo_dir = config.find_case_dir(req.case_number)
if repo_dir.exists(): if repo_dir.exists():
subprocess.run(["git", "add", "."], cwd=repo_dir, capture_output=True) subprocess.run(["git", "add", "."], cwd=repo_dir, capture_output=True)
@@ -2836,6 +2840,8 @@ async def _process_case_document(task_id: str, source: Path, req: ClassifyReques
"GIT_COMMITTER_NAME": "Ezer Mishpati", "GIT_COMMITTER_EMAIL": "legal@local", "GIT_COMMITTER_NAME": "Ezer Mishpati", "GIT_COMMITTER_EMAIL": "legal@local",
"PATH": "/usr/bin:/bin"}, "PATH": "/usr/bin:/bin"},
) )
except Exception:
logger.warning("Git commit failed for %s (non-critical)", req.filename)
# Remove from uploads # Remove from uploads
source.unlink(missing_ok=True) source.unlink(missing_ok=True)