ci: migrate GitHub actions to Gitea actions
Deploy CV Site (andreknie.de) / deploy (push) Canceled after 0s
Deploy CV Site (andreknie.de) / deploy (push) Canceled after 0s
This commit is contained in:
@@ -1,21 +0,0 @@
|
||||
name: Deploy to VPS
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Deploy to VPS via SSH
|
||||
uses: appleboy/ssh-action@v1
|
||||
with:
|
||||
host: 217.160.174.2
|
||||
username: root
|
||||
key: ${{ secrets.VPS_SSH_KEY }}
|
||||
script: |
|
||||
cd /opt/AI-Orchestrator
|
||||
git pull origin main
|
||||
docker compose up -d --build
|
||||
echo "Deploy complete"
|
||||
@@ -1,32 +0,0 @@
|
||||
name: PAT Lifecycle Check
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 6 * * 1' # Every Monday at 06:00 UTC
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
check-pats:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- name: Install dependencies
|
||||
run: pip install -r scripts/pat_manager/requirements.txt
|
||||
- name: Run PAT Manager
|
||||
env:
|
||||
GITLAB_PAT: ${{ secrets.GITLAB_PAT }}
|
||||
GITLAB_URL: https://gitlab.com
|
||||
JIRA_PAT: ${{ secrets.JIRA_PAT }}
|
||||
JIRA_URL: https://jira.atlassian.net
|
||||
CONFLUENCE_PAT: ${{ secrets.CONFLUENCE_PAT }}
|
||||
CONFLUENCE_URL: https://confluence.atlassian.net
|
||||
ORGMYLIFE_API_KEY: ${{ secrets.ORGMYLIFE_API_SECRET }}
|
||||
ORGMYLIFE_URL: https://orgmylife.app
|
||||
ORGMYLIFE_USER: ${{ secrets.ORGMYLIFE_USER }}
|
||||
ORGMYLIFE_PASS: ${{ secrets.ORGMYLIFE_PASS }}
|
||||
GH_TOKEN: ${{ secrets.PAT_MANAGER_TOKEN }}
|
||||
ALERT_CHANNEL: orgmylife
|
||||
run: python -m scripts.pat_manager
|
||||
@@ -1,38 +0,0 @@
|
||||
name: Sync Tasks to OrgMyLife
|
||||
|
||||
on:
|
||||
push:
|
||||
paths: ['PLAN.md', 'TASKS.md', 'SETUP_TODO.md']
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Parse open tasks and sync to OrgMyLife
|
||||
run: |
|
||||
REPO_NAME="AI-Orchestrator"
|
||||
|
||||
TASKS="[]"
|
||||
for file in SETUP_TODO.md PLAN.md TASKS.md; do
|
||||
if [ -f "$file" ]; then
|
||||
ITEMS=$(grep -E '^\s*- \[ \]' "$file" | sed 's/.*- \[ \] //' | head -50)
|
||||
if [ -n "$ITEMS" ]; then
|
||||
TASKS=$(echo "$ITEMS" | jq -R -s 'split("\n") | map(select(length > 0)) | map({"title": ., "status": "backlog"})')
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Found tasks: $TASKS"
|
||||
|
||||
PAYLOAD=$(jq -n --arg repo "$REPO_NAME" --argjson tasks "$TASKS" '{"repo": $repo, "tasks": $tasks}')
|
||||
|
||||
curl -s -X POST \
|
||||
-u "${{ secrets.ORGMYLIFE_USER }}:${{ secrets.ORGMYLIFE_PASS }}" \
|
||||
-H "X-API-Key: ${{ secrets.ORGMYLIFE_API_SECRET }}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$PAYLOAD" \
|
||||
"https://api.andreknie.de/api/projects/sync"
|
||||
@@ -15,6 +15,8 @@ authors = [
|
||||
|
||||
dependencies = [
|
||||
"pyyaml>=6.0",
|
||||
"pypdf>=4.0",
|
||||
"python-docx>=1.1.0",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
|
||||
@@ -127,11 +127,13 @@ def register_default_strategies() -> None:
|
||||
from monorepo.knowledge.sources.jira import JiraSource
|
||||
from monorepo.knowledge.sources.markdown import MarkdownSource
|
||||
from monorepo.knowledge.sources.pdf import PDFSource
|
||||
from monorepo.knowledge.sources.docx import DocxSource
|
||||
from monorepo.knowledge.sources.wissensdatenbank import WissensdatenbankSource
|
||||
|
||||
defaults: dict[str, type[SourceStrategy]] = {
|
||||
"markdown": MarkdownSource,
|
||||
"pdf": PDFSource,
|
||||
"docx": DocxSource,
|
||||
"confluence": ConfluenceSource,
|
||||
"jira": JiraSource,
|
||||
"email": EmailSource,
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
"""DOCX-Quellstrategie für die ETL-Pipeline.
|
||||
|
||||
Implementiert die Extraktion von Text aus DOCX-Dateien.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from datetime import date, datetime
|
||||
from pathlib import Path
|
||||
|
||||
from monorepo.knowledge.artifact import Artifact, ArtifactMetadata, compute_content_hash
|
||||
from monorepo.knowledge.sources.base import (
|
||||
ExtractionResult,
|
||||
SourceConfig,
|
||||
SourceError,
|
||||
SourceStrategy,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
DOCX_EXTENSIONS = {".docx"}
|
||||
|
||||
|
||||
def _extract_docx_text(file_path: Path) -> str:
|
||||
try:
|
||||
import docx # type: ignore[import-untyped]
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"Keine DOCX-Bibliothek verfügbar. "
|
||||
"Installiere 'python-docx': pip install python-docx"
|
||||
)
|
||||
|
||||
doc = docx.Document(str(file_path))
|
||||
full_text = []
|
||||
for para in doc.paragraphs:
|
||||
full_text.append(para.text)
|
||||
|
||||
return "\n\n".join(full_text)
|
||||
|
||||
|
||||
class DocxSource(SourceStrategy):
|
||||
"""Quellstrategie für DOCX-Dateien."""
|
||||
|
||||
def extract(self, config: SourceConfig, context: str) -> ExtractionResult:
|
||||
result = ExtractionResult()
|
||||
|
||||
source_path = self._resolve_source_path(config)
|
||||
if source_path is None:
|
||||
result.errors.append(
|
||||
SourceError(
|
||||
source_name=config.name,
|
||||
error_type="parse",
|
||||
message="Kein gültiger Pfad in config.params['path'] oder config.params['directory']",
|
||||
timestamp=datetime.now().isoformat(),
|
||||
retry=False,
|
||||
)
|
||||
)
|
||||
return result
|
||||
|
||||
files = self._collect_files(source_path)
|
||||
if not files:
|
||||
logger.info("Keine DOCX-Dateien gefunden in: %s", source_path)
|
||||
return result
|
||||
|
||||
for file_path in files:
|
||||
try:
|
||||
artifact = self._process_file(file_path, config, context)
|
||||
if artifact is not None:
|
||||
result.artifacts.append(artifact)
|
||||
except Exception as e:
|
||||
logger.error("Fehler bei der Verarbeitung von %s: %s", file_path, e)
|
||||
result.errors.append(
|
||||
SourceError(
|
||||
source_name=config.name,
|
||||
error_type="parse",
|
||||
message=f"Fehler bei {file_path.name}: {e}",
|
||||
timestamp=datetime.now().isoformat(),
|
||||
retry=True,
|
||||
artifact_path=str(file_path),
|
||||
)
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
def supports_incremental(self) -> bool:
|
||||
return True
|
||||
|
||||
def _resolve_source_path(self, config: SourceConfig) -> Path | None:
|
||||
path_str = config.params.get("path") or config.params.get("directory") or ""
|
||||
if not path_str:
|
||||
return None
|
||||
source_path = Path(path_str)
|
||||
if not source_path.exists():
|
||||
return None
|
||||
return source_path
|
||||
|
||||
def _collect_files(self, source_path: Path) -> list[Path]:
|
||||
if source_path.is_file():
|
||||
if source_path.suffix.lower() in DOCX_EXTENSIONS:
|
||||
return [source_path]
|
||||
return []
|
||||
|
||||
files: list[Path] = []
|
||||
for ext in DOCX_EXTENSIONS:
|
||||
files.extend(source_path.rglob(f"*{ext}"))
|
||||
return sorted(files)
|
||||
|
||||
def _process_file(
|
||||
self, file_path: Path, config: SourceConfig, context: str
|
||||
) -> Artifact | None:
|
||||
text = ""
|
||||
try:
|
||||
text = _extract_docx_text(file_path)
|
||||
except Exception as e:
|
||||
logger.warning("DOCX Extraktion fehlgeschlagen für %s: %s", file_path, e)
|
||||
|
||||
return self._create_artifact(file_path, text, context)
|
||||
|
||||
def _create_artifact(
|
||||
self, file_path: Path, text: str, context: str
|
||||
) -> Artifact:
|
||||
title = file_path.stem.replace("-", " ").replace("_", " ").strip()
|
||||
if not title:
|
||||
title = file_path.name
|
||||
|
||||
content_hash = compute_content_hash(text) if text else ""
|
||||
|
||||
metadata = ArtifactMetadata(
|
||||
type="reference",
|
||||
title=title,
|
||||
tags=["docx"],
|
||||
source_context=context,
|
||||
created=date.today(),
|
||||
updated=date.today(),
|
||||
shareable=False,
|
||||
content_hash=content_hash,
|
||||
source={
|
||||
"type": "docx",
|
||||
"file": str(file_path),
|
||||
},
|
||||
category="references",
|
||||
)
|
||||
|
||||
content = f"# {title}\n\n{text}\n" if text else f"# {title}\n\n"
|
||||
|
||||
return Artifact(
|
||||
metadata=metadata,
|
||||
content=content,
|
||||
file_path=file_path,
|
||||
)
|
||||
Reference in New Issue
Block a user