版本发布¶
发布通过推送(push)git 标签触发。标签名称决定发布渠道。
标签命名约定¶
| 标签格式 | 渠道 | GitHub Release 类型 |
|---|---|---|
v1.2.3-alpha.1 |
alpha | Pre-release |
v1.2.3-beta.1 |
beta | Pre-release |
v1.2.3-rc.1 |
rc | Pre-release |
v1.2.3 |
stable | Latest release |
创建发布¶
# Alpha
git tag v1.2.3-alpha.1 && git push origin v1.2.3-alpha.1
# Beta
git tag v1.2.3-beta.1 && git push origin v1.2.3-beta.1
# Release candidate
git tag v1.2.3-rc.1 && git push origin v1.2.3-rc.1
# Stable
git tag v1.2.3 && git push origin v1.2.3
CI 工作流(build-dmg.yml,名为"Build Provisa Packages")会在任何 v* 标签上触发,并执行以下工作,其中大部分并行运行:
- Resolve release metadata — 从标签后缀检测渠道,推导 PEP 440 版本和资产名称
- Download / package Trino plugins — 拉取 Calcite Trino 连接器并打包为 tarball
- Pull core / obs / demo Docker images — 保存服务镜像的 tarball(arm64,另加 amd64 core 供 Windows 容器层使用)
- Build macOS Core / Obs / Demo DMGs — 在
macos-14(Apple Silicon)上运行,离线环境(airgapped) - Build Linux AppImage — core,离线环境
- Build Windows Core installer — 原生、内嵌 Python、无需 Docker
- Build Windows Container-tier installer — WSL2 + Trino,按需获取镜像(无需 VirtualBox/OVA)
- Build JDBC driver — Maven shaded JAR
- Build and test Python client,然后 Publish to PyPI
- Publish GitHub Release — 上传全部资产,为 alpha/beta/rc 设置 pre-release 标志
发布资产¶
每次发布都会发布以下资产,全部附加到 GitHub Release(wheel 也会同步发布到 PyPI):
| 资产 | 平台/用途 |
|---|---|
Provisa-<tag>-macOS.dmg |
macOS Core(Apple Silicon,离线环境) |
Provisa-Runtime-<tag>-macOS.dmg |
macOS 原生 Python 运行时(与 Core 一起挂载) |
Provisa-Obs-<tag>-macOS.dmg |
macOS 可观测性扩展 |
Provisa-Demo-<tag>-macOS.dmg |
macOS 演示扩展(需要 Obs) |
Provisa-<tag>-linux-x86_64.AppImage |
Linux x86_64 core(离线环境) |
Provisa-<tag>-windows-x64.exe |
Windows x64 原生安装程序(内嵌 Python,无需 Docker) |
Provisa-Container-<tag>-windows-x64.exe |
Windows x64 容器层升级(WSL2 + Trino) |
provisa-jdbc-<tag>.jar |
JDBC 驱动程序 — Tableau、PowerBI、DBeaver |
provisa_client-<pep440>-py3-none-any.whl |
Python 客户端(同时发布于 PyPI) |
provisa-core-images-<tag>.tar.gz |
Core Services 镜像 tarball(arm64,离线环境) |
provisa-core-images-amd64-<tag>.zip |
Core Services 镜像(amd64,Windows 容器层/离线环境) |
provisa-obs-images-<tag>.tar.gz |
Observability Stack 镜像(可选) |
provisa-demo-images-<tag>.tar.gz |
Demo Data Pack 镜像(可选) |
provisa-trino-plugins-<tag>.tar.gz |
Coordination Engine 连接器(SharePoint、Splunk、File) |
Python 客户端版本会自动转换为 PEP 440 格式:
v0.1.0-alpha.1 → 0.1.0a1,v0.1.0-beta.1 → 0.1.0b1,v0.1.0-rc.1 → 0.1.0rc1。
PyPI 发布设置(一次性)¶
.github/workflows/build-dmg.yml 中的 publish-pypi(provisa-client)和 publish-provisa-pypi(provisa)任务通过 PyPI 可信发布(trusted publishing)进行发布:由任务的 GitHub OIDC 令牌(id-token: write)完成身份验证,不读取任何 API 令牌。请在 pypi.org 上将本仓库和 build-dmg.yml 注册为每个项目的可信发布者(Your projects → Manage → Publishing)。此后每次打标签都会自动发布。
签名与供应链¶
发布工作流构建时,每个发布工件所带有的内容:
| 工件 | 签名 |
|---|---|
PyPI 上的 provisa 和 provisa-client |
每个文件一份经 Sigstore 签名的 PEP 740 证明(attestations: true),可在 pypi.org 上验证 |
PyPI 上的 provisa-pg-ext、provisa-duckdb-ext |
每个文件一份经 Sigstore 签名的 PEP 740 证明 |
JDBC 驱动 .jar |
Sigstore 构建来源证明(actions/attest-build-provenance) |
macOS .dmg 安装程序 |
Developer ID 代码签名和 Apple 公证 |
Windows .exe 安装程序 |
未签名 |
Linux .AppImage |
未签名 |
任何操作系统上的签名安装方式都是 pip install provisa:带有 Sigstore 证明的 PyPI 软件包。需要在 Linux 或 Windows 上获得签名工件的审阅者,请使用 pip 安装。配置了代码签名证书时,Windows 构建会使用 Authenticode 签名(WINDOWS_CERT_PFX_BASE64、WINDOWS_CERT_PFX_PASSWORD、WINDOWS_CERT_TIMESTAMP_URL,由 packaging/windows/build-sfx.ps1 读取);目前未配置,因此以未签名形式发布。
依赖项和 CVE 关卡:
- Python 依赖项在
uv.lock中带哈希锁定;CI 使用uv sync --frozen安装它们。 CVE Audit工作流(.github/workflows/cve-audit.yml)在每次推送到main、每个拉取请求以及每周,对锁定的集合运行pip-audit。- 发布时,
provisa和provisa-client的构建各自生成一份 CycloneDX SBOM,并对所发布的内容运行pip-audit。JDBC 驱动使用grype --fail-on medium扫描。任何发现都会使任务失败,且发布不会发布任何内容:PyPI 上传和 GitHub 发布都会等待这些任务。SBOM 和 CVE 报告会附加到每个发布上。 - 桌面安装程序在发布运行器上从源代码构建
provisawheel,并在构建时用pip解析其依赖项,而不是从uv.lock解析;发布 CVE 关卡扫描的是锁定的集合,而不是安装程序捆绑的依赖项。 - 有一项有文档记录的例外被忽略:PYSEC-2026-4114 / CVE-2026-49265(服务器端 oauthlib PKCE;Provisa 仅在客户端使用 oauthlib)。
packaging/pypi/requirements-embedded.lock是provisa[embedded]的哈希固定解析结果,供离线(airgap)镜像使用(参见packaging/pypi/MIRROR-CHECKLIST.md)。它是手动重新生成的,而不是每次发布都生成。
所需的仓库密钥¶
请在 Settings → Secrets → Actions 中配置以下内容:
| 密钥 | 所需用途 | 说明 |
|---|---|---|
APPLE_CERT_P12_BASE64 |
签名构建 | Base64 编码的 .p12 证书文件(见下文) |
APPLE_CERT_P12_PASSWORD |
签名构建 | 从 Keychain Access 导出 .p12 时设置的密码 |
APPLE_DEVELOPER_ID |
签名构建 | 完整证书名称:Developer ID Application: Your Name (TEAMID) |
APPLE_NOTARYTOOL_APPLE_ID |
公证构建 | Apple ID 电子邮件地址 |
APPLE_NOTARYTOOL_PASSWORD |
公证构建 | 来自 appleid.apple.com 的应用程序专用密码(不是你的登录密码) |
APPLE_NOTARYTOOL_TEAM_ID |
公证构建 | 10 个字符的 Apple Team ID |
没有这些密钥的构建仍能成功完成,但会生成未签名/未公证的 DMG(用户将看到 Gatekeeper 警告)。
导出 .p12 证书¶
- 打开 Keychain Access → 登录钥匙串 → My Certificates
- 查找 Developer ID Application: Your Name (TEAMID) — 展开以确认私钥嵌套在其下方
- 同时选中证书及其私钥 → 右键点击 → Export 2 Items → 另存为
.p12→ 设置一个强密码 - 进行 Base64 编码并复制到剪贴板:
- 将其粘贴为
APPLE_CERT_P12_BASE64的值;将APPLE_CERT_P12_PASSWORD设置为步骤 3 中的密码
查找你的证书名称¶
复制引号中的完整字符串——这就是 APPLE_DEVELOPER_ID 的值。
删除错误的标签¶
然后在界面中删除对应的 GitHub Release,再重新打标签。