Skip to main content

funbuild

PyPI version Python License: MIT

funbuild 是面向 Python / 混合仓库的构建与发布辅助工具:根据项目结构自动选择构建策略(UV、Poetry、旧式 PyPI 脚本、package.json 前端包、Flutter 及混合模式等),串联版本递增、构建、安装校验、发布与 Git 标签等常见流程。

特性

  • 多构建策略:按仓库布局自动匹配 UVBuild、PoetryBuild、PypiBuild、NpmFrontendBuild、UvNpmHybridBuild 等实现,无需手写切换逻辑。
  • 版本同步:以根目录 pyproject.toml 的 [project].version 为主源时,可将版本同步到仓内其它带 version 的 pyproject.toml、package.json 与 pubspec.yaml(含子目录;pubspec.yaml 只同步 major.minor.patch,+buildNumber 保持不变)。
  • 依赖取最新:在 [tool.funbuild].latest-packages 里列出的依赖,每次发版前会把版本下界抬到当时最新的已发布版本并写回 pyproject.toml,使其进入 wheel metadata,下游升级时必定带上最新的上游;名单里的包若还没写进 dependencies,会按最新版本补上。
  • 依赖与工具链:内置对 uv、ruff 等工具的调用约定;日志通过 farlog,Shell 流程通过 funshell。
  • Git 工作流:pull / push / tag 等与远程协作;push 在提交阶段优先用 aicommits 生成说明,未安装时自动回退到默认信息。
  • 失败即中止:任一 shell 步骤返回非 0 即抛出 ShellCommandError 并以非 0 码退出,构建失败不会继续推送或打标签。
  • 维护命令:clean 与 clean-history 会改写 Git 状态或强制重写远程历史,使用前请确认团队规范与备份策略。

打包支持的项目类型

funbuild 运行时会按下表顺序(从上到下)依次探测仓库根目录,命中第一个匹配的类型即停止;判定逻辑见 src/funbuild/core/registry.py。

优先级 构建类型 判定条件 适用项目
1 SubmoduleWorkspaceBuild 根目录同时存在 apps/ 目录与 scripts/funbuild.toml <product>-dev 编排仓库:apps/ 下每个 app 是独立仓库的 git submodule,仓库自身没有可构建产物,见下方专节
2 UvNpmHybridBuild 同时满足 UVBuild 与 NpmFrontendBuild 的判定条件 同一仓库里既是 UV 管理的 Python 包、又带前端 package.json 的混合项目(一条命令串联两侧构建/安装/发布)
3 UVBuild 根目录存在 pyproject.toml 且含 [project] 段 使用 uv / PEP 621 标准 pyproject.toml 的现代 Python 包(含 extbuild/、exts/ 子包)
4 PoetryBuild pyproject.toml 存在且 [tool.poetry].version 有效 使用 Poetry 管理版本与依赖的 Python 项目
5 PypiBuild 根目录存在 script/__version__.md 早期遗留的 PyPI 发布脚本项目
6 FlutterBuild pubspec.yaml 存在且 dependencies.flutter.sdk == flutter Flutter 应用/插件项目
7 NpmFrontendBuild 存在 package.json(含 extbuild/ 等子目录的多包场景) npm / pnpm / yarn 管理的纯前端项目
8 VersionFileBuild 根目录存在纯文本 VERSION 文件 没有 pyproject.toml / package.json、无需真正构建的仓库(如 Shell 脚本仓库),仅借用 upgrade / push / tag 的版本与 Git 流程
9 EmptyBuild 兜底,永远匹配 未识别到任何版本清单的仓库;upgrade、build、tag 均为空操作,仅保留提示日志

<product>-dev 提交工作区 (SubmoduleWorkspaceBuild)

面向 apps/<name> 下每个 app 都是独立仓库 git submodule 的编排仓库(配套 submodule-workspace-governance 技能约定的目录结构)。这个仓库本身没有可构建产物,scripts/funbuild.toml 里的 version 是分发给所有 app 的共享版本号,而不是每个 app 各自维护。

# scripts/funbuild.toml
version = "1.0.0"
packages = ["funtrack"]   # 可选:这些依赖在每个 app 构建前会被升级到最新版

funbuild build 在这类仓库上依次执行:

  1. pull 当前仓库,递增共享 version。
  2. 遍历 apps/ 下每个已初始化的 submodule:跳过结构上是嵌套 <something>-dev 工作区的 app(自己也有 apps/ + scripts/setup.sh,由它自己的发布节奏管理,不会被递归进入);其余 app 依次切到跟踪分支、git pull、把 packages 里配置的依赖升级到最新版(按 app 目录下存在的清单文件分派:pyproject.toml → uv add <pkg>@latest;package.json → 按 pnpm-lock.yaml/yarn.lock/默认 npm 自动选择 pnpm add / yarn add / npm install --save;pubspec.yaml → dart pub add <pkg>),再转发 funbuild build --version <共享版本号>。
  3. 统一 push、打 v{version} 标签一次,使所有 submodule 指针更新落成一个提交。

Flutter 项目 (FlutterBuild)

版本号沿用 pubspec.yaml 的 major.minor.patch+buildNumber 惯例:upgrade 按 128 进制递增 major.minor.patch,同时把 +buildNumber 单独 +1(应用商店要求构建号严格递增,不与主版本号混在一起处理)。

默认命令:

阶段 默认命令
构建 flutter pub get + flutter build apk --release + flutter build web --release
安装 无(本地一般没有可安装的产物形态)
发布 经 funpub 上传到私有通用仓库(--repo-name funpackage):apk 直传,web 产物先打包成 zip 再传,远端路径为 flutter/{pubspec name}/apk 与 flutter/{pubspec name}/web
清理 flutter clean

可在 pubspec.yaml 中加一段 funbuild: 来覆盖任意阶段(字符串或字符串数组均可,数组会依次执行):

funbuild:
  build: flutter build ios --release        # 或写成数组: [flutter build apk, flutter build appbundle]
  install: flutter install
  publish: curl -T build/app/outputs/flutter-apk/app-release.apk -u "$ARTIFACT_USER:$ARTIFACT_PASS" https://packages.example.com/generic/demo/app-release.apk
  cleanDirs: [build, .dart_tool]

默认发布走 funpub upload,仓库固定为 funpackage(阿里云 Packages generic 仓库);账号、地址等凭据不经 funbuild 之手,需提前用 funsecret write ... funpub aliyun generic funpackage ... 配置好,funbuild 只负责拼装 funpub upload 命令,不接触任何凭据。如果你的团队使用别的制品仓库(自建 Nexus 等)或需要不同的 repo-name,在 funbuild.publish 里写你自己的上传命令即可完全接管这一步,同样能接入 funbuild build 的完整流水线。

系统要求

  • Python 3.10+
  • Git(版本管理与标签推送)
  • 可选:aicommits(npm install -g aicommits)。只有在不传 message 时才会调用它生成提交信息;没装或调用失败则回退到默认信息 chore: 更新项目文件。显式传了 message 就直接用该值,不走 aicommits。不影响流程。
  • Flutter 项目需要本机装好 flutter 命令并加入 PATH;funbuild 本身只负责拼装 flutter 命令并不校验其可用性。
  • Flutter 项目的默认发布步骤需要安装 funpub(pip install funpub),并提前用 funsecret 配置好 funpackage 仓库的凭据,否则 funpub upload 会失败。

安装

从 PyPI 安装

pip install funbuild

从源码安装

git clone https://github.com/farfarfun/funbuild.git
cd funbuild
pip install .

使用 uv 时,可在克隆后执行 uv sync 或 uv pip install -e . 进行可编辑安装。

命令一览

在项目根目录执行(入口由 pyproject.toml 的 [project.scripts] 注册为 funbuild):

命令 参数 作用
upgrade --version(默认不传=自动递增) 版本自增(或写入指定版本号)并写回各清单文件
latest-deps — 把 latest-packages 里的依赖下界抬到最新版(不构建、不发布,用于单独验证配置)
pull — git pull
push target(位置参数,仅接受 all)
--message / -m(默认不传)
--batch-size(默认 20)
按文件修改时间从旧到新分批提交,最后统一推送;传 all 时先依次 push 每个 submodule
install — 构建 + 安装到当前环境 + 清理产物
build message(位置参数,默认不传)
--version(默认不传=自动递增)
完整发布流水线,见下
release 同 build build 的别名,行为完全一致
tag — 打 v{version} 标签并推送
clean — 重建 Git 索引以应用新的 .gitignore(会产生一次提交)
clean-history — 破坏性:删除全部标签与提交历史并强推远程

命令名中的下划线会被 typer 转成连字符,因此是 clean-history 而非 clean_history。

--message / message 不传时为 None:此时优先交给 aicommits 生成提交信息,未安装 aicommits 才回退到默认信息 chore: 更新项目文件(定义在 src/funbuild/core/util.py 的 DEFAULT_COMMIT_MESSAGE)。传了值则必须符合 SPEC §10 的 <类型>: <中文描述> 格式,否则在任何改动发生之前就以非 0 退出码中止。

版本

funbuild upgrade

自增规则为 128 进制进位:patch 满 128 向 minor 进位,minor 满 128 向 major 进位。

1.6.54  → 1.6.55
1.6.127 → 1.7.0
1.127.127 → 2.0.0

版本号会写回根 pyproject.toml,并同步到仓内所有带 version 字段的 pyproject.toml、package.json 与 pubspec.yaml(含 extbuild/ exts/ 子目录)。非三段版本按缺位补 0 处理(1.0 视作 1.0.0);1.0.0rc1 这类预发布后缀会被丢弃并打印告警。以 FlutterBuild 为主构建类型时例外:pubspec.yaml 自己的 +buildNumber 每次 upgrade 单独 +1,不受该丢弃规则影响。

需要写入指定版本号(而非自动递增)时,给 upgrade 或 build 传 --version:

funbuild upgrade --version 2.0.0

Git

funbuild pull

# 默认每 20 个文件一次提交
funbuild push

# 自定义每个提交的文件数
funbuild push --batch-size 50

# 指定提交信息(未安装 aicommits 时生效);注意这里是选项而非位置参数。
# 信息必须是 `<类型>: <中文描述>`,英文描述会被校验直接拒绝。
funbuild push --message "fix: 修复拼写"

# 先依次 push 每个 submodule,再 push 当前仓库
funbuild push all

push 会先执行 git reset 清空暂存区再按批次重新 add,已手工 git add 的内容会被一并纳入分批提交。

构建与发布

# 完整流水线
funbuild build

# release 是 build 的别名,两者完全等价
funbuild release

# 仅构建并安装到当前环境,不发布、不推送
funbuild install

build 依次触发:pull → upgrade → 抬依赖下界 → 清理 → 构建 → 安装校验 → 发布 → 清理 → push → tag。实际命令序列取决于选中的 Build 类型。任一步失败会立即中止,不会继续 push 或打标签。

让某个依赖每次发版都取最新

组织内部包之间(如 funflix-api 依赖 funflix)常常希望每次发版都带上最新的上游。只靠发版时的 rm -rf uv.lock && uv lock 是不够的:那只影响本仓库构建时解析到的版本,发布出去的 wheel metadata 仍写着 pyproject.toml 里那个早已过期的下界,而下游 pip install -U funflix-api 默认 --upgrade-strategy only-if-needed,已装的旧 funflix 满足旧下界就不会被升上来。

在被依赖方的仓库里声明:

# funflix-api/pyproject.toml
[project]
dependencies = ["funflix>=1.0.0"]

[tool.funbuild]
latest-packages = ["funflix"]

此后每次 funbuild build 都会在构建之前:向 index 查询 funflix 当前最新版本(走 uv pip compile --no-deps --refresh-package funflix,因此自动沿用本仓库 [[tool.uv.index]] 配置的私有源,并绕过 uv 的 index 缓存——上游往往是几秒前才发出去的),把 dependencies 里的下界改写为 funflix>=<最新版> 并写回 pyproject.toml,改动随本次发布的 push 一起提交。[project.optional-dependencies] 与 [dependency-groups](含 extbuild/ exts/ 子包的 pyproject.toml)同样覆盖。

名单里的包如果在上述任何一处依赖声明里都还没出现过,会按最新版本追加到根 pyproject.toml 的 [project].dependencies(dependencies 键不存在时一并创建):

# 改写前
[project]
name = "funflix-api"
dependencies = ["requests>=2"]

[tool.funbuild]
latest-packages = ["funflix"]

# 改写后
dependencies = ["requests>=2", "funflix>=1.9.0"]

不补上这条配置就等于白写:包不在依赖里,既进不了 wheel metadata,也不会被 uv lock 解析。两点例外:

  • 本仓库自己的包名不补——自己依赖自己会让 uv 直接解析失败。
  • 只认根 pyproject.toml 里的那份名单。<product>-dev 编排仓库 scripts/funbuild.toml 的 packages 仍会被用来抬下界,但不会被补进 dependencies:那是「这条链上要发哪些包」的清单,不是「本仓库依赖哪些包」,照搬会给编排仓库凭空加上一堆它并不依赖的包。根 pyproject.toml 没有 [project] 表时同样不补,只记一条告警——凭空造出 [project] 只会生成一份缺 name / version 的残缺元数据。

改写只动版本下界,调用方刻意写下的其它信息一字不动:

原声明 最新版为 1.9.0 时
funflix funflix>=1.9.0
funflix>=1.0.0 funflix>=1.9.0
funflix[all]>=1.0,<2 funflix[all]>=1.9.0,<2
funflix>=1.0,!=1.5.0 funflix>=1.9.0,!=1.5.0
funflix>=1.0; python_version>="3.11" funflix>=1.9.0; python_version>="3.11"
funflix @ https://example.com/funflix.whl 不改动(来源由调用方显式指定,不是 index 上的版本)

即 >= / > / == / ~= 跟着最新版走,< / <= / != / === 原样保留。<product>-dev 编排仓库无需重复配置,scripts/funbuild.toml 里已有的 packages 会被当作同一份名单读取。

要在真正发版之前确认配置写对了、私有源也解析得通:

funbuild latest-deps   # 只改写 pyproject.toml,不构建、不发布、不提交

几点需要注意:

  • 约束里不要留上界。写成 funflix>=1.0,<2 时,<2 会被保留,下游永远拿不到 2.x。要「永远最新」就只写 funflix 或 funflix>=x。

  • 发布顺序由调用方保证。funflix 必须先发完,funflix-api 才能解析到它的新版本。两者本来就该一起发时,更合适的做法是建一个 <product>-dev 编排仓库交给 SubmoduleWorkspaceBuild,一条 funbuild build 按顺序发完整条链。

  • 私有 index 必须让 uv 看得见。查询走 uv pip compile,它只认 uv 自己的 index 配置:仓库 pyproject.toml 里的 [[tool.uv.index]],或 ~/.config/uv/uv.toml 里的全局配置(凭据可放 ~/.netrc)。~/.pypirc 不算——那里的 repository 是 uv publish 用的上传端点,与解析用的 simple index 不是同一个 URL,funbuild 不会拿它去猜。只发在私有源上的包,在没配 index 的仓库里会解析失败。

    [[tool.uv.index]]
    name = "packages-pypi"
    url = "https://packages.aliyun.com/<id>/pypi/<repo>"
    
  • 解析不出最新版本(私有源没配或不可达、包名写错、该包所有版本的 requires-python 都不匹配当前解释器等)时会抛 LatestDependencyError 直接中止发布,不会沿用旧下界继续发出一个钉着过期上游的包。报错里带上 uv 自己的输出、工作目录和命令,便于直接定位。

Poetry 的 [tool.poetry.dependencies] 表形式暂不在覆盖范围内,目前只处理 PEP 621 的 [project] 依赖数组与 PEP 735 的 [dependency-groups]。

维护类(高风险)

funbuild clean          # 重建索引,使新增的 .gitignore 规则生效
funbuild clean-history  # 抹掉全部历史与标签并强推,不可恢复且无二次确认

发布凭据

uv publish 的凭据优先读取 UV_PUBLISH_TOKEN / UV_PUBLISH_USERNAME / UV_PUBLISH_PASSWORD / UV_PUBLISH_URL 环境变量;某个变量未设置时,才用 ~/.pypirc 里对应的值补齐(已设置的环境变量不会被 ~/.pypirc 覆盖)。服务器名的选取顺序为:pyproject.toml 中 [[tool.uv.index]] 的 name > ~/.pypirc 里 [distutils].index-servers 的首项 > 默认 pypi。

[distutils]
index-servers = pypi

[pypi]
username = __token__
password = pypi-AgEIcHl...

凭据以 UV_PUBLISH_TOKEN / UV_PUBLISH_USERNAME / UV_PUBLISH_PASSWORD / UV_PUBLISH_URL 环境变量传给 uv,不会出现在命令行参数中(否则完整命令行会通过进程表对本机所有用户可见)。

CI 环境可以不放 .pypirc,直接导出这些环境变量即可:

export UV_PUBLISH_TOKEN=pypi-AgEIcHl...
funbuild build

错误处理

所有 shell 步骤经 run_checked() 执行,退出码非 0 即抛 ShellCommandError,进程以非 0 码退出。这意味着 funbuild build 在构建或发布失败时不会再继续 push 和 tag,可直接用于 CI 的失败判定。

配置说明

  • Python 项目:在根目录 pyproject.toml 中维护 [project].version 与依赖;UV 类构建会读写该版本并同步到其它清单。可选的 [tool.funbuild].latest-packages 用于指定「每次发版取最新」的依赖,见上方「让某个依赖每次发版都取最新」。
  • 纯前端 / 子包:在对应 package.json 中可使用 funbuild 字段(对象或 true)扩展行为(例如自定义 build 命令、cleanDirs 等),具体逻辑见源码中 NpmFrontendBuild。
  • Flutter 项目:在 pubspec.yaml 中可使用 funbuild 字段自定义 build / install / publish / cleanDirs,具体逻辑见源码中 FlutterBuild;详见上方「打包支持的项目类型」里的 Flutter 小节。

构建类型的判定顺序见上方「打包支持的项目类型」表格及 src/funbuild/core/registry.py 中的注册表 —— 构建类型由仓库布局自动探测,不需要也无法在配置里指定。[tool.funbuild] 目前只认 latest-packages 一个键。

集成组件

  • uv — 包管理与构建
  • ruff — Lint / 格式化(按项目配置使用)
  • typer(typer-slim)— CLI 框架
  • aicommits — 默认与 push 流水线集成的提交信息生成(以本机 CLI 为准)

仓库布局(摘要)

funbuild/
├── src/
│   └── funbuild/
│       ├── core/       # 构建注册与各策略实现
│       └── tool/       # 附加工具入口
├── tests/              # 单元测试
├── pyproject.toml
└── README.md

参与贡献

  1. Fork funbuild
  2. 新建分支并提交变更
  3. 发起 Pull Request

本地开发示例:

git clone https://github.com/farfarfun/funbuild.git
cd funbuild
uv pip install -e .
# 或: pip install -e .

# 跑测试 (pytest 已在 dev 依赖组, uv 会自动装)
uv run pytest -q

# 格式化与静态检查
uvx ruff format .
uvx ruff check . --fix

许可证

本项目以 MIT 许可证 发布。

链接

维护者

若 funbuild 对你有帮助,欢迎点个 Star。


关于 farfarfun

farfarfun 是一个专注于实用工具库的开源组织, 涵盖云存储、数据处理、AI、多媒体与开发工具链等方向。

本项目基于 MIT 协议开源。

Metadata

Release files for funbuild 1.6.87

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for funbuild 1.6.87
File Interpreter ABI Platform
funbuild-1.6.87-py3-none-any.whl Python 3 none any Details

Release files / funbuild-1.6.87-py3-none-any.whl

Download URL funbuild-1.6.87-py3-none-any.whl
Size 61.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9e864fff76e0df1bd58079ebaeeadd9d28465981094d18695f0169c46a0d2077
BLAKE2b-256 checksum
How to use checksums
2eabc507e40dd1df8c10c4bdff35a4715d25c3727f6eb176cf91370fb3b98cd3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

1.6.97

1 release file

1.6.96

1 release file

1.6.95

1 release file

1.6.94

1 release file

1.6.93

1 release file

1.6.92

1 release file

1.6.91

1 release file

1.6.90

1 release file

1.6.89

1 release file

1.6.88

1 release file

This release

1.6.87 This release

1 release file

1.6.86

1 release file

1.6.85

1 release file

1.6.84

1 release file

1.6.83

1 release file

1.6.82

1 release file

1.6.81

1 release file

1.6.80

1 release file

1.6.79

1 release file

1.6.78

1 release file

1.6.77

1 release file

1.6.76

1 release file

1.6.75

1 release file

1.6.73

1 release file

1.6.72

1 release file

1.6.71

1 release file

1.6.69

1 release file

1.6.68

1 release file

1.6.67

1 release file

1.6.66

1 release file

1.6.30

1 release file

1.6.29

1 release file

1.6.28

1 release file

1.6.27

1 release file

1.6.26

1 release file

1.6.25

1 release file

1.6.24

1 release file

1.6.23

1 release file

1.6.22

1 release file

1.6.21

1 release file

1.6.20

1 release file

1.6.19

1 release file

1.6.18

1 release file

1.6.17

1 release file

1.6.16

2 release files

1.6.15

2 release files

1.6.11

2 release files

1.6.10

1 release file

1.6.9

1 release file

1.6.8

1 release file

1.6.7

1 release file

1.6.6

1 release file

1.6.5

1 release file

1.6.4

1 release file

1.6.3

1 release file

1.6.2

1 release file

1.6.1

1 release file

1.6.0

1 release file

1.5.99

1 release file

1.5.98

1 release file

1.5.97

1 release file

1.5.96

1 release file

1.5.95

1 release file

1.5.94

1 release file

1.5.93

1 release file

1.5.92

1 release file

1.5.91

1 release file

1.5.90

1 release file

1.5.89

1 release file

1.5.88

1 release file

1.5.87

1 release file

1.5.86

1 release file

1.5.84

1 release file

1.5.83

1 release file

1.5.82

1 release file

1.5.81

1 release file

1.5.80

1 release file

1.5.79

1 release file

1.5.75

2 release files

1.5.74

2 release files

1.5.73

2 release files

1.5.72

2 release files

1.5.71

2 release files

1.5.70

2 release files

1.5.68

2 release files

1.5.66

2 release files

1.5.65

2 release files

1.5.64

2 release files

1.5.63

2 release files

1.5.62

2 release files

1.5.61

2 release files

1.5.55

2 release files

1.5.54

2 release files

1.5.53

2 release files

1.5.51

2 release files

1.5.50

2 release files

1.5.49

2 release files

1.5.48

2 release files

1.5.47

2 release files

1.5.46

2 release files

1.5.45

2 release files

1.5.44

2 release files

1.5.43

2 release files

1.5.32

2 release files

1.5.31

2 release files

1.5.30

2 release files

1.5.29

2 release files

1.5.28

2 release files

1.5.27

2 release files

1.5.26

2 release files

1.5.25

2 release files

1.5.24

2 release files

1.5.23

2 release files

1.5.19

2 release files

1.5.18

2 release files

1.5.17

2 release files

1.5.16

2 release files

1.5.15

2 release files

1.5.14

2 release files

1.5.13

2 release files

1.5.12

2 release files

1.5.11

2 release files

1.5.10

2 release files

1.5.7

2 release files

1.5.6

2 release files

1.5.5

2 release files

1.5.3

2 release files

1.4.23

2 release files

1.4.22

2 release files

1.4.21

2 release files

1.4.20

2 release files

1.4.19

2 release files

1.4.18

2 release files

1.4.17

2 release files

1.4.16

2 release files

1.4.15

2 release files

1.4.14

2 release files

1.4.13

2 release files

1.4.9

2 release files

1.4.8

2 release files

1.4.7

2 release files

1.4.6

2 release files

1.4.5

1 release file

1.4.4

2 release files

1.4.3

2 release files

1.4.2

2 release files

1.4.1

2 release files

1.3.21

1 release file

1.3.19

1 release file

1.3.17

1 release file

1.3.16

1 release file

1.3.15

1 release file

1.3.14

1 release file

1.3.13

1 release file

1.3.8

1 release file

1.3.7

1 release file

1.3.6

1 release file

1.3.4

1 release file

1.3.2

1 release file

1.3.0

1 release file

1.2.29

1 release file

1.2.27

1 release file

1.2.24

1 release file

1.2.22

1 release file

1.2.20

1 release file

1.2.18

1 release file

1.2.15

1 release file

1.2.14

1 release file

1.2.13

1 release file

1.2.11

1 release file

1.2.10

1 release file

1.2.9

1 release file

1.2.8

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page