Compare commits
34 Commits
v0.1.1
...
45fbf975b3
| Author | SHA1 | Date | |
|---|---|---|---|
| 45fbf975b3 | |||
| b8f2798e29 | |||
| c762d91eb1 | |||
| 35a68387ab | |||
| 9b13c69631 | |||
| 2ca1ea29b2 | |||
| 5e86615bde | |||
| 6701a4b392 | |||
| 68372405d6 | |||
| f1ea0de247 | |||
| 974d008825 | |||
| 8a87d94e6d | |||
| ec99a501fc | |||
| c256b26601 | |||
| 56a3c1257d | |||
| 79d23f936a | |||
| f02e916d33 | |||
| 4e64c83c4b | |||
| 07cae9abd1 | |||
| 21b2dffc37 | |||
| 2d1055cccf | |||
| fdb2447862 | |||
| 13746ee8cc | |||
| 49f31e492f | |||
| f1fd1b11a1 | |||
| 6f3b21ab17 | |||
| 566f0f6ea2 | |||
| 340c54b3d8 | |||
| 8d0bc59d28 | |||
| f969724ee4 | |||
| ffd2678c91 | |||
| 365f110f9c | |||
| 59d40241e2 | |||
| 51fb30646c |
@@ -0,0 +1,88 @@
|
|||||||
|
name: CI/CD Awesome Pipeline
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*.*.*'
|
||||||
|
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY_URL: ${{ vars.REGISTRY_URL || 'gitea.iswearihadsomethingforthis.net' }}
|
||||||
|
REGISTRY_USER: ${{ vars.REGISTRY_USER || 'francwa' }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: Test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Build and run tests
|
||||||
|
env:
|
||||||
|
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
||||||
|
TMDB_API_KEY: ${{ secrets.TMDB_API_KEY }}
|
||||||
|
run: make _ci-run-tests
|
||||||
|
|
||||||
|
build-and-push:
|
||||||
|
name: Build & Push to Registry
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: test
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Load config from Makefile
|
||||||
|
id: config
|
||||||
|
run: make -s _ci-dump-config >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: 🏷️ Docker Metadata (Tags & Labels)
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: gitea.iswearihadsomethingforthis.net/francwa/${{ steps.config.outputs.image_name }}
|
||||||
|
tags: |
|
||||||
|
# Tagged (v1.2.3)
|
||||||
|
type=semver,pattern={{ version }}
|
||||||
|
# Latest
|
||||||
|
type=raw,value=latest,enable={{ is_default_branch }}
|
||||||
|
|
||||||
|
- name: Login to Gitea Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: gitea.iswearihadsomethingforthis.net
|
||||||
|
username: ${{ gitea.actor }}
|
||||||
|
password: ${{ secrets.G1T34_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
id: docker_build
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./brain/Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
build-args: |
|
||||||
|
PYTHON_VERSION=${{ steps.config.outputs.python_version }}
|
||||||
|
PYTHON_VERSION_SHORT=${{ steps.config.outputs.python_version_short }}
|
||||||
|
RUNNER=${{ steps.config.outputs.runner }}
|
||||||
|
|
||||||
|
- name: 🛡️ Run Trivy Vulnerability Scanner
|
||||||
|
uses: docker://aquasec/trivy:latest
|
||||||
|
env:
|
||||||
|
TRIVY_USERNAME: ${{ gitea.actor }}
|
||||||
|
TRIVY_PASSWORD: ${{ secrets.G1T34_TOKEN }}
|
||||||
|
# Unset the fake GITHUB_TOKEN injected by Gitea
|
||||||
|
GITHUB_TOKEN: ""
|
||||||
|
with:
|
||||||
|
args: image --format table --output trivy-report.txt --exit-code 0 --ignore-unfixed --severity CRITICAL,HIGH gitea.iswearihadsomethingforthis.net/francwa/${{ steps.config.outputs.image_name }}:latest
|
||||||
|
|
||||||
|
- name: 📤 Upload Security Report
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: security-report
|
||||||
|
path: trivy-report.txt
|
||||||
|
retention-days: 7
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
name: Renovate Bot
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
# Every Monday 4AM
|
||||||
|
- cron: '0 4 * * 1'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
renovate:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Run Renovate
|
||||||
|
uses: docker://renovate/renovate:latest
|
||||||
|
env:
|
||||||
|
RENOVATE_PLATFORM: "gitea"
|
||||||
|
RENOVATE_ENDPOINT: "https://gitea.iswearihadsomethingforthis.net/api/v1"
|
||||||
|
RENOVATE_TOKEN: "${{ secrets.RENOVATE_TOKEN }}"
|
||||||
|
RENOVATE_REPOSITORIES: '["${{ gitea.repository }}"]'
|
||||||
|
RENOVATE_GIT_AUTHOR: "Renovate Bot <renovate@bot.local>"
|
||||||
|
# Might need a free github token if lots of depencies
|
||||||
|
# RENOVATE_GITHUB_TOKEN: "${{ secrets.GITHUB_COM_TOKEN }}"
|
||||||
@@ -18,18 +18,18 @@ repos:
|
|||||||
hooks:
|
hooks:
|
||||||
- id: ruff-check
|
- id: ruff-check
|
||||||
name: Ruff Linter
|
name: Ruff Linter
|
||||||
entry: bash -c 'cd brain && poetry run ruff check --fix'
|
entry: bash -c 'make lint'
|
||||||
language: system
|
language: system
|
||||||
types: [python]
|
types: [python]
|
||||||
|
|
||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
name: Ruff Formatter
|
name: Ruff Formatter
|
||||||
entry: bash -c 'cd brain && poetry run ruff format'
|
entry: bash -c 'make format'
|
||||||
language: system
|
language: system
|
||||||
types: [python]
|
types: [python]
|
||||||
|
|
||||||
- id: system-pytest
|
- id: system-pytest
|
||||||
name: Pytest
|
name: Pytest
|
||||||
entry: bash -c 'cd brain && poetry run pytest -n auto --dist=loadscope'
|
entry: bash -c 'make test'
|
||||||
language: system
|
language: system
|
||||||
always_run: true
|
always_run: true
|
||||||
|
|||||||
@@ -1,25 +1,266 @@
|
|||||||
# Versioning
|
.POSIX:
|
||||||
check-branch-is-main:
|
.SUFFIXES:
|
||||||
@current_branch=$$(git rev-parse --abbrev-ref HEAD); \
|
.DEFAULT_GOAL := help
|
||||||
if [ "$$current_branch" != "main" ]; then \
|
|
||||||
echo "Error: not on the main branch" \
|
# --- SETTINGS ---
|
||||||
exit 1; \
|
CORE_DIR = brain
|
||||||
|
IMAGE_NAME = agent_media
|
||||||
|
# renovate: datasource=docker depName=python
|
||||||
|
PYTHON_VERSION = $(shell grep "python" $(CORE_DIR)/pyproject.toml | head -n 1 | sed -E 's/.*[=<>^~"]+ *([0-9]+\.[0-9]+(\.[0-9]+)?).*/\1/')
|
||||||
|
PYTHON_VERSION_SHORT = $(shell echo $(PYTHON_VERSION) | cut -d. -f1,2)
|
||||||
|
# Change to 'uv' when ready.
|
||||||
|
RUNNER ?= poetry
|
||||||
|
SERVICE_NAME = agent_media
|
||||||
|
|
||||||
|
export IMAGE_NAME
|
||||||
|
export PYTHON_VERSION
|
||||||
|
export PYTHON_VERSION_SHORT
|
||||||
|
export RUNNER
|
||||||
|
|
||||||
|
# --- ADAPTERS ---
|
||||||
|
# UV uses "sync", Poetry uses "install". Both install DEV deps by default.
|
||||||
|
INSTALL_CMD = $(if $(filter uv,$(RUNNER)),sync,install)
|
||||||
|
|
||||||
|
# --- MACROS ---
|
||||||
|
ARGS = $(filter-out $@,$(MAKECMDGOALS))
|
||||||
|
BUMP_CMD = cd $(CORE_DIR) && $(RUNNER) run bump-my-version bump
|
||||||
|
COMPOSE_CMD = docker-compose
|
||||||
|
DOCKER_CMD = docker build \
|
||||||
|
--build-arg PYTHON_VERSION=$(PYTHON_VERSION) \
|
||||||
|
--build-arg PYTHON_VERSION_SHORT=$(PYTHON_VERSION_SHORT) \
|
||||||
|
--build-arg RUNNER=$(RUNNER) \
|
||||||
|
-f $(CORE_DIR)/Dockerfile \
|
||||||
|
-t $(IMAGE_NAME):latest .
|
||||||
|
|
||||||
|
RUNNER_ADD = cd $(CORE_DIR) && $(RUNNER) add
|
||||||
|
RUNNER_HOOKS = cd $(CORE_DIR) && $(RUNNER) run pre-commit install -c ../.pre-commit-config.yaml
|
||||||
|
RUNNER_INSTALL = cd $(CORE_DIR) && $(RUNNER) $(INSTALL_CMD)
|
||||||
|
RUNNER_RUN = cd $(CORE_DIR) && $(RUNNER) run
|
||||||
|
RUNNER_UPDATE = cd $(CORE_DIR) && $(RUNNER) update
|
||||||
|
|
||||||
|
# --- STYLES ---
|
||||||
|
B = \033[1m
|
||||||
|
G = \033[32m
|
||||||
|
T = \033[36m
|
||||||
|
R = \033[0m
|
||||||
|
|
||||||
|
# --- TARGETS ---
|
||||||
|
.PHONY: add build build-test check-docker check-runner clean coverage down format help init-dotenv install install-hooks lint logs major minor patch prune ps python-version restart run shell test up update _check_branch _ci-dump-config _ci-run-tests _push_tag
|
||||||
|
|
||||||
|
# Catch-all for args
|
||||||
|
%:
|
||||||
|
@:
|
||||||
|
|
||||||
|
add: check-runner
|
||||||
|
@echo "$(T)➕ Adding dependency ($(RUNNER)): $(ARGS)$(R)"
|
||||||
|
$(RUNNER_ADD) $(ARGS)
|
||||||
|
|
||||||
|
build: check-docker
|
||||||
|
@echo "$(T)🐳 Building Docker image...$(R)"
|
||||||
|
$(DOCKER_CMD)
|
||||||
|
@echo "✅ Image $(IMAGE_NAME):latest ready."
|
||||||
|
|
||||||
|
build-test: check-docker
|
||||||
|
@echo "$(T)🐳 Building test image (with dev deps)...$(R)"
|
||||||
|
docker build \
|
||||||
|
--build-arg RUNNER=$(RUNNER) \
|
||||||
|
--build-arg PYTHON_VERSION=$(PYTHON_VERSION) \
|
||||||
|
--build-arg PYTHON_VERSION_SHORT=$(PYTHON_VERSION_SHORT) \
|
||||||
|
-f $(CORE_DIR)/Dockerfile \
|
||||||
|
--target test \
|
||||||
|
-t $(IMAGE_NAME):test .
|
||||||
|
@echo "✅ Test image $(IMAGE_NAME):test ready."
|
||||||
|
|
||||||
|
check-docker:
|
||||||
|
@command -v docker >/dev/null 2>&1 || { echo "$(R)❌ Docker not installed$(R)"; exit 1; }
|
||||||
|
@docker info >/dev/null 2>&1 || { echo "$(R)❌ Docker daemon not running$(R)"; exit 1; }
|
||||||
|
|
||||||
|
check-runner:
|
||||||
|
@command -v $(RUNNER) >/dev/null 2>&1 || { echo "$(R)❌ $(RUNNER) not installed$(R)"; exit 1; }
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo "$(T)🧹 Cleaning caches...$(R)"
|
||||||
|
cd $(CORE_DIR) && rm -rf .ruff_cache __pycache__ .pytest_cache
|
||||||
|
find $(CORE_DIR) -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
|
||||||
|
find $(CORE_DIR) -type d -name ".pytest_cache" -exec rm -rf {} + 2>/dev/null || true
|
||||||
|
find $(CORE_DIR) -type f -name "*.pyc" -delete 2>/dev/null || true
|
||||||
|
@echo "✅ Caches cleaned."
|
||||||
|
|
||||||
|
coverage: check-runner
|
||||||
|
@echo "$(T)📊 Running tests with coverage...$(R)"
|
||||||
|
$(RUNNER_RUN) pytest --cov=. --cov-report=html --cov-report=term $(ARGS)
|
||||||
|
@echo "✅ Report generated in htmlcov/"
|
||||||
|
|
||||||
|
down: check-docker
|
||||||
|
@echo "$(T)🛑 Stopping containers...$(R)"
|
||||||
|
$(COMPOSE_CMD) down
|
||||||
|
@echo "✅ System stopped."
|
||||||
|
|
||||||
|
format: check-runner
|
||||||
|
@echo "$(T)✨ Formatting with Ruff...$(R)"
|
||||||
|
$(RUNNER_RUN) ruff format .
|
||||||
|
$(RUNNER_RUN) ruff check --fix .
|
||||||
|
@echo "✅ Code cleaned."
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "$(B)Available commands:$(R)"
|
||||||
|
@echo ""
|
||||||
|
@echo "$(G)Setup:$(R)"
|
||||||
|
@echo " $(T)check-docker $(R) Verify Docker is installed and running."
|
||||||
|
@echo " $(T)check-runner $(R) Verify package manager ($(RUNNER))."
|
||||||
|
@echo " $(T)init-dotenv $(R) Create .env from .env.example with generated secrets."
|
||||||
|
@echo " $(T)install $(R) Install ALL dependencies (Prod + Dev)."
|
||||||
|
@echo " $(T)install-hooks $(R) Install git pre-commit hooks."
|
||||||
|
@echo ""
|
||||||
|
@echo "$(G)Docker:$(R)"
|
||||||
|
@echo " $(T)build $(R) Build the docker image (production)."
|
||||||
|
@echo " $(T)build-test $(R) Build the docker image (with dev deps for testing)."
|
||||||
|
@echo " $(T)down $(R) Stop and remove containers."
|
||||||
|
@echo " $(T)logs $(R) Follow logs."
|
||||||
|
@echo " $(T)prune $(R) Clean Docker system."
|
||||||
|
@echo " $(T)ps $(R) Show container status."
|
||||||
|
@echo " $(T)restart $(R) Restart all containers."
|
||||||
|
@echo " $(T)shell $(R) Open shell in container."
|
||||||
|
@echo " $(T)up $(R) Start the agent."
|
||||||
|
@echo ""
|
||||||
|
@echo "$(G)Development:$(R)"
|
||||||
|
@echo " $(T)add ... $(R) Add dependency (use --group dev or --dev if needed)."
|
||||||
|
@echo " $(T)clean $(R) Clean caches."
|
||||||
|
@echo " $(T)coverage $(R) Run tests with coverage."
|
||||||
|
@echo " $(T)format $(R) Format code (Ruff)."
|
||||||
|
@echo " $(T)lint $(R) Lint code without fixing."
|
||||||
|
@echo " $(T)test ... $(R) Run tests (local with $(RUNNER))."
|
||||||
|
@echo " $(T)update $(R) Update dependencies."
|
||||||
|
@echo ""
|
||||||
|
@echo "$(G)Versioning:$(R)"
|
||||||
|
@echo " $(T)major/minor/patch $(R) Bump version and push tag (triggers CI/CD)."
|
||||||
|
|
||||||
|
init-dotenv:
|
||||||
|
@echo "$(T)🔑 Initializing .env file...$(R)"
|
||||||
|
@if [ -f .env ]; then \
|
||||||
|
echo "$(R)⚠️ .env already exists. Skipping.$(R)"; \
|
||||||
|
exit 0; \
|
||||||
|
fi
|
||||||
|
@if [ ! -f .env.example ]; then \
|
||||||
|
echo "$(R)❌ .env.example not found$(R)"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
@if ! command -v openssl >/dev/null 2>&1; then \
|
||||||
|
echo "$(R)❌ openssl not found. Please install it first.$(R)"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
@echo "$(T) → Copying .env.example...$(R)"
|
||||||
|
@cp .env.example .env
|
||||||
|
@echo "$(T) → Generating secrets...$(R)"
|
||||||
|
@sed -i.bak "s|JWT_SECRET=.*|JWT_SECRET=$$(openssl rand -base64 32)|" .env
|
||||||
|
@sed -i.bak "s|JWT_REFRESH_SECRET=.*|JWT_REFRESH_SECRET=$$(openssl rand -base64 32)|" .env
|
||||||
|
@sed -i.bak "s|CREDS_KEY=.*|CREDS_KEY=$$(openssl rand -hex 16)|" .env
|
||||||
|
@sed -i.bak "s|CREDS_IV=.*|CREDS_IV=$$(openssl rand -hex 8)|" .env
|
||||||
|
@sed -i.bak "s|MEILI_MASTER_KEY=.*|MEILI_MASTER_KEY=$$(openssl rand -base64 32)|" .env
|
||||||
|
@sed -i.bak "s|AGENT_BRAIN_API_KEY=.*|AGENT_BRAIN_API_KEY=$$(openssl rand -base64 24)|" .env
|
||||||
|
@rm -f .env.bak
|
||||||
|
@echo "$(G)✅ .env created with generated secrets!$(R)"
|
||||||
|
@echo "$(T)⚠️ Don't forget to add your API keys:$(R)"
|
||||||
|
@echo " - OPENAI_API_KEY"
|
||||||
|
@echo " - DEEPSEEK_API_KEY"
|
||||||
|
@echo " - TMDB_API_KEY (optional)"
|
||||||
|
|
||||||
|
install: check-runner
|
||||||
|
@echo "$(T)📦 Installing FULL environment ($(RUNNER))...$(R)"
|
||||||
|
$(RUNNER_INSTALL)
|
||||||
|
@echo "✅ Environment ready (Prod + Dev)."
|
||||||
|
|
||||||
|
install-hooks: check-runner
|
||||||
|
@echo "$(T)🔧 Installing hooks...$(R)"
|
||||||
|
$(RUNNER_HOOKS)
|
||||||
|
@echo "✅ Hooks ready."
|
||||||
|
|
||||||
|
lint: check-runner
|
||||||
|
@echo "$(T)🔍 Linting code...$(R)"
|
||||||
|
$(RUNNER_RUN) ruff check .
|
||||||
|
|
||||||
|
logs: check-docker
|
||||||
|
@echo "$(T)📋 Following logs...$(R)"
|
||||||
|
$(COMPOSE_CMD) logs -f
|
||||||
|
|
||||||
|
major: _check_branch
|
||||||
|
@echo "$(T)💥 Bumping major...$(R)"
|
||||||
|
SKIP=all $(BUMP_CMD) major
|
||||||
|
@$(MAKE) -s _push_tag
|
||||||
|
|
||||||
|
minor: _check_branch
|
||||||
|
@echo "$(T)✨ Bumping minor...$(R)"
|
||||||
|
SKIP=all $(BUMP_CMD) minor
|
||||||
|
@$(MAKE) -s _push_tag
|
||||||
|
|
||||||
|
patch: _check_branch
|
||||||
|
@echo "$(T)🚀 Bumping patch...$(R)"
|
||||||
|
SKIP=all $(BUMP_CMD) patch
|
||||||
|
@$(MAKE) -s _push_tag
|
||||||
|
|
||||||
|
prune: check-docker
|
||||||
|
@echo "$(T)🗑️ Pruning Docker resources...$(R)"
|
||||||
|
docker system prune -af
|
||||||
|
@echo "✅ Docker cleaned."
|
||||||
|
|
||||||
|
ps: check-docker
|
||||||
|
@echo "$(T)📋 Container status:$(R)"
|
||||||
|
@$(COMPOSE_CMD) ps
|
||||||
|
|
||||||
|
python-version:
|
||||||
|
@echo "🔍 Reading pyproject.toml..."
|
||||||
|
@echo "✅ Python version : $(PYTHON_VERSION)"
|
||||||
|
@echo "ℹ️ Sera utilisé pour : FROM python:$(PYTHON_VERSION)-slim"
|
||||||
|
|
||||||
|
|
||||||
|
restart: check-docker
|
||||||
|
@echo "$(T)🔄 Restarting containers...$(R)"
|
||||||
|
$(COMPOSE_CMD) restart
|
||||||
|
@echo "✅ Containers restarted."
|
||||||
|
|
||||||
|
run: check-runner
|
||||||
|
$(RUNNER_RUN) $(ARGS)
|
||||||
|
|
||||||
|
shell: check-docker
|
||||||
|
@echo "$(T)🐚 Opening shell in $(SERVICE_NAME)...$(R)"
|
||||||
|
$(COMPOSE_CMD) exec $(SERVICE_NAME) /bin/sh
|
||||||
|
|
||||||
|
test: check-runner
|
||||||
|
@echo "$(T)🧪 Running tests...$(R)"
|
||||||
|
$(RUNNER_RUN) pytest $(ARGS)
|
||||||
|
|
||||||
|
up: check-docker
|
||||||
|
@echo "$(T)🚀 Starting Agent Media...$(R)"
|
||||||
|
$(COMPOSE_CMD) up -d
|
||||||
|
@echo "✅ System is up."
|
||||||
|
|
||||||
|
update: check-runner
|
||||||
|
@echo "$(T)🔄 Updating dependencies...$(R)"
|
||||||
|
$(RUNNER_UPDATE)
|
||||||
|
@echo "✅ All packages up to date."
|
||||||
|
|
||||||
|
_check_branch:
|
||||||
|
@curr=$$(git rev-parse --abbrev-ref HEAD); \
|
||||||
|
if [ "$$curr" != "main" ]; then \
|
||||||
|
echo "❌ Error: not on the main branch"; exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
BUMP = cd brain && poetry run bump-my-version bump
|
_ci-dump-config:
|
||||||
|
@echo "image_name=$(IMAGE_NAME)"
|
||||||
|
@echo "python_version=$(PYTHON_VERSION)"
|
||||||
|
@echo "python_version_short=$(PYTHON_VERSION_SHORT)"
|
||||||
|
@echo "runner=$(RUNNER)"
|
||||||
|
@echo "service_name=$(SERVICE_NAME)"
|
||||||
|
|
||||||
.PHONY: help patch minor major
|
_ci-run-tests: build-test
|
||||||
help:
|
@echo "$(T)🧪 Running tests in Docker...$(R)"
|
||||||
@echo "Versioning commands :"
|
docker run --rm \
|
||||||
@echo " make patch : Bump version 0.0.1 (bugfix)"
|
-e DEEPSEEK_API_KEY \
|
||||||
@echo " make minor : Bump version 0.1.0 (feature)"
|
-e TMDB_API_KEY \
|
||||||
@echo " make major : Bump version 1.0.0 (breaking change)"
|
$(IMAGE_NAME):test pytest
|
||||||
|
@echo "✅ Tests passed."
|
||||||
|
|
||||||
patch: check-branch-is-main
|
_push_tag:
|
||||||
SKIP=all $(BUMP) patch
|
@echo "$(T)📦 Pushing tag...$(R)"
|
||||||
|
git push --tags
|
||||||
minor: check-branch-is-main
|
@echo "✅ Tag pushed. Check CI for build status."
|
||||||
SKIP=all $(BUMP) minor
|
|
||||||
|
|
||||||
major: check-branch-is-main
|
|
||||||
SKIP=all $(BUMP) major
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[tool.bumpversion]
|
[tool.bumpversion]
|
||||||
current_version = "0.1.1"
|
current_version = "0.1.6"
|
||||||
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
||||||
serialize = ["{major}.{minor}.{patch}"]
|
serialize = ["{major}.{minor}.{patch}"]
|
||||||
search = "{current_version}"
|
search = "{current_version}"
|
||||||
|
|||||||
+70
-38
@@ -1,47 +1,86 @@
|
|||||||
# Dockerfile for Agent Media
|
# syntax=docker/dockerfile:1
|
||||||
# Multi-stage build for smaller image size
|
# check=skip=InvalidDefaultArgInFrom
|
||||||
|
|
||||||
|
ARG PYTHON_VERSION
|
||||||
|
ARG PYTHON_VERSION_SHORT
|
||||||
|
ARG RUNNER
|
||||||
# ===========================================
|
# ===========================================
|
||||||
# Stage 1: Builder
|
# Stage 1: Builder
|
||||||
# ===========================================
|
# ===========================================
|
||||||
FROM python:3.12.7-slim as builder
|
FROM python:${PYTHON_VERSION}-slim-bookworm AS builder
|
||||||
|
|
||||||
# STFU (please)
|
# Re-declare ARGs after FROM to make them available in this stage
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ARG RUNNER
|
||||||
|
|
||||||
|
# STFU - No need - Write logs asap
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive \
|
||||||
|
PYTHONDONTWRITEBYTECODE=1 \
|
||||||
|
PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
# Install build dependencies (needs root)
|
# Install build dependencies (needs root)
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
build-essential \
|
build-essential \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Install Poetry globally (needs root)
|
# Install runner globally (needs root) - Save cache for future
|
||||||
RUN pip install --no-cache-dir poetry
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
|
pip install $RUNNER
|
||||||
|
|
||||||
# Copy dependency files (as root for now)
|
# Set working directory for dependency installation
|
||||||
COPY pyproject.toml poetry.lock* /tmp/
|
WORKDIR /tmp
|
||||||
|
|
||||||
|
# Copy dependency files
|
||||||
|
COPY brain/pyproject.toml brain/poetry.lock* brain/uv.lock* Makefile ./
|
||||||
|
|
||||||
# Install dependencies as root (to avoid permission issues with system packages)
|
# Install dependencies as root (to avoid permission issues with system packages)
|
||||||
WORKDIR /tmp
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
RUN poetry config virtualenvs.create false \
|
--mount=type=cache,target=/root/.cache/pypoetry \
|
||||||
&& poetry install --only main --no-root --no-cache
|
--mount=type=cache,target=/root/.cache/uv \
|
||||||
|
if [ "$RUNNER" = "poetry" ]; then \
|
||||||
# Create non-root user
|
poetry config virtualenvs.create false && \
|
||||||
RUN useradd -m -u 1000 -s /bin/bash appuser
|
poetry install --only main --no-root; \
|
||||||
|
elif [ "$RUNNER" = "uv" ]; then \
|
||||||
# Switch to non-root user
|
uv pip install --system -r pyproject.toml; \
|
||||||
USER appuser
|
fi
|
||||||
|
|
||||||
# Set working directory (owned by appuser)
|
|
||||||
WORKDIR /home/appuser/app
|
|
||||||
|
|
||||||
# ===========================================
|
# ===========================================
|
||||||
# Stage 2: Runtime
|
# Stage 2: Testing
|
||||||
# ===========================================
|
# ===========================================
|
||||||
FROM python:3.12.7-slim as runtime
|
FROM builder AS test
|
||||||
|
|
||||||
|
ARG RUNNER
|
||||||
|
|
||||||
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
|
--mount=type=cache,target=/root/.cache/pypoetry \
|
||||||
|
--mount=type=cache,target=/root/.cache/uv \
|
||||||
|
if [ "$RUNNER" = "poetry" ]; then \
|
||||||
|
poetry install --no-root; \
|
||||||
|
elif [ "$RUNNER" = "uv" ]; then \
|
||||||
|
uv pip install --system -e .[dev]; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
COPY brain/agent/ ./agent/
|
||||||
|
COPY brain/application/ ./application/
|
||||||
|
COPY brain/domain/ ./domain/
|
||||||
|
COPY brain/infrastructure/ ./infrastructure/
|
||||||
|
COPY brain/tests/ ./tests/
|
||||||
|
COPY brain/app.py .
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# Stage 3: Runtime
|
||||||
|
# ===========================================
|
||||||
|
FROM python:${PYTHON_VERSION}-slim-bookworm AS runtime
|
||||||
|
|
||||||
|
ARG PYTHON_VERSION_SHORT
|
||||||
|
|
||||||
|
ENV LLM_PROVIDER=deepseek \
|
||||||
|
MEMORY_STORAGE_DIR=/data/memory \
|
||||||
|
PYTHONDONTWRITEBYTECODE=1 \
|
||||||
|
PYTHONPATH=/home/appuser/app \
|
||||||
|
PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
# Install runtime dependencies (needs root)
|
# Install runtime dependencies (needs root)
|
||||||
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 \
|
ca-certificates \
|
||||||
&& rm -rf /var/lib/apt/lists/* \
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
&& apt-get clean
|
&& apt-get clean
|
||||||
@@ -60,15 +99,15 @@ USER appuser
|
|||||||
WORKDIR /home/appuser/app
|
WORKDIR /home/appuser/app
|
||||||
|
|
||||||
# Copy Python packages from builder stage
|
# Copy Python packages from builder stage
|
||||||
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
|
COPY --from=builder /usr/local/lib/python${PYTHON_VERSION_SHORT}/site-packages /usr/local/lib/python${PYTHON_VERSION_SHORT}/site-packages
|
||||||
COPY --from=builder /usr/local/bin /usr/local/bin
|
COPY --from=builder /usr/local/bin /usr/local/bin
|
||||||
|
|
||||||
# Copy application code (already owned by appuser)
|
# Copy application code (already owned by appuser)
|
||||||
COPY --chown=appuser:appuser agent/ ./agent/
|
COPY --chown=appuser:appuser brain/agent/ ./agent/
|
||||||
COPY --chown=appuser:appuser application/ ./application/
|
COPY --chown=appuser:appuser brain/application/ ./application/
|
||||||
COPY --chown=appuser:appuser domain/ ./domain/
|
COPY --chown=appuser:appuser brain/domain/ ./domain/
|
||||||
COPY --chown=appuser:appuser infrastructure/ ./infrastructure/
|
COPY --chown=appuser:appuser brain/infrastructure/ ./infrastructure/
|
||||||
COPY --chown=appuser:appuser app.py .
|
COPY --chown=appuser:appuser brain/app.py .
|
||||||
|
|
||||||
# Create volumes for persistent data
|
# Create volumes for persistent data
|
||||||
VOLUME ["/data/memory", "/data/logs"]
|
VOLUME ["/data/memory", "/data/logs"]
|
||||||
@@ -78,14 +117,7 @@ EXPOSE 8000
|
|||||||
|
|
||||||
# Health check
|
# Health check
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||||
CMD curl -f http://localhost:8000/health || exit 1
|
CMD python -c "import requests; requests.get('http://localhost:8000/health', timeout=5).raise_for_status()" || exit 1
|
||||||
|
|
||||||
# Environment variables (can be overridden)
|
|
||||||
ENV PYTHONUNBUFFERED=1 \
|
|
||||||
PYTHONDONTWRITEBYTECODE=1 \
|
|
||||||
PYTHONPATH=/home/appuser/app \
|
|
||||||
LLM_PROVIDER=deepseek \
|
|
||||||
MEMORY_STORAGE_DIR=/data/memory
|
|
||||||
|
|
||||||
# Run the application
|
# Run the application
|
||||||
CMD ["python", "-m", "uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
|
CMD ["python", "-m", "uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||||
|
|||||||
Generated
+39
-41
@@ -35,7 +35,6 @@ files = [
|
|||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
idna = ">=2.8"
|
idna = ">=2.8"
|
||||||
typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""}
|
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
trio = ["trio (>=0.31.0)", "trio (>=0.32.0)"]
|
trio = ["trio (>=0.31.0)", "trio (>=0.32.0)"]
|
||||||
@@ -373,25 +372,25 @@ testing = ["hatch", "pre-commit", "pytest", "tox"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastapi"
|
name = "fastapi"
|
||||||
version = "0.121.3"
|
version = "0.127.0"
|
||||||
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
|
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.9"
|
||||||
files = [
|
files = [
|
||||||
{file = "fastapi-0.121.3-py3-none-any.whl", hash = "sha256:0c78fc87587fcd910ca1bbf5bc8ba37b80e119b388a7206b39f0ecc95ebf53e9"},
|
{file = "fastapi-0.127.0-py3-none-any.whl", hash = "sha256:725aa2bb904e2eff8031557cf4b9b77459bfedd63cae8427634744fd199f6a49"},
|
||||||
{file = "fastapi-0.121.3.tar.gz", hash = "sha256:0055bc24fe53e56a40e9e0ad1ae2baa81622c406e548e501e717634e2dfbc40b"},
|
{file = "fastapi-0.127.0.tar.gz", hash = "sha256:5a9246e03dcd1fdb19f1396db30894867c1d630f5107dc167dcbc5ed1ea7d259"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
annotated-doc = ">=0.0.2"
|
annotated-doc = ">=0.0.2"
|
||||||
pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
|
pydantic = ">=2.7.0"
|
||||||
starlette = ">=0.40.0,<0.51.0"
|
starlette = ">=0.40.0,<0.51.0"
|
||||||
typing-extensions = ">=4.8.0"
|
typing-extensions = ">=4.8.0"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=3.1.5)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
|
all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=3.1.5)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
|
||||||
standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "jinja2 (>=3.1.5)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"]
|
standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "jinja2 (>=3.1.5)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"]
|
||||||
standard-no-fastapi-cloud-cli = ["email-validator (>=2.0.0)", "fastapi-cli[standard-no-fastapi-cloud-cli] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "jinja2 (>=3.1.5)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"]
|
standard-no-fastapi-cloud-cli = ["email-validator (>=2.0.0)", "fastapi-cli[standard-no-fastapi-cloud-cli] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "jinja2 (>=3.1.5)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "filelock"
|
name = "filelock"
|
||||||
@@ -535,13 +534,13 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nodeenv"
|
name = "nodeenv"
|
||||||
version = "1.9.1"
|
version = "1.10.0"
|
||||||
description = "Node.js virtual environment builder"
|
description = "Node.js virtual environment builder"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"},
|
{file = "nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827"},
|
||||||
{file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"},
|
{file = "nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1037,13 +1036,13 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rich-click"
|
name = "rich-click"
|
||||||
version = "1.9.4"
|
version = "1.9.5"
|
||||||
description = "Format click help output nicely with rich"
|
description = "Format click help output nicely with rich"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "rich_click-1.9.4-py3-none-any.whl", hash = "sha256:d70f39938bcecaf5543e8750828cbea94ef51853f7d0e174cda1e10543767389"},
|
{file = "rich_click-1.9.5-py3-none-any.whl", hash = "sha256:9b195721a773b1acf0e16ff9ec68cef1e7d237e53471e6e3f7ade462f86c403a"},
|
||||||
{file = "rich_click-1.9.4.tar.gz", hash = "sha256:af73dc68e85f3bebb80ce302a642b9fe3b65f3df0ceb42eb9a27c467c1b678c8"},
|
{file = "rich_click-1.9.5.tar.gz", hash = "sha256:48120531493f1533828da80e13e839d471979ec8d7d0ca7b35f86a1379cc74b6"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@@ -1057,30 +1056,30 @@ docs = ["markdown-include (>=0.8.1)", "mike (>=2.1.3)", "mkdocs-github-admonitio
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruff"
|
name = "ruff"
|
||||||
version = "0.14.9"
|
version = "0.14.10"
|
||||||
description = "An extremely fast Python linter and code formatter, written in Rust."
|
description = "An extremely fast Python linter and code formatter, written in Rust."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "ruff-0.14.9-py3-none-linux_armv6l.whl", hash = "sha256:f1ec5de1ce150ca6e43691f4a9ef5c04574ad9ca35c8b3b0e18877314aba7e75"},
|
{file = "ruff-0.14.10-py3-none-linux_armv6l.whl", hash = "sha256:7a3ce585f2ade3e1f29ec1b92df13e3da262178df8c8bdf876f48fa0e8316c49"},
|
||||||
{file = "ruff-0.14.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ed9d7417a299fc6030b4f26333bf1117ed82a61ea91238558c0268c14e00d0c2"},
|
{file = "ruff-0.14.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:674f9be9372907f7257c51f1d4fc902cb7cf014b9980152b802794317941f08f"},
|
||||||
{file = "ruff-0.14.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d5dc3473c3f0e4a1008d0ef1d75cee24a48e254c8bed3a7afdd2b4392657ed2c"},
|
{file = "ruff-0.14.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d85713d522348837ef9df8efca33ccb8bd6fcfc86a2cde3ccb4bc9d28a18003d"},
|
||||||
{file = "ruff-0.14.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84bf7c698fc8f3cb8278830fb6b5a47f9bcc1ed8cb4f689b9dd02698fa840697"},
|
{file = "ruff-0.14.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6987ebe0501ae4f4308d7d24e2d0fe3d7a98430f5adfd0f1fead050a740a3a77"},
|
||||||
{file = "ruff-0.14.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aa733093d1f9d88a5d98988d8834ef5d6f9828d03743bf5e338bf980a19fce27"},
|
{file = "ruff-0.14.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:16a01dfb7b9e4eee556fbfd5392806b1b8550c9b4a9f6acd3dbe6812b193c70a"},
|
||||||
{file = "ruff-0.14.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a1cfb04eda979b20c8c19550c8b5f498df64ff8da151283311ce3199e8b3648"},
|
{file = "ruff-0.14.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7165d31a925b7a294465fa81be8c12a0e9b60fb02bf177e79067c867e71f8b1f"},
|
||||||
{file = "ruff-0.14.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1e5cb521e5ccf0008bd74d5595a4580313844a42b9103b7388eca5a12c970743"},
|
{file = "ruff-0.14.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:c561695675b972effb0c0a45db233f2c816ff3da8dcfbe7dfc7eed625f218935"},
|
||||||
{file = "ruff-0.14.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd429a8926be6bba4befa8cdcf3f4dd2591c413ea5066b1e99155ed245ae42bb"},
|
{file = "ruff-0.14.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4bb98fcbbc61725968893682fd4df8966a34611239c9fd07a1f6a07e7103d08e"},
|
||||||
{file = "ruff-0.14.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab208c1b7a492e37caeaf290b1378148f75e13c2225af5d44628b95fd7834273"},
|
{file = "ruff-0.14.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f24b47993a9d8cb858429e97bdf8544c78029f09b520af615c1d261bf827001d"},
|
||||||
{file = "ruff-0.14.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72034534e5b11e8a593f517b2f2f2b273eb68a30978c6a2d40473ad0aaa4cb4a"},
|
{file = "ruff-0.14.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59aabd2e2c4fd614d2862e7939c34a532c04f1084476d6833dddef4afab87e9f"},
|
||||||
{file = "ruff-0.14.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:712ff04f44663f1b90a1195f51525836e3413c8a773574a7b7775554269c30ed"},
|
{file = "ruff-0.14.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:213db2b2e44be8625002dbea33bb9c60c66ea2c07c084a00d55732689d697a7f"},
|
||||||
{file = "ruff-0.14.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a111fee1db6f1d5d5810245295527cda1d367c5aa8f42e0fca9a78ede9b4498b"},
|
{file = "ruff-0.14.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b914c40ab64865a17a9a5b67911d14df72346a634527240039eb3bd650e5979d"},
|
||||||
{file = "ruff-0.14.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8769efc71558fecc25eb295ddec7d1030d41a51e9dcf127cbd63ec517f22d567"},
|
{file = "ruff-0.14.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1484983559f026788e3a5c07c81ef7d1e97c1c78ed03041a18f75df104c45405"},
|
||||||
{file = "ruff-0.14.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:347e3bf16197e8a2de17940cd75fd6491e25c0aa7edf7d61aa03f146a1aa885a"},
|
{file = "ruff-0.14.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c70427132db492d25f982fffc8d6c7535cc2fd2c83fc8888f05caaa248521e60"},
|
||||||
{file = "ruff-0.14.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7715d14e5bccf5b660f54516558aa94781d3eb0838f8e706fb60e3ff6eff03a8"},
|
{file = "ruff-0.14.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5bcf45b681e9f1ee6445d317ce1fa9d6cba9a6049542d1c3d5b5958986be8830"},
|
||||||
{file = "ruff-0.14.9-py3-none-win32.whl", hash = "sha256:df0937f30aaabe83da172adaf8937003ff28172f59ca9f17883b4213783df197"},
|
{file = "ruff-0.14.10-py3-none-win32.whl", hash = "sha256:104c49fc7ab73f3f3a758039adea978869a918f31b73280db175b43a2d9b51d6"},
|
||||||
{file = "ruff-0.14.9-py3-none-win_amd64.whl", hash = "sha256:c0b53a10e61df15a42ed711ec0bda0c582039cf6c754c49c020084c55b5b0bc2"},
|
{file = "ruff-0.14.10-py3-none-win_amd64.whl", hash = "sha256:466297bd73638c6bdf06485683e812db1c00c7ac96d4ddd0294a338c62fdc154"},
|
||||||
{file = "ruff-0.14.9-py3-none-win_arm64.whl", hash = "sha256:8e821c366517a074046d92f0e9213ed1c13dbc5b37a7fc20b07f79b64d62cc84"},
|
{file = "ruff-0.14.10-py3-none-win_arm64.whl", hash = "sha256:e51d046cf6dda98a4633b8a8a771451107413b0f07183b2bef03f075599e44e6"},
|
||||||
{file = "ruff-0.14.9.tar.gz", hash = "sha256:35f85b25dd586381c0cc053f48826109384c81c00ad7ef1bd977bfcc28119d5b"},
|
{file = "ruff-0.14.10.tar.gz", hash = "sha256:9a2e830f075d1a42cd28420d7809ace390832a490ed0966fe373ba288e77aaf4"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1096,7 +1095,6 @@ files = [
|
|||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
anyio = ">=3.6.2,<5"
|
anyio = ">=3.6.2,<5"
|
||||||
typing-extensions = {version = ">=4.10.0", markers = "python_version < \"3.13\""}
|
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.18)", "pyyaml"]
|
full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.18)", "pyyaml"]
|
||||||
@@ -1156,13 +1154,13 @@ zstd = ["backports-zstd (>=1.0.0)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uvicorn"
|
name = "uvicorn"
|
||||||
version = "0.38.0"
|
version = "0.40.0"
|
||||||
description = "The lightning-fast ASGI server."
|
description = "The lightning-fast ASGI server."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.10"
|
||||||
files = [
|
files = [
|
||||||
{file = "uvicorn-0.38.0-py3-none-any.whl", hash = "sha256:48c0afd214ceb59340075b4a052ea1ee91c16fbc2a9b1469cca0e54566977b02"},
|
{file = "uvicorn-0.40.0-py3-none-any.whl", hash = "sha256:c6c8f55bc8bf13eb6fa9ff87ad62308bbbc33d0b67f84293151efe87e0d5f2ee"},
|
||||||
{file = "uvicorn-0.38.0.tar.gz", hash = "sha256:fd97093bdd120a2609fc0d3afe931d4d4ad688b6e75f0f929fde1bc36fe0e91d"},
|
{file = "uvicorn-0.40.0.tar.gz", hash = "sha256:839676675e87e73694518b5574fd0f24c9d97b46bea16df7b8c05ea1a51071ea"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@@ -1219,5 +1217,5 @@ files = [
|
|||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.12"
|
python-versions = "==3.14.2"
|
||||||
content-hash = "6204ac4c938e73f59f5bffef08e8e3cdbbc5c307a693578b1183d6140d4e8f31"
|
content-hash = "7046b2edca4660e38f5f14ef0282854a4bb7892af5028c4af9e968f2c65590c5"
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "agent-media"
|
name = "agent-media"
|
||||||
version = "0.1.1"
|
version = "0.1.6"
|
||||||
description = "AI agent for managing a local media library"
|
description = "AI agent for managing a local media library"
|
||||||
authors = ["Francwa <francois.hodiaumont@gmail.com>"]
|
authors = ["Francwa <francois.hodiaumont@gmail.com>"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
package-mode = false
|
package-mode = false
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.12"
|
python = "==3.14.2"
|
||||||
python-dotenv = "^1.0.0"
|
python-dotenv = "^1.0.0"
|
||||||
requests = "^2.32.5"
|
requests = "^2.32.5"
|
||||||
fastapi = "^0.121.1"
|
fastapi = "^0.127.0"
|
||||||
pydantic = "^2.12.4"
|
pydantic = "^2.12.4"
|
||||||
uvicorn = "^0.38.0"
|
uvicorn = "^0.40.0"
|
||||||
pytest-xdist = "^3.8.0"
|
pytest-xdist = "^3.8.0"
|
||||||
httpx = "^0.28.1"
|
httpx = "^0.28.1"
|
||||||
|
|
||||||
@@ -47,6 +47,7 @@ addopts = [
|
|||||||
#"--cov-report=xml", # Génère un rapport XML (pour CI/CD)
|
#"--cov-report=xml", # Génère un rapport XML (pour CI/CD)
|
||||||
#"--cov-fail-under=80", # Échoue si coverage < 80%
|
#"--cov-fail-under=80", # Échoue si coverage < 80%
|
||||||
"-n=auto", # --numprocesses=auto : parallélise les tests (pytest-xdist)
|
"-n=auto", # --numprocesses=auto : parallélise les tests (pytest-xdist)
|
||||||
|
"--dist=loadscope", # Distribution strategy: group tests by module
|
||||||
"--strict-markers", # Erreur si un marker non déclaré est utilisé
|
"--strict-markers", # Erreur si un marker non déclaré est utilisé
|
||||||
"--disable-warnings", # Désactive l'affichage des warnings (sauf erreurs)
|
"--disable-warnings", # Désactive l'affichage des warnings (sauf erreurs)
|
||||||
]
|
]
|
||||||
|
|||||||
+9
-6
@@ -6,6 +6,8 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: ./brain
|
context: ./brain
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
|
args:
|
||||||
|
RUNNER: ${RUNNER} # Get it from Makefile
|
||||||
container_name: agent-brain
|
container_name: agent-brain
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
env_file: .env
|
env_file: .env
|
||||||
@@ -49,21 +51,21 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
# MongoDB connection (no auth, matching LibreChat default)
|
# MongoDB connection (no auth, matching LibreChat default)
|
||||||
MONGO_URI: mongodb://mongodb:27017/LibreChat
|
MONGO_URI: mongodb://mongodb:27017/LibreChat
|
||||||
|
|
||||||
# App configuration
|
# App configuration
|
||||||
HOST: 0.0.0.0
|
HOST: 0.0.0.0
|
||||||
PORT: 3080
|
PORT: 3080
|
||||||
|
|
||||||
# Security
|
# Security
|
||||||
JWT_SECRET: ${JWT_SECRET:-your-super-secret-jwt-key-change-this-in-production}
|
JWT_SECRET: ${JWT_SECRET:-your-super-secret-jwt-key-change-this-in-production}
|
||||||
JWT_REFRESH_SECRET: ${JWT_REFRESH_SECRET:-your-super-secret-refresh-key-change-this-too}
|
JWT_REFRESH_SECRET: ${JWT_REFRESH_SECRET:-your-super-secret-refresh-key-change-this-too}
|
||||||
CREDS_KEY: ${CREDS_KEY:-your-32-character-secret-key-here}
|
CREDS_KEY: ${CREDS_KEY:-your-32-character-secret-key-here}
|
||||||
CREDS_IV: ${CREDS_IV:-your-16-character-iv-here}
|
CREDS_IV: ${CREDS_IV:-your-16-character-iv-here}
|
||||||
|
|
||||||
# Session
|
# Session
|
||||||
SESSION_EXPIRY: ${SESSION_EXPIRY:-1000 * 60 * 15}
|
SESSION_EXPIRY: ${SESSION_EXPIRY:-1000 * 60 * 15}
|
||||||
REFRESH_TOKEN_EXPIRY: ${REFRESH_TOKEN_EXPIRY:-1000 * 60 * 60 * 24 * 7}
|
REFRESH_TOKEN_EXPIRY: ${REFRESH_TOKEN_EXPIRY:-1000 * 60 * 60 * 24 * 7}
|
||||||
|
|
||||||
# Domain
|
# Domain
|
||||||
DOMAIN_CLIENT: ${DOMAIN_CLIENT:-http://localhost:3080}
|
DOMAIN_CLIENT: ${DOMAIN_CLIENT:-http://localhost:3080}
|
||||||
DOMAIN_SERVER: ${DOMAIN_SERVER:-http://localhost:3080}
|
DOMAIN_SERVER: ${DOMAIN_SERVER:-http://localhost:3080}
|
||||||
@@ -105,8 +107,9 @@ services:
|
|||||||
- agent-network
|
- agent-network
|
||||||
|
|
||||||
# Meilisearch - Search engine for LibreChat
|
# Meilisearch - Search engine for LibreChat
|
||||||
|
#TODO: Follow currently used version on librechat's github
|
||||||
meilisearch:
|
meilisearch:
|
||||||
image: getmeili/meilisearch:v1.11.3
|
image: getmeili/meilisearch:v1.12.3
|
||||||
container_name: librechat-meilisearch
|
container_name: librechat-meilisearch
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
@@ -201,4 +204,4 @@ volumes:
|
|||||||
# Network for inter-service communication
|
# Network for inter-service communication
|
||||||
networks:
|
networks:
|
||||||
agent-network:
|
agent-network:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
|
"extends": [
|
||||||
|
"config:base",
|
||||||
|
":disableRateLimiting",
|
||||||
|
":semanticCommits"
|
||||||
|
],
|
||||||
|
"labels": ["dependencies", "renovate"],
|
||||||
|
|
||||||
|
"packageRules": [
|
||||||
|
{
|
||||||
|
"matchLanguages": ["python"],
|
||||||
|
"matchUpdateTypes": ["patch"],
|
||||||
|
"automerge": true,
|
||||||
|
"groupName": "Python Security Patches"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matchPackageNames": ["python"],
|
||||||
|
"matchUpdateTypes": ["major", "minor"],
|
||||||
|
"dependencyDashboardApproval": true,
|
||||||
|
"groupName": "Python Update(s) (Manual Action Required)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matchPackageNames": ["getmeili/meilisearch"],
|
||||||
|
"enabled": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"regexManagers": [
|
||||||
|
{
|
||||||
|
"description": "Update Docker variables in the Makefile",
|
||||||
|
"fileMatch": ["^Makefile$"],
|
||||||
|
"matchStrings": [
|
||||||
|
"# renovate: datasource=(?<datasource>.*?) depName=(?<depName>.*?)( versioning=(?<versioning>.*?))?\\s[A-Z_]+_VERSION [?:]?= (?<currentValue>.*)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user