9b8d24b435
- 后端: 空镜匹配支持 exclude_urls 去重 - 后端: materials.json 关键词映射扩充 - Rust: compose_video 参数平铺化修复 IPC 调用 - Rust: concat_videos_copy 去除音频 - Rust: 上传接口 API 地址改为 8081 - Rust: clip_video 放宽输入路径校验 - 前端: VideoGeneration 人物素材本地选择 + 保存恢复 - 前端: 空镜自动匹配 + 串行去重 - 前端: 对口型任务提交 + 字段重命名 - 前端: 分镜卡片去除点击/选中/hover 交互 - 前端: 视频预览改为成品视频 - Makefile: Docker 命令适配共享基础设施
155 lines
4.8 KiB
Makefile
155 lines
4.8 KiB
Makefile
# 美家卡智影 API - 常用命令
|
||
# ==========================
|
||
|
||
.PHONY: help install dev install-hooks update-lock lint format test security clean docker
|
||
|
||
help: ## 显示帮助信息
|
||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
||
|
||
# ========== 依赖管理 ==========
|
||
|
||
install: ## 安装生产依赖(使用 lock 文件)
|
||
uv pip sync requirements.lock
|
||
|
||
dev: ## 安装开发依赖(包含 dev extras)
|
||
uv pip install -e ".[dev]"
|
||
pre-commit install
|
||
|
||
install-hooks: ## 安装 Git pre-commit 钩子
|
||
pre-commit install
|
||
|
||
update-lock: ## 更新 requirements.lock(修改 pyproject.toml 后执行)
|
||
uv pip compile pyproject.toml -o requirements.lock --upgrade
|
||
|
||
update-lock-no-upgrade: ## 重新生成 lock 文件(不升级版本)
|
||
uv pip compile pyproject.toml -o requirements.lock
|
||
|
||
# ========== 代码质量 ==========
|
||
|
||
lint: ## 运行代码检查 (ruff + mypy)
|
||
ruff check app/
|
||
mypy app/
|
||
|
||
format: ## 格式化代码 (black + ruff)
|
||
black app/
|
||
ruff check --fix app/
|
||
|
||
format-check: ## 检查代码格式(不修改)
|
||
black --check app/
|
||
ruff check app/
|
||
|
||
# ========== 测试 ==========
|
||
|
||
test: ## 运行测试
|
||
pytest -v
|
||
|
||
test-cov: ## 运行测试并生成覆盖率报告
|
||
pytest --cov=app --cov-report=html --cov-report=term
|
||
|
||
# ========== 安全扫描 ==========
|
||
|
||
security: ## 运行安全扫描 (bandit + pip-audit)
|
||
@echo "🔍 运行 Bandit 安全扫描..."
|
||
bandit -r app/ -c pyproject.toml
|
||
@echo "🔍 运行依赖漏洞扫描..."
|
||
pip-audit
|
||
|
||
# ========== 开发服务器 ==========
|
||
|
||
run: ## 启动开发服务器
|
||
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
|
||
|
||
scheduler: ## 启动 Async Engine Scheduler
|
||
python -m app.scheduler.main
|
||
|
||
# ========== Docker ==========
|
||
# ⚠️ 注意:db + redis 是共享基础设施(另一个项目管理),
|
||
# 当前项目只管理 api + scheduler,禁止用 docker-compose down。
|
||
|
||
docker: ## 构建 Docker 镜像
|
||
docker build -t meijiaka-api:latest .
|
||
|
||
docker-run: ## 启动 api + scheduler(共享 db/redis,不动基础设施)
|
||
docker-compose up -d
|
||
|
||
docker-rebuild: ## 强制重建 api + scheduler(代码更新后使用)
|
||
docker-compose up -d --build --force-recreate api scheduler
|
||
|
||
docker-stop: ## 只停止 api + scheduler(保留 db/redis)
|
||
docker-compose stop api scheduler
|
||
|
||
docker-rm: ## 删除 api + scheduler 容器(保留 db/redis)
|
||
docker-compose rm -f api scheduler
|
||
|
||
docker-logs: ## 查看 Docker 日志
|
||
docker-compose logs -f
|
||
|
||
docker-logs-api: ## 查看 api 日志
|
||
docker-compose logs -f api
|
||
|
||
docker-logs-scheduler: ## 查看 scheduler 日志
|
||
docker-compose logs -f scheduler
|
||
|
||
# ========== 清理 ==========
|
||
|
||
clean: ## 清理缓存文件
|
||
find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
|
||
find . -type f -name "*.pyc" -delete 2>/dev/null || true
|
||
find . -type d -name ".pytest_cache" -exec rm -rf {} + 2>/dev/null || true
|
||
find . -type d -name ".mypy_cache" -exec rm -rf {} + 2>/dev/null || true
|
||
rm -rf htmlcov/ .coverage 2>/dev/null || true
|
||
|
||
# ========== 语义层防护网 ==========
|
||
|
||
lint-semantic: ## 语义层禁词检查(防止供应商术语泄漏到业务层)
|
||
@echo "🔍 检查 Layer 3+ 是否泄漏供应商术语..."
|
||
@# API 层(除 klingai Provider 代理)禁止 element_id 作为字段/参数名
|
||
@errs=$$(grep -rn 'element_id' app/api --include='*.py' \
|
||
| grep -v 'klingai.py' \
|
||
| grep -v 'provider_element_id' \
|
||
| grep -v '__pycache__' \
|
||
| grep -v '#' \
|
||
| grep -v '".*element_id.*"' \
|
||
| grep -v "'.*element_id.*'"); \
|
||
if [ -n "$$errs" ]; then \
|
||
echo "$$errs"; \
|
||
echo "❌ API 层发现 element_id(应使用 provider_element_id 或 human_id)"; \
|
||
exit 1; \
|
||
fi
|
||
@# Scheduler 层禁止 task_id 作为内部变量/Redis key(读取 Provider 返回除外)
|
||
@errs=$$(grep -rn '\btask_id\b' app/scheduler --include='*.py' \
|
||
| grep -v 'job_id' \
|
||
| grep -v '__pycache__' \
|
||
| grep -v '\.get("task_id")' \
|
||
| grep -v 'result.get("task_id")' \
|
||
| grep -v 'task_type' \
|
||
| grep -v '"task_id"' \
|
||
| grep -v "'task_id'"); \
|
||
if [ -n "$$errs" ]; then \
|
||
echo "$$errs"; \
|
||
echo "❌ Scheduler 层发现 task_id(应使用 job_id)"; \
|
||
exit 1; \
|
||
fi
|
||
@# 全局禁止 kling_task_id 作为持久化字段
|
||
@errs=$$(grep -rn 'kling_task_id' app --include='*.py' \
|
||
| grep -v '__pycache__' \
|
||
| grep -v 'providers/klingai'); \
|
||
if [ -n "$$errs" ]; then \
|
||
echo "$$errs"; \
|
||
echo "❌ 发现 kling_task_id(应使用 provider_task_id)"; \
|
||
exit 1; \
|
||
fi
|
||
@# Scheduler 层 Redis key 必须使用 job: 而非 task:
|
||
@errs=$$(grep -rn 'redis.*task:' app/scheduler --include='*.py' \
|
||
| grep -v '__pycache__'); \
|
||
if [ -n "$$errs" ]; then \
|
||
echo "$$errs"; \
|
||
echo "❌ Scheduler Redis key 使用 task:(应使用 job:)"; \
|
||
exit 1; \
|
||
fi
|
||
@echo "✅ 语义层检查通过"
|
||
|
||
# ========== CI 检查 ==========
|
||
|
||
ci: format-check lint lint-semantic test security ## 运行所有 CI 检查
|