Skip to content

Latest commit

 

History

History
469 lines (323 loc) · 16 KB

File metadata and controls

469 lines (323 loc) · 16 KB

构建指南

本文档说明 Undefined 当前仓库中的主要构建方式,包括:

  • Python 包构建(wheel / sdist)
  • Undefined-webui 管理控制台的本地开发与验证
  • 跨平台连接器 apps/undefined-console/ 的桌面端 / Android 构建
  • 原生优先聊天客户端 apps/undefined-chat/ 的桌面端 / Android 构建
  • 手动 GitHub Actions artifact 构建
  • GitHub Release 工作流的发布矩阵

约定:

  • 浏览器版管理入口仍然是 uv run Undefined-webui
  • 桌面端 / Android Console 是额外的连接器 / 容器,不替代 Undefined-webui
  • Undefined Chat 是 Runtime API 的原生聊天客户端,Runtime 仍是会话、历史、任务、附件和事件真源
  • Release 工作流默认覆盖 Windows / macOS / Linux / Android,不包含 iOS

1. 环境准备

Python

  • 推荐 Python:3.12
  • 支持范围:3.11 ~ 3.13
  • 推荐使用 uv

安装依赖:

uv sync --group dev -p 3.12
uv run playwright install

渲染环境

render.render_latex 使用 Python 依赖中的 matplotlib.mathtext 本地渲染常见数学公式,不需要系统 TeX、Playwright 或外部网络。复杂 TeX 环境和自定义宏可能不受支持。

HTML 和 Markdown 图片渲染需要 Playwright:

uv run playwright install

渲染 BrowserContext 强制离线;外部图片、字体、样式和脚本不会加载,应改为内联资源。

Node.js / Rust / Tauri

如果需要构建跨平台 Console 或 Chat,请额外准备:

  • Node.js:建议 22
  • Rust stable
  • Tauri v2 所需系统依赖
  • Android 构建时还需要 Java 17、Android SDK / NDK

2. Python 包构建

构建发行包:

uv build

仅构建 wheel:

uv build --wheel

常用本地校验:

uv run ruff check .
uv run ruff format --check .
uv run mypy .
uv run pytest tests/

如果你修改了 res/、img/、config.toml.example 等打包资源,建议额外检查 wheel 内容是否齐全。

3. 浏览器版管理控制台

本地开发入口

推荐直接运行:

uv run Undefined-webui

这条命令会启动管理控制台。推荐工作流:

  1. 启动 Undefined-webui
  2. 在浏览器中打开 WebUI
  3. 若 config.toml 缺失,先由 WebUI 自动生成模板
  4. 在 WebUI 中补齐配置、保存并校验
  5. 直接点击启动 Bot

说明

当前仓库中的 WebUI 静态资源直接由 Python 后端托管,不需要额外执行前端打包命令。

如果你修改了:

  • src/Undefined/webui/templates/
  • src/Undefined/webui/static/js/
  • src/Undefined/webui/static/css/

建议至少运行:

uv run pytest tests/test_webui_management_api.py -q
uv run ruff check src/Undefined/webui

4. 跨平台 App

当前 App 的职责不是维护一套长期独立的第二后台,而是:

  • 保存连接档案
  • 使用一个 IP/域名 + 两个端口录入方式管理实例
  • 测试 Management / Runtime 入口
  • 自动尝试登录后打开真正的远程 WebUI
  • 退出 WebUI 后回到主界面

跨平台 Console 位于:

apps/undefined-console/

Undefined Chat 位于:

apps/undefined-chat/

安装依赖

cd apps/undefined-console
npm install

Chat 使用同样的安装方式:

cd apps/undefined-chat
npm install

Web 壳本地调试

npm run dev

桌面端调试

npm run tauri:dev

桌面端构建

npm run tauri:build

Linux 本地 AppImage 备注

在部分较新的 Linux 发行版上,本地执行 npm run tauri:build 可能在 AppImage 阶段失败,常见表现是:

  • failed to run linuxdeploy
  • 或 strip 无法处理 .relr.dyn 段

如果你本地遇到这个问题,可直接使用:

NO_STRIP=true npm run tauri:build

或者使用仓库里补好的快捷脚本:

npm run tauri:build:no-strip

如果你只想在本机先验证 Linux 安装包链路,也可以优先只打 deb:

npm run tauri:build:no-strip -- --bundles deb

这个问题主要是本机 linuxdeploy / strip 工具链兼容性导致,不一定代表项目代码或 Tauri 配置有问题。

Android 初始化与构建

推荐使用仓库脚本统一检查环境、初始化生成工程、构建并收集产物:

uv run python scripts/build_native_apps.py check --targets android --android-abi arm64-v8a
uv run python scripts/build_native_apps.py build --product chat --targets android --android-abi arm64-v8a

脚本只构建当前机器本地可构建的目标,不会自动安装 Android SDK、NDK 或 Rust target。缺少依赖时,check 和 build 会报告需要补齐的命令。

首次或 CI 环境中,先初始化 Android 项目:

npm run tauri:android:init

Undefined Chat 的 tauri:android:init 会在 Tauri 生成 src-tauri/gen/android 后自动运行 scripts/prepare_tauri_android.py,向生成工程注入移动端 HTML 预览使用的 HtmlPreviewActivity 和 Android Keystore 安全存储使用的 SecretPlugin。src-tauri/gen/ 仍是生成目录,不提交到仓库。

构建 Android:

npm run tauri:android -- --apk

当前仓库也保留了 debug APK 构建路径,便于在 CI 中稳定产出可安装 APK:

npm run tauri:android:debug -- --apk

5. 平台依赖说明

Linux

构建 Tauri 桌面端通常需要:

sudo apt-get update
sudo apt-get install -y \
  libwebkit2gtk-4.1-dev \
  libgtk-3-dev \
  libayatana-appindicator3-dev \
  librsvg2-dev \
  patchelf

macOS

  • 可构建 .dmg
  • 如需签名 / notarization,需额外配置 Apple 证书与 secrets
  • 当前 Release workflow 预留了后续接入空间

Windows

  • 可构建 .exe / .msi
  • 若后续需要代码签名,可在 CI 中继续补证书配置

Android

需要:

  • Java 17
  • Android SDK
  • Android NDK
  • Rust Android targets

Release workflow 会分别为 Console 和 Chat 构建 arm64-v8a、armeabi-v7a、x86、x86_64 的签名 release APK。发布环境必须配置 ANDROID_KEYSTORE_BASE64、ANDROID_KEYSTORE_PASSWORD、ANDROID_KEY_ALIAS 和 ANDROID_KEY_PASSWORD;缺少任一 secret 时 Android 发布任务会失败。

6. Git Hook 集成

WebUI、Console 和 Chat 统一使用 Biome 2.5.10。两个 App 的 package.json 固定该版本,锁文件与根目录及两个 App 的 biome.json schema 同步维护;使用 npm ci 安装锁定的工具版本。

Biome v2 通过 files.includes 表达检查范围和排除规则。两个 App 的 biome.json 设置 root: false,避免从仓库根目录执行检查时出现 nested root configuration 错误;同时使用 extends: [] 显式声明不继承根配置,并各自声明 formatter.indentStyle = "tab",因此 App 代码的格式与规则完全由本目录配置决定,根目录的 WebUI 规则(4 空格缩进、9 条关闭的 lint 规则)不会渗入 App 检查。root: false 只声明配置的嵌套关系,不代表继承根规则。WebUI 脚本仍由根配置的 files.includes 单独圈定,Console 的 npm run lint:webui 通过 --config-path ../../biome.json 显式使用根配置。后续升级应同时迁移三份配置并运行两个 App 的 npm run check,不能只修改 schema 版本号。迁移方式见 Biome v2 官方指南。

仓库内已提供可版本化维护的 git hooks:

.githooks/pre-commit

打 tag 前的版本一致性校验不在本地钩子中执行(git 没有 pre-tag 事件),由 Release workflow 调用 scripts/release_notes.py validate 完成。

安装方式:

bash scripts/install_git_hooks.sh

安装后:

  • pre-commit 会继续执行 Python 的 ruff + mypy
  • 当提交里包含 apps/undefined-console/、apps/undefined-chat/、src/Undefined/webui/static/js/、biome.json、CI workflow 相关改动时,还会额外执行对应 App 的:
    • Biome 检查
    • TypeScript 类型检查
    • cargo fmt --check
    • cargo check

说明:如果本机还没安装 App 依赖,需要先执行:

cd apps/undefined-console
npm install
cd ../undefined-chat
npm install

7. Release 工作流

当前 tag 发布工作流位于:

.github/workflows/release.yml

触发条件:

  • 推送 tag:v*

工作流主要阶段:

  1. verify-python:校验 tag、构建版本和 CHANGELOG.md 最新版本一致,并执行 ruff、mypy、pytest、uv build。
  2. verify-native-app:分别对 Console 和 Chat 执行 npm run check。
  3. build-tauri-desktop:分别构建 Console / Chat 的 Linux .AppImage / .deb、Windows .exe / .msi、macOS x64 .dmg 和 macOS arm64 .dmg。
  4. build-tauri-android:分别构建 Console / Chat 的 Android .apk。
  5. build-docker / merge-docker:构建并发布 Docker 多架构镜像,详见下节。
  6. publish-release:汇总所有产物并上传 GitHub Release;Release notes 从 CHANGELOG.md 最新版本条目生成,不读取 tag 注释。
  7. publish-pypi:发布 Python 包到 PyPI。

Docker 镜像构建与维护

本节面向镜像维护者。部署和使用步骤见 Docker 一键部署指南。

镜像 内容与版本
ghcr.io/<owner>/undefined-bot:v<版本> Undefined 本体,包含 Python 3.12、项目依赖、FFmpeg、Docker CLI 和 Playwright Chromium;版本与项目版本一致
ghcr.io/<owner>/undefined-lxmusic2api:<短sha> 从 lxmusic2api 上游固定 commit 构建,使用该 commit 的短 SHA 作为 tag

.github/workflows/release.yml 在推送 v* tag 时构建这两个镜像。build-docker 在原生 amd64 / arm64 runner 上分别构建并推送 digest,merge-docker 再合并为支持 linux/amd64 与 linux/arm64 的 manifest。镜像发布使用内置 GITHUB_TOKEN,packages: write 权限仅授予这两个 job,无需额外配置推送 secret。

该工作流没有 workflow_dispatch,旧 tag 不会自动补建镜像。需要本地构建时,在仓库根目录执行以下命令,并将 <owner> 与 <版本> 替换成部署时使用的镜像 owner 和当前项目版本:

docker build -f src/Undefined/deploy/templates/Dockerfile.bot -t 'ghcr.io/<owner>/undefined-bot:v<版本>' .

镜像定义集中在 src/Undefined/deploy/images.py:

  • 升级 lxmusic2api 时,更新 LXMUSIC2API_UPSTREAM_SHA 为完整的 40 位 commit SHA,再发布新版本;CI 会构建对应镜像,部署脚本只在选中该服务时解析它。
  • 升级 NapCat、SearXNG、Firecrawl 及依赖时,更新对应镜像引用并同步 PIN_VERIFIED_ON。其中 playwright-service 与 nuq-postgres 当前使用 latest。
  • 修改后运行 uv run pytest tests/test_deploy_catalog.py tests/test_deploy_generate.py tests/test_deploy_packaging.py,核对镜像引用、生成配置与打包资源。

CI 工作流(ci.yml)

拉取请求与 main / develop 推送会触发 .github/workflows/ci.yml,工作流级声明 permissions: contents: read 与并发取消(同一 ref 的新推送会取消旧运行),每个 job 都带 timeout-minutes:

  1. quality-check(Python 3.12):ruff + ruff format --check + mypy + pytest tests/ --cov(覆盖率低于 pyproject.toml 的 fail_under 即失败)+ uv build --wheel 并校验 wheel 内含资源。该 job 会 setup-node 并执行 npm ci --prefix tests/frontend,以便 WebUI 前端的 node 行为测试(用 jsdom 驱动真实 DOM)真正执行——缺这段安装时该文件的 _require_env() 会让用例直接失败(只有在本地非 CI 环境下才会 skip)。
  2. python-compat(3.11 / 3.13):pyproject.toml 声明 >=3.11,<3.14,因此两端边界各跑一次 mypy 与 pytest。
  3. native-app-quality-check(Console / Chat 矩阵):npm run check。

依赖统一通过 uv sync --group dev 安装:dev 是唯一一份工具清单(含 pytest-cov 与 types-* 类型桩),不再维护与它重复的 ci 组或 [project.optional-dependencies]。

8. 手动 Artifact 工作流

如果只想让 GitHub Actions 编译一次原生 App 并从 workflow run 页面手动下载产物,不创建 GitHub Release,也不发布 PyPI,可以使用:

.github/workflows/manual-native-artifacts.yml

触发方式:

  • workflow_dispatch

默认输入会构建 Undefined Chat:

  • 桌面端:Linux .AppImage / .deb、Windows .exe / .msi、macOS x64 / arm64 .dmg
  • Android:arm64-v8a debug APK

可选输入:

  • source_ref:要构建的分支、tag 或 SHA;留空时使用 Actions 页面选择的 ref。
  • product:chat、console 或 all。
  • build_desktop:是否构建桌面端。
  • desktop_platform:all、linux、windows 或 macos。
  • build_android_debug:是否构建 Android debug APK。
  • android_abi:arm64-v8a、armeabi-v7a、x86、x86_64 或 all。

手动 artifact 工作流的边界:

  • 不调用 gh release create。
  • 不发布 Python 包到 PyPI。
  • Android 只构建 debug APK,不需要配置 release keystore secrets。
  • artifacts 通过 actions/upload-artifact 上传到 workflow run,默认保留 14 天。

注意:GitHub 的 workflow_dispatch 手动入口通常要求 workflow 文件已存在于默认分支。若该文件只存在于 feature 分支,Actions 页面可能不会显示这个手动 workflow;将该 workflow 文件合入默认分支后,可在运行时通过 source_ref 指向任意待构建分支,例如 feature/chat-app。

9. Release 产物矩阵

面向普通用户的下载选择见 README — Release 下载速查;本节只记录构建和发布矩阵。部署 Bot 本身不需要下载 Console / Chat 客户端安装包。

每次正式 Release 计划上传:

  • Python
    • wheel
    • sdist
  • Windows
    • Undefined-Console-*-windows-x64-setup.exe
    • Undefined-Console-*-windows-x64.msi
    • Undefined-Chat-*-windows-x64-setup.exe
    • Undefined-Chat-*-windows-x64.msi
  • Linux
    • Undefined-Console-*-linux-x64.AppImage
    • Undefined-Console-*-linux-x64.deb
    • Undefined-Chat-*-linux-x64.AppImage
    • Undefined-Chat-*-linux-x64.deb
  • macOS
    • Undefined-Console-*-macos-x64.dmg
    • Undefined-Console-*-macos-arm64.dmg
    • Undefined-Chat-*-macos-x64.dmg
    • Undefined-Chat-*-macos-arm64.dmg
  • Android
    • Undefined-Console-*-android-*-release.apk
    • Undefined-Chat-*-android-*-release.apk

iOS 当前不在发布矩阵内。

10. 推荐的本地构建顺序

如果你准备发布一个版本,建议本地先按以下顺序自检:

uv sync --group dev -p 3.12
uv run ruff check .
uv run ruff format --check .
uv run mypy .
uv run pytest tests/ --cov
uv build

如果本次改动涉及 App:

cd apps/undefined-console
npm install
npm run check  # 代码检查与测试(lint/typecheck/test/cargo fmt/check/test,具体以 package.json 为准)
# 注意:npm run tauri:build 会自动执行 npm run build,无需手动构建前端

cd ../undefined-chat
npm install
npm run check  # Biome、TypeScript、unit + e2e(jsdom)测试、cargo fmt/check/test

如果本次改动涉及 Android 构建链:

uv run python scripts/build_native_apps.py check --targets android --android-abi arm64-v8a
uv run python scripts/build_native_apps.py build --product chat --targets android --android-abi arm64-v8a

如需排查底层 Tauri Android 命令,可继续直接运行:

npm run tauri:android:init
npm run tauri:android:prepare:check  # Undefined Chat 检查生成工程已包含 HtmlPreviewActivity/SecretPlugin
npm run tauri:android:debug -- --apk

11. 常见建议

  • 日常开发和首次部署,优先验证 uv run Undefined-webui 全流程是否顺畅。
  • 改动管理接口时,优先补 tests/test_webui_management_api.py。
  • 改动发布矩阵时,务必同步更新 README.md、Undefined Chat 与本文件。
  • 改动 App 构建脚本时,注意同时检查 apps/undefined-console/package.json、apps/undefined-chat/package.json 与 .github/workflows/release.yml。