关于 phoenix-sqlean
phoenix-sqlean 是 nalgeon/sqlean.py 的内置分支,提供工具来固定和更新打包的 SQLite、sqlean 与 xxHash 源码版本,面向该包的维护和发布。文档涵盖可复现的源码获取、版本检查、wheel 构建与发布。
主要功能
- 01固定上游源码版本
- 02检查并更新版本固定项的脚本
- 03构建 Python wheel 和 sdist
- 04wheelhouse 与发布校验
适用场景
- 01更新打包的 SQLite 或 sqlean 源码
- 02发布前检查源码版本固定项
- 03构建并验证包的分发文件
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ arize-ai/ phoenix --skill phoenix-sqlean安装后在 Claude Code 中输入/phoenix-sqlean确认已加载。
详细介绍
phoenix-sqlean
nalgeon/sqlean.py 的 vendored 分支。
更新捆绑版本
固定项位于 packages/phoenix-sqlean/Makefile。每项都有一个必须同步更新的配套项:
| 固定项 | 需同步更新 |
|---|---|
SQLITE_VERSION | SQLITE_RELEASE_YEAR(URL 中包含两者,不匹配会导致 404)和 SQLITE_SHA256 |
SQLEAN_COMMIT | Makefile 和 setup.py 中的 SQLEAN_VERSION——实际获取的是该提交,字符串仅用于描述它 |
SQLEAN_VERSION | setup.py 中的副本,它会被编译进去,作为 sqlean_version() 的返回值。仅当 SQLEAN_COMMIT 超前于指定标签时,才添加后缀 +<short sha> |
XXHASH_TAG | XXHASH_COMMIT、XXHASH_SHA256,以及 sqlean 自己的 Makefile 获取的标签 |
download-sqlean 的前置目标 check-sqlean-pin 会通过一次 ls-remote 检查 SQLEAN_* 各项:后缀必须是提交的前缀,基础版本必须是真实标签,仅当提交领先时才应有后缀,且 setup.py 中的版本必须一致。它无法判断基础版本是否指向了错误的发行版——单提交获取不包含祖先关系。SQLITE_* 和 XXHASH_* 没有类似的交叉检查,只会在获取时检查哈希。
sqlean 通过 git 按提交获取:GitHub 的源代码归档按需生成,字节内容不稳定,因此无法固定校验和;而 git 会对收到的每个对象进行哈希。因此,download-sqlean 需要 PATH 中有 git,且无需校验和。另外两个依赖通过普通 HTTP 获取,而 curl 不会验证任何内容——XXHASH_COMMIT 确定哪些字节才是正确的,XXHASH_SHA256 则证明获取到的正是这些字节。src/test_windirent.h 两者都不需要;它已提交到此仓库。
使用脚本
scripts/check-upstream.sh 会解析并重写所有固定项,包括哈希:
cd packages/phoenix-sqlean
./scripts/check-upstream.sh sqlite # detection only, no downloads
./scripts/check-upstream.sh sqlite --apply # rewrite pins, print a Markdown summary
./scripts/check-upstream.sh sqlean [--apply] # also moves XXHASH_* if sqlean moved its own
手动操作
使用 git ls-remote <repo> 'refs/tags/<version>*' 将标签解析为提交;如果标签带注释,则取 ^{} 行。sqlean 还有一个非版本标签(incubator),因此选择最新标签前应先按格式筛选。
对于 SQLITE_SHA256,在记录 SHA-256 前,应根据 https://sqlite.org/download.html 的 PRODUCT 行确认下载文件的 SHA3-256(shasum 无法计算 SHA3)。跳过这一步会导致该固定项采用首次使用时信任的做法。
验证
cd packages/phoenix-sqlean
make prepare-src download-sqlite download-sqlean # always the full chain: download-sqlean
# APPENDS init.c, so alone it double-appends
python setup.py build_ext -i
python -m tests
保持最新
Dependabot 无法识别这些固定项——它没有自定义正则管理器——这里也没有 Renovate。phoenix-sqlean-upstream.yml 弥补了这一缺口:每周为每个组件创建一个草稿 PR,运行 check-upstream.sh --apply,不涉及模型。
它不会构建或测试任何内容。 CI 会在 PR 上负责这些工作;如果在更新任务中验证,就会重复运行其中一部分,而且只能在最可能出现问题的平台上运行——该平台无法复现 MSVC 补丁上的 patch(1) 问题。
如果脚本本身失败,则是另一回事:上游的结构发生了变化,因此脚本会在写入前退出,任务会失败且不会创建 PR,因为没有可供审查的计算结果。
XXHASH_* 按设计不受监控。它由 sqlean 驱动,而 sqlean 更改自己的固定项时,download-sqlean 已经会失败。
注意事项
src/test_windirent.h固定在 3.50.4 版本——不要重新同步。 SQLite 已在 3.51.0 中移除该文件,之后的标签中也没有它。该文件是有意随项目一并提供的,并非下载所得。- sqlean >= 0.28 需要
crypto/xxhash.impl.h,而 sqlean 并未随附该文件。 添加任何新的第三方源代码时,都需要在THIRD_PARTY_LICENSES中添加相应条目,并且在license=中注明其 SPDX 标识符。 patch(1)无法应用src/sqlean-time-msvc.patch是预期的警示信号,并非故障。请基于新版 sqlean 源代码重新生成该补丁。- “sqlean 获取了 xxHash X,但 XXHASH_TAG 是 Y”是另一个警示信号。 请更新全部三个
XXHASH_*固定项,以及THIRD_PARTY_LICENSES中注明的版本。 - 单独来看,
sqlean_version()测试只是个恒真测试——它将编译时宏与setup.py自身的常量比较,只能证明二进制文件不是陈旧的。只有check-sqlean-pin能将该常量与SQLEAN_COMMIT关联起来。 - 仅更改
SQLEAN_VERSION不会触发重新编译。 它只会修改一个-D标志,而build_ext根据源文件修改时间来判断是否重新编译。编辑后请执行touch src/sqlean.c,否则版本测试会因构建产物陈旧而失败。 - 保持软件包版本为纯 SemVer。 release-please 的版本正则表达式未锚定,因此
1.2.3.1和1.2.3.post1会被截断为1.2.3,并与已有标签冲突,且不会提示。同理,setup.py中的VERSION必须保持高于SQLEAN_VERSION。软件包版本有意与捆绑的 SQLite 版本相互独立。
Wheel 和发布
- 设置位于
cibuildwheel.toml;运行器和步骤位于phoenix-sqlean-build.yml,这是一个workflow_call工作流,publish.yaml中的build-sqlean和 CI 的wheels作业都会在不传入覆盖项的情况下调用它。PR 运行的构建与发布运行的完全相同——应保持如此,而不是缩小 CI 中的构建范围。 - Wheel 矩阵包含
python_requires允许的所有 CPython 版本 × toml 中的build平台 × 构建工作流的运行器,减去 toml 中的skip,再加上 C 源代码的 sdist。请从配置中读取矩阵,而不要在此处重述。 - cibuildwheel 会测试每个 wheel,因此 Linux/Windows 的每种架构都需要一个运行器。 这些架构为
native;cibuildwheel 会跳过交叉编译的win_arm64的测试,而 Windows AMD64 上的auto会额外包含 32 位 x86。macOS 在一个 arm64 运行器上构建两种架构,并在 Rosetta 下测试 x86_64。配置文件中的skip排除了自由线程构建;否则 cibuildwheel 默认也会构建这些版本。 - 构建工作流的
check作业会通过scripts/check-wheelhouse.py检查合并后的集合,因此 CI 和发布都会运行此检查:对于PLATFORMS中的每个平台,python_requires允许的每个 CPython 版本都必须恰好有一个 wheel,此外还必须有一个 sdist。添加或移除平台时,必须同时修改PLATFORMS、运行器和archs。 - 支持的 Python 版本范围由
setup.py中的python_requires决定,除此之外没有其他定义。 cibuildwheel 会读取它来选择 CPython 版本,而 wheelhouse 检查会要求版本与其完全一致。它必须是if __name__ == "__main__"下setuptools.setup(...)调用中的字符串字面量关键字——cibuildwheel 会静态解析该项;如果找不到,它会静默构建其已知的所有 CPython 版本(届时 wheelhouse 检查会失败)。 - 纳入新的 CPython 版本可能会以两种方式失败,而且都会明确报错。 cibuildwheel 可能仍将其视为预发布版本,因此缺少对应 wheel,导致 wheelhouse 检查失败——此时应升级 cibuildwheel。或者,该版本可能移除了驱动程序使用的私有 C API,导致该版本的 wheel 构建失败。
- 源代码准备是构建工作流的第一个作业,在 Ubuntu 上运行,因为 Windows 运行器缺少 make/curl/unzip。其
ref输入决定要构建的内容:CI 留空(使用 PR 的提交),发布则传入发布标签。调用方不传入其他内容。 test-sources根据 cibuildwheel 的工作目录解析,而不是根据package-dir解析——因此各构建任务会在工作区根目录解压源代码。- 只有标签
arize-phoenix-sqlean-v<manifest version>才能通过发布门控。在 release-please 创建该标签之前,sqlean-release会跳过,因此不会进行构建。 - sqlean 会一直发布,直到 PyPI 上包含该版本的所有发行文件,而不仅仅是该版本号。
list-python-packages中通用的“版本已在 PyPI 上”门控会跳过 sqlean;sqlean-release会在每次发布时运行,并针对 PyPI 的该版本文件列表运行check-wheelhouse.py --missing-only。如果发布在上传途中中断,重新运行发布即可完成:它会根据标签重新构建,并使用skip-existing上传。 check-wheelhouse.py始终来自运行工作流的提交;python_requires则来自正在构建的源代码。PLATFORMS必须与运行器匹配,运行器也来自该提交;而较早的发布标签早于此脚本。- PyPI 使用可信发布,且不使用 GitHub 环境;发布者的 Environment 字段必须保持空白,才能与之匹配。