
Yuxi 候选发布验证与 CLI 独立发布tag 驱动的发布门禁工程实践【免费下载链接】Yuxi可私有部署的多租户知识智能体平台统一 RAG、知识图谱、多智能体、MCP/Skills、沙盒与权限管理。Self-hosted knowledge agent platform for RAG, knowledge graphs and multi-agent workflows.项目地址: https://gitcode.com/GitHub_Trending/yu/Yuxi本文是 Yuxi 仓库内部工程决策记录docs/develop-guides/decisions/implemented/2026-09-09-release-validation.md的展开解读聚焦应用版本与 CLI 包版本解耦这一发布工程问题。你将看到如何通过v[0-9]*tag 触发完整 CI 门禁、如何让 Ruff 独立于后端依赖树运行、如何显式注入 CI 账号完成 HTTP 认证测试以及候选 tag → 正式 tag 的两段式发布操作。文中所有结论均可追溯到仓库内的 workflow 配置、回归测试与贡献指南。一、问题背景三个互相关联的发布缺陷Yuxi 采用应用后端 Web与 CLI 包两个独立版本体系应用通过 GitHub Release 发布CLI 包通过 PyPI 发布。在本次决策落地之前发布流程存在三个典型缺陷应用 Release 误触发 CLI 重复上传。应用发布与 CLI 包版本相互独立但应用 Release 事件会触发 CLI 的 PyPI 上传。只要 CLI 代码未升版就会产生对同一版本号的重复上传更严重的是这种机制会掩盖未升版 CLI 代码被误发布的问题继续把两个独立产品版本耦合在一起。候选 tag 缺少完整 CI 触发。候选 tag如v0.7.3-rc.1没有触发完整发布门禁维护者无法直接查看候选版本的全部检查结果若只依赖 main 分支的路径过滤检查就无法确认候选 tag 指向的提交是否真的满足发布条件。HTTP 测试因缺少认证变量被跳过。运行链路Runtime System Tests中的部分 HTTP 测试依赖登录账号与密码未显式传入 CI 初始化的账号时会被静默跳过导致 API Key 生命周期、Skill 授权等关键路径在发布验证中缺席。Ruff 检查受无关依赖下载失败影响。Ruff workflow 直接安装整个后端依赖树而 lint/format 检查本身与这些依赖无关任何无关镜像或包下载失败都会让格式检查整体失败放大了检查的失败面。二、核心决策tag 驱动的发布门禁与 CLI 独立发布针对上述问题决策层确立了三项机制2.1 发布门禁统一监听v[0-9]*tag.github/workflows中的发布门禁trust、test、web、ruff、system-tests、dependency-audit、deploy统一监听v[0-9]*版本 tag覆盖工程契约、后端单测、前端、运行链路、依赖审计和文档构建六类检查分支推送main继续保留原有的路径过滤文档部署仍限制在 main 分支。这样候选 tag 与正式 tag 都会跑完整 CI维护者在推 tag 时即可看到该提交的全部发布门禁结果。2.2 Ruff 独立安装不再安装整个后端依赖Ruff workflow 从后端锁文件backend/uv.lock中读取工具版本并通过官方 PyPI 独立安装RUFF_VERSION$(python -c import tomllib; from pathlib import Path; print(next(p[version] for p in tomllib.loads(Path(uv.lock).read_text())[package] if p[name] ruff))) uv tool install --no-config --default-index https://pypi.org/simple ruff$RUFF_VERSION随后对package目录执行三项检查lintruff check package、格式ruff format package --check、导入顺序ruff check --select I package。完整实现见 .github/workflows/ruff.yml。该方案把工具本身与被检查的依赖树解耦检查只受 Ruff 自身下载影响也显著缩短了 job 耗时。2.3 运行链路显式注入 CI 账号运行链路 workflow.github/workflows/system-tests.yml通过E2E_USERNAME/E2E_PASSWORD环境变量承载 CI 初始化的隔离管理员账号并为 Run 结果归属test_agent_run_result_causality.py、API Keytest_apikey_router.py和 Skill 授权test_skill_artifact_authorization.py测试显式传入- name: Verify Run result causality run: docker compose exec -T -e TEST_USERNAME$E2E_USERNAME -e TEST_PASSWORD$E2E_PASSWORD api uv run --no-sync --no-dev pytest test/integration/api/test_agent_run_result_causality.py -q账号由 workflow 在启动阶段初始化调用/api/auth/initialize创建隔离的 E2E 管理员见 .github/workflows/system-tests.yml 中 Initialize isolated E2E administrator 步骤。2.4 CLI 发布仅保留手动入口publish-yuxi-cli.yml只保留workflow_dispatch手动触发CLI 包版本由其自身的pyproject.toml拥有见 packages/yuxi-cli/pyproject.toml应用 Release 事件不再触发任何 PyPI 写入。发布步骤依次为安装依赖uv sync --group test、跑测试uv run pytest、构建uv build、通过 trusted publishing 发布pypa/gh-action-pypi-publish见 .github/workflows/publish-yuxi-cli.yml。三、源码级防线回归测试把决策固化为门禁决策不只是一份文档还由两个可执行检查长期守护任何回归都会让对应 gate 失败。3.1 发布事件回归检查python3 -m unittest scripts.test_release_workflows源码见 scripts/test_release_workflows.py逐字解析真实 workflow 文件验证七个发布门禁都必须声明 tag 触发对 trust、test、web、ruff、system-tests、dependency-audit、deploy 逐一断言push.tags含[v[0-9]*]删除任一 tag 触发都会触发负向断言失败test_missing_tag_trigger_is_rejected。CLI 只能手动发布解析publish-yuxi-cli的on事件列表必须恰好等于[workflow_dispatch]恢复应用 Release 触发on: release: types: [published]时断言失败test_application_release_cannot_publish_cli。Runtime System Tests 必须有冷缓存构建预算断言system-tests.yml的timeout-minutes不少于 60 分钟把预算改回 35 分钟时 gate 必须失败test_runtime_system_tests_reject_short_build_budget。该检查由 .github/workflows/trust.ymlEngineering Trust Contracts在 PR 与 tag 推送时执行。3.2 认证命令接线检查python3 scripts/verify_engineering_contracts.py源码见 scripts/verify_engineering_contracts.py从真实 workflow 文件提取runstep核对WORKFLOW_CONTRACTS中登记的认证命令必须原样存在且处于阻断状态不得被if跳过、continue-on-error吞错或set e掩盖失败。system-tests.yml的契约中明确登记了携带TEST_USERNAME/TEST_PASSWORD/E2E_USERNAME/E2E_PASSWORD的命令删除任一账号或密码参数对应 HTTP 门禁命令便无法匹配verifier 报错。负向测试见 scripts/test_verify_engineering_contracts.py。四、验证结果18 项测试零跳过决策验证阶段在真实 Docker Compose 服务上运行了 Run 结果归属、API Key 与 Skill 授权三组集成测试全部通过docker compose exec -T api uv run --no-sync --no-dev pytest test/integration/api/test_agent_run_result_causality.py test/integration/api/test_apikey_router.py test/integration/api/test_skill_artifact_authorization.py -q -rs共 18 项测试通过、零跳过分别断言Run 持久化后的归属关系、API Key 生命周期创建、派生、删除、用户生命周期联动见 backend/test/integration/services/test_api_key_user_lifecycle.py 与 backend/test/integration/services/test_api_key_schema_migration.py以及撤销权限后的 Skill artifact 访问被拒绝见 backend/test/integration/api/test_skill_artifact_authorization.py。除此之外Actionlint 校验 workflow 语法Ruff、后端 unit 与文档构建分别由实际命令验证远端 workflow 结果记录在 PR 中不以本地配置检查替代 GitHub 实际执行。五、候选 tag 与正式发布操作指南发布操作流程由贡献指南维护核心要点如下准备发布前定稿版本号、changelog 和升级说明功能更新以最近的正式 tag 为基线例如 0.7.3 使用v0.7.2..HEAD对比范围候选版本之间的修复归并到对应功能不单独替代完整发布说明。创建候选 tag在已审查的提交上创建如v0.7.3-rc.1的候选 tag 并显式推送需要对外试用时创建 GitHub Release 并标记 Pre-release。候选 tag 命中v[0-9]*后完整 CI工程契约、后端单测、Ruff、Web、运行链路、依赖审计、文档构建全部触发。核对结果并迭代在 Actions 核对各门禁若修复产生新提交创建下一个候选 tag已推送的候选 tag 保留原指向。转正式最终候选通过后在同一提交新增正式 tag 并发布正式 ReleaseRelease 正文保留相对上一正式版本的完整功能更新与升级注意事项。文档站只在 main 分支推送时部署。发布 CLI需要发布 CLI 时先提交packages/yuxi-cli/pyproject.toml的版本与锁文件更新再对明确的提交或 tag 手动运行 Publish yuxi-cliCLI 版本未变时无需重复发布上传失败须检查版本与 PyPI 状态。六、后果与边界这套方案的代价与边界在决策记录中如实写明运行成本增加候选与正式 tag 都运行完整 CI相比纯分支路径过滤更昂贵。为此system-tests的 job 预算设为 60 分钟覆盖 GitHub 新 runner 冷缓存构建 sandbox-provisioner、API 和 worker 后的完整检查构建阶段超时会阻断发布参见 .github/workflows/system-tests.yml 的timeout-minutes: 60与 scripts/test_release_workflows.py 中assert_cold_build_budget的预算下限断言。CLI 发布需要显式人工操作这是有意为之的摩擦用于防止应用发布顺手把未升版的 CLI 也发上去。验证边界明确workflow 成功不证明真实 provider 连通性与生产备份恢复可用——这两类能力仍由 .github/workflows/real-provider-probe.yml 手动探针和部署演练覆盖未验证范围需要在发布说明中记录。七、小结把发布纪律固化为可执行门禁Yuxi 这次发布验证决策的实质是把三条纪律写进了 CI 本身候选版本必须接受与正式版本同等的完整检查独立版本的产品应用与 CLI必须由独立入口发布会静默跳过测试的认证缺口必须由 verifier 拒绝。从 .github/workflows/trust.yml 到 scripts/test_release_workflows.py再到 docs/develop-guides/contributing.md 的操作清单整条链路自洽且可回归。对于同样维护应用 CLI 双版本的团队这套tag 触发 独立发布 契约回归的组合值得直接借鉴。【免费下载链接】Yuxi可私有部署的多租户知识智能体平台统一 RAG、知识图谱、多智能体、MCP/Skills、沙盒与权限管理。Self-hosted knowledge agent platform for RAG, knowledge graphs and multi-agent workflows.项目地址: https://gitcode.com/GitHub_Trending/yu/Yuxi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考