Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
ac554f8
fix: docker desktop のkind なのでいらない
yu-sugimoto Feb 28, 2026
986fdd3
feat: ジョブの継続機能を実装し、親ジョブとの関連を追加
yu-sugimoto Feb 28, 2026
178d8bc
feat: Job→Session DBモデル移行 + Alembicマイグレーション
yu-sugimoto Feb 28, 2026
5390561
feat: S3/MinIO基盤 + バックエンド設定追加
yu-sugimoto Feb 28, 2026
8932e1f
feat: sessiton系の移行
yu-sugimoto Feb 28, 2026
83e8790
feat: Session移行に伴うLangGraphワークフロー更新
yu-sugimoto Feb 28, 2026
e0ac21a
feat: SettingモデルをJobからSessionに変更
yu-sugimoto Feb 28, 2026
7753a5f
feat: ユースケース + APIルーター
yu-sugimoto Feb 28, 2026
a3406a9
feat: S3アクセスのためにboto3をClaude Agent SDKと共にインストール
yu-sugimoto Feb 28, 2026
ec03b03
feat: JobPollingおよびJobDetailコンポーネントを削除
yu-sugimoto Feb 28, 2026
417ead7
feat: S3Serviceのバケット確認メソッドをモック化
yu-sugimoto Feb 28, 2026
a9ae71a
feat: Job関連の機能をSessionに変更したのでフロントも修正
yu-sugimoto Feb 28, 2026
d3228b5
feat: コードのリファクタリングと不要なファイルの削除
yu-sugimoto Feb 28, 2026
b993a98
feat: リポジトリの初期化を簡素化し、冗長なコードを削除
yu-sugimoto Feb 28, 2026
1d73214
feat: セッション取得およびリスト表示時に関連するイテレーションと提案をロードするように変更
yu-sugimoto Feb 28, 2026
4712ec6
feat: バックエンドのテストジョブに環境変数を追加
yu-sugimoto Feb 28, 2026
1924e57
feat: S3サービスのエラーハンドリングを改善し、特定のエラーコードに基づいて処理を追加
yu-sugimoto Feb 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ jobs:
defaults:
run:
working-directory: backend
env:
ENVIRONMENT: development
POSTGRES_SERVER: localhost
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: test
POSTGRES_PORT: "5432"
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5
Expand Down
10 changes: 9 additions & 1 deletion backend/app/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,17 @@ class Settings(BaseSettings):
K8S_NAMESPACE: str = "default"
K8S_IN_CLUSTER: bool = False

# Artifact保存先
# Artifact保存先 (legacy, Phase 6 cleanup)
ARTIFACTS_DIR: str = "/tmp/ui-recommender-artifacts"

# S3 / MinIO設定
S3_BUCKET: str = "ui-recommender-artifacts"
S3_REGION: str = "us-east-1"
S3_ENDPOINT_URL: str = "" # MinIO: http://minio:9000
S3_ENDPOINT_URL_K8S: str = "" # K8sワーカー用。未設定時はS3_ENDPOINT_URLを使用
S3_ACCESS_KEY: str = "minioadmin"
S3_SECRET_KEY: str = "minioadmin"

# Worker設定
WORKER_IMAGE: str = "ui-recommender-worker:latest"
WORKER_DEADLINE_SECONDS: int = 900
Expand Down
10 changes: 0 additions & 10 deletions backend/app/di/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
from sqlalchemy.orm import Session

from app.repository.database import SessionLocal
from app.repository.job_repository import JobRepository
from app.repository.proposal_repository import ProposalRepository
from app.repository.setting_repository import SettingRepository


Expand All @@ -20,14 +18,6 @@ def get_db() -> Generator[Session]:
finally:
db.close()

@staticmethod
def get_job_repository(db: Session) -> JobRepository:
return JobRepository(db)

@staticmethod
def get_proposal_repository(db: Session) -> ProposalRepository:
return ProposalRepository(db)

@staticmethod
def get_setting_repository(db: Session) -> SettingRepository:
return SettingRepository(db)
16 changes: 3 additions & 13 deletions backend/app/di/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,18 @@
from sqlalchemy.orm import Session

from app.di.container import DIContainer
from app.repository.job_repository import JobRepository
from app.repository.proposal_repository import ProposalRepository
from app.repository.setting_repository import SettingRepository
from app.service.artifact_service import ArtifactService
from app.service.s3_service import S3Service


def get_db() -> Generator[Session]:
"""データベースセッションを取得"""
yield from DIContainer.get_db()


def get_job_repository(db: Session = Depends(get_db)) -> JobRepository:
return DIContainer.get_job_repository(db)


def get_proposal_repository(db: Session = Depends(get_db)) -> ProposalRepository:
return DIContainer.get_proposal_repository(db)


def get_setting_repository(db: Session = Depends(get_db)) -> SettingRepository:
return DIContainer.get_setting_repository(db)


def get_artifact_service() -> ArtifactService:
return ArtifactService()
def get_s3_service() -> S3Service:
return S3Service()
21 changes: 19 additions & 2 deletions backend/app/main.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@
import logging
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from app.core.middleware import ErrorHandlerMiddleware, RequestLoggingMiddleware
from app.router import router
from app.router.jobs import router as jobs_router
from app.router.sessions import router as sessions_router
from app.router.settings import router as settings_router

logger = logging.getLogger(__name__)


@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncIterator[None]:
"""Startup / shutdown lifecycle."""
from app.usecase.session_usecase import recover_stuck_proposals

await recover_stuck_proposals()
yield


# FastAPIのインスタンスを作成(Swagger UIのメタデータを設定)
app = FastAPI(
title="UI Recommender API",
description="UI推薦システムのバックエンドAPI",
version="0.1.0",
docs_url="/docs", # Swagger UI
redoc_url="/redoc", # ReDoc
lifespan=lifespan,
)

# ミドルウェア登録(後に追加したものが先に実行される)
Expand All @@ -30,5 +47,5 @@

# API層のルーティングを読み込む
app.include_router(router)
app.include_router(jobs_router)
app.include_router(sessions_router)
app.include_router(settings_router)
20 changes: 18 additions & 2 deletions backend/app/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,22 @@
# - マイグレーション(Alembic)で使用
# - Repository層の実装で使用

from .job import Job, JobStatus, Proposal, ProposalStatus, Setting
from .session import (
Iteration,
IterationStatus,
Proposal,
ProposalStatus,
Session,
SessionStatus,
Setting,
)

__all__ = ["Job", "JobStatus", "Proposal", "ProposalStatus", "Setting"]
__all__ = [
"Session",
"SessionStatus",
"Iteration",
"IterationStatus",
"Proposal",
"ProposalStatus",
"Setting",
]
16 changes: 3 additions & 13 deletions backend/app/model/base.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
from typing import Any
from sqlalchemy.orm import DeclarativeBase, declared_attr

from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.orm import as_declarative


@as_declarative()
class Base:
__allow_unmapped__ = True

id: Any
__name__: str

# Generate __tablename__ automatically
@declared_attr
class Base(DeclarativeBase):
@declared_attr.directive
def __tablename__(cls) -> str:
return cls.__name__.lower()
78 changes: 0 additions & 78 deletions backend/app/model/job.py

This file was deleted.

Loading