tliu93 8565534b73
pytest / test (push) Successful in 45s
docker-image / build-and-push (push) Successful in 3m40s
Merge pull request 'fix ci test' (#5) from feature/add_separate_migration_container into main
Reviewed-on: #5
2026-04-22 13:35:40 +02:00
2026-04-19 20:19:58 +02:00
2026-04-20 23:33:57 +02:00
2026-04-22 13:28:00 +02:00
2026-04-20 20:40:04 +02:00
2026-04-20 20:40:04 +02:00
2026-04-22 13:28:00 +02:00
2026-04-22 13:31:26 +02:00
2026-04-20 20:40:04 +02:00
2026-04-19 23:25:13 +02:00
2026-04-22 13:28:00 +02:00
2026-04-20 20:40:04 +02:00
2026-04-22 13:28:00 +02:00

Home Automation Backend

这是当前 home-automation 项目的首个 Python 版本。

当前系统已经包含:

  • FastAPI Web 应用与服务端模板页面
  • SQLite + SQLAlchemy + Alembic 的三库结构
  • username/password + server-side session 鉴权
  • runtime config 页面与 app DB 持久化
  • location recorder
  • poo recorder
  • Home Assistant inbound / outbound integration
  • TickTick OAuth 与 action task 集成
  • pytest 测试与 OpenAPI 导出脚本
  • Docker / Compose 部署入口

当前明确不包含:

  • Notion 模块

当前配置现实

当前系统仍然是三个独立的 SQLite 数据库文件,而不是单一数据库:

  • app 级共享数据使用自己的 DB 文件
  • location 模块使用自己的 DB 文件
  • poo 模块使用自己的 DB 文件

当前阶段明确不借这次重构把这些 DB 合并。配置层已经显式反映这一点:

  • APP_DATABASE_URL
  • LOCATION_DATABASE_URL
  • POO_DATABASE_URL

目前 auth、locationpoo 都已经接到各自独立的数据库文件。

其中 app 级共享 DB 当前主要用于:

  • 单个 admin 用户
  • server-side session
  • runtime config 持久化

这部分现在也使用 Alembic 管理:

  • app db 不会在应用启动时自动创建
  • 需要先运行 python scripts/app_db_adopt.py
  • 这个脚本会创建新 DB 并建好 schema

当前目录

主要目录如下:

  • app/: FastAPI 应用代码
  • alembic_app/: App DB 的 Alembic migration 环境
  • alembic_location/: Location DB 的 Alembic migration 环境
  • alembic_poo/: Poo DB 的 Alembic migration 环境
  • tests/: pytest 测试
  • docs/: 当前系统说明文档
  • scripts/: 辅助脚本,例如 OpenAPI 导出

依赖管理

项目现在采用 pip-tools 管理依赖:

  • 生产依赖源文件:requirements.in
  • 开发依赖源文件:dev-requirements.in
  • 编译产物:
    • requirements.txt
    • dev-requirements.txt

更新依赖时建议使用:

python -m venv .venv
source .venv/bin/activate
pip install pip-tools
pip-compile requirements.in
pip-compile dev-requirements.in

如果要升级某个依赖,可以用:

pip-compile --upgrade-package fastapi requirements.in
pip-compile dev-requirements.in

本地启动

建议使用 Python 3.11 或以上版本。

  1. 创建虚拟环境并安装依赖
python -m venv .venv
source .venv/bin/activate
pip install -r dev-requirements.txt
  1. 准备环境变量
cp .env.example .env
  1. 初始化数据库
python -m scripts.run_migrations
  1. 启动服务
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

启动后可访问:

  • 应用首页:http://localhost:8000/
  • 健康检查:http://localhost:8000/status
  • Swagger UIhttp://localhost:8000/docs
  • ReDochttp://localhost:8000/redoc

数据库与 Alembic

当前默认使用 SQLite,并区分三个数据库文件:

  • App DBsqlite:///./data/app.db
  • Location DBsqlite:///./data/locationRecorder.db
  • Poo DBsqlite:///./data/pooRecorder.db
  • 数据目录:./data/

初始化 migration 环境后,可继续添加模型并生成迁移:

当前 applocationpoo 都已经有各自独立的 Alembic 链路。

  • App Alembic 环境:alembic_app.ini + alembic_app/
  • Location Alembic 环境:alembic_location.ini + alembic_location/
  • Poo Alembic 环境:alembic_poo.ini + alembic_poo/
  • 统一 migration jobpython -m scripts.run_migrations
  • App DB 初始化:python scripts/app_db_adopt.py
  • Location DB 接管 / 初始化:python scripts/location_db_adopt.py
  • Poo DB 接管 / 初始化:python scripts/poo_db_adopt.py

基础鉴权

当前项目提供一个单用户 admin 鉴权层,用于保护配置页面与管理能力。

  • 认证模型:username/password
  • 会话模型:server-side session + cookie
  • 当前主要受保护页面:/config
  • 当前公开页面:/login
  • 当前公开 API:现有业务 API 暂未在这一轮统一收口到 auth 下

安全实现的当前边界:

  • 密码使用 Argon2 做哈希存储
  • session cookie 使用 HttpOnly
  • Secure 默认随 APP_ENV 切换:非 development 时默认开启
  • SameSite=Lax
  • 登录表单和登出表单都有基础 CSRF 防护

首次启动时,如果 APP_DATABASE_URL 对应的 auth DB 里还没有用户,应用会使用:

  • AUTH_BOOTSTRAP_USERNAME
  • AUTH_BOOTSTRAP_PASSWORD

创建初始 admin 用户。当前默认就是:

  • username: admin
  • password: admin

首次登录后会被要求立即修改密码。这个 bootstrap 只用于首个用户落库,不是后续的完整配置管理方案。

当前前端主要有两条页面路径:

  • /login
  • /config

无论是本地 host:port 还是反向代理后的域名访问,登录成功后都使用相对路径跳转到 /config

Config 持久化

当前 config 页面不会把修改写回 .env

当前原则是:

  • .env 只负责 bootstrap / fallback
  • app 启动先从 .env 读取数据库地址等基础配置
  • 请求期读取配置时,优先使用 app DB 中的 app_config
  • 如果数据库里没有对应值,再 fallback 到 .env

这意味着:

  • location / poo / app DB 地址仍然属于 bootstrap 范畴
  • 运行时可编辑配置主要通过 app_config 表持久化
  • token / secret 这类运行时必须可取回的配置,目前允许明文存储在 config 表中
  • 登录密码仍然单独使用 Argon2 哈希,不走 config 表明文存储

OpenAPI

可使用下面的脚本重新导出当前 API 定义:

python scripts/export_openapi.py

导出结果会写入:

  • openapi/openapi.json
  • openapi/openapi.yaml

Docker Compose

当前默认 Compose 服务名为 app,容器名固定为 home-automation-app

当前 Compose 分成两层:

  • docker-compose.yml:默认使用 registry image,适合部署 / 生产拉取
  • docker-compose.override.yml:仅为本地开发追加 build: .

本地开发启动方式:

docker compose up -d --build

上面的命令会自动叠加 docker-compose.override.yml,因此本地仍然会按当前工作目录重新 build。

如果要按生产方式直接从 registry 拉取并启动,显式只使用基础 compose 文件:

docker compose -f docker-compose.yml pull
docker compose -f docker-compose.yml up -d

持续查看日志:

docker compose logs -f app

Container Image CI

项目提供了一个 release image workflow

  • workflow 文件:.github/workflows/docker-image.yml
  • 触发条件:push 匹配 v* 的 tag,例如 v1.0.0
  • registrycode.wanderingbadger.dev
  • imagecode.wanderingbadger.dev/<owner>/<repo>

docker-compose.yml 中生产默认使用的 app image 当前为:

  • code.wanderingbadger.dev/tliu93/home-automation:latest

当前 workflow 不再把 image name 硬编码到特定 user package 路径,而是直接使用当前仓库标识生成镜像路径:

  • code.wanderingbadger.dev/${github.repository}:${tag}

在 Gitea 这里,package 更贴近 repo 归属的语义,主要体现在镜像命名路径本身,而不是额外的“绑定”动作。也就是说,当前发布方式是按仓库路径约定来对齐 repo/package 语义。

这个 workflow 会构建并推送 multi-arch image

  • linux/amd64
  • linux/arm64

推送的 tag

  • release tag 本身,例如 v1.0.0
  • latest

workflow 依赖以下 secrets

  • REGISTRY_USERNAME
  • REGISTRY_TOKEN

CI 产出的 image 是给部署机直接 docker pull 使用的。部署机不需要 checkout 本仓库,也不需要本地执行 docker build

运行测试

pytest

当前测试包含:

  • app 基本启动测试
  • /status endpoint 测试
  • 登录 / session 基础流程测试

OpenAPI 导出

FastAPI 默认会暴露 OpenAPI。若需要导出静态 schema 文件,可运行:

python scripts/export_openapi.py

输出文件会写到:

  • openapi/openapi.json
  • openapi/openapi.yaml

openapi/ 当前纳入版本控制。接口发生变更时,应重新运行导出脚本并同步提交生成的 schema 文件。

容器启动

  1. 准备环境变量文件
cp .env.example .env
  1. 启动容器
docker compose up --build

默认端口:

  • 8000:8000

SQLite 持久化目录:

  • 本地 ./data
  • 容器内 /app/data
S
Description
No description provided
Readme 660 KiB
v1.0.3 Latest
2026-04-29 13:18:03 +02:00
Languages
Python 94.8%
HTML 2.8%
CSS 1.7%
Mako 0.5%
Dockerfile 0.2%