This document explains the release process for xbbg, intended for AI agents and maintainers.
xbbg uses semantic versioning (SemVer) with Python package versions automatically derived from git tags via setuptools_scm. The JS package families use the same version numbers, stamped during release workflows: vX.Y.Z for the npm publish flow and js-vX.Y.Z for the GitHub-only JS asset flow. The build system is setuptools + setuptools-rust + setuptools_scm for Python and npm package stamping for JS.
{major}.{minor}.{patch}[-{pre-release}]
Examples:
- 0.12.1 # Stable release
- 0.12.1b1 # Beta pre-release
- 0.12.1a1 # Alpha pre-release
- 0.12.1rc1 # Release candidate
Dev builds (untagged commits) automatically get versions like 0.12.1.dev268+g84acdcf.d20260219.
| Component | Package | Purpose |
|---|---|---|
| Build backend | setuptools |
Python packaging |
| Rust extension | setuptools-rust |
Compiles PyO3 extension (xbbg._core) |
| Version | setuptools_scm |
Derives Python package versions from git tags |
| JS package version | js-xbbg/scripts/stamp-version.ts |
Stamps @xbbg/core wrapper/platform package versions for JS release workflows |
| Build tool | uv |
Fast package manager and build frontend |
Ensure all changes are documented under the [Unreleased] section:
## [Unreleased]
### Added
- New feature description
### Changed
- Modified behavior description
### Fixed
- Bug fix descriptionCategories (use only what applies):
Added- New featuresChanged- Changes in existing functionalityDeprecated- Soon-to-be removed featuresRemoved- Removed featuresFixed- Bug fixesSecurity- Vulnerability fixes
git add CHANGELOG.md
git commit -m "docs(CHANGELOG): prepare for vX.Y.Z release"
git pushGo to GitHub Actions > Bump Version and Create Release > Run workflow
Parameters:
| Parameter | Description | Options |
|---|---|---|
bump_type |
Version increment | major, minor, patch |
pre_release |
Pre-release type | none, alpha, beta, rc |
pre_number |
Pre-release number | 1, 2, 3, etc. |
create_release |
Create GitHub release | true, false |
Examples:
0.12.1→0.13.0: bump_type=minor, pre_release=none0.12.1→0.12.2: bump_type=patch, pre_release=none0.12.1→0.12.2b1: bump_type=patch, pre_release=beta, pre_number=1
- Version Calculation: Computes new version from current tags
- Changelog Update: Renames
[Unreleased]to[version] - date - README Release Sync: Updates the
README.mdlatest-release marker block to the new version/tag - Git Tag: Creates
vX.Y.Ztag and pushes it - GitHub Release: Creates release with notes from CHANGELOG
- PyPI Publish: Tag push triggers
pypi_upload.yml— builds wheels and publishes via OIDC trusted publishing - npm Publish: Tag push triggers
npm-publish.yml— builds platform-native@xbbg/core-*packages, stamps JS versions from the git tag, and publishes@xbbg/coreto npm via trusted publishing - Release Assets: Wheels and sdist are attached to the GitHub release
| Workflow | File | Purpose |
|---|---|---|
| CI | ci-rust.yml |
Rust lint, clippy, build, test (Linux + Windows) |
| Docker | ci-docker.yml |
Build CI Docker image |
| Workflow | File | Purpose |
|---|---|---|
| Release | pypi_upload.yml |
Build wheels (Linux + Windows × Python 3.10–3.14), sdist, publish to PyPI, attach to GitHub release |
| Release | npm-publish.yml |
Build and publish stable @xbbg/core prebuilt native packages for supported platforms, then publish the @xbbg/core wrapper and @xbbg/langgraph package via npm trusted publishing |
npm-publish.yml is tokenless: the publish job uses GitHub OIDC (id-token: write) from GitHub-hosted runners and npm CLI >=11.10.0. Configure this once on npmjs.com for each published package before relying on tag-push publishing:
| npm package | Publisher | GitHub org/user | Repository | Workflow filename | Environment |
|---|---|---|---|---|---|
@xbbg/core |
GitHub Actions | alpha-xone |
xbbg |
npm-publish.yml |
leave blank |
@xbbg/core-linux-x64 |
GitHub Actions | alpha-xone |
xbbg |
npm-publish.yml |
leave blank |
@xbbg/core-win32-x64 |
GitHub Actions | alpha-xone |
xbbg |
npm-publish.yml |
leave blank |
@xbbg/core-darwin-arm64 |
GitHub Actions | alpha-xone |
xbbg |
npm-publish.yml |
leave blank |
@xbbg/langgraph |
GitHub Actions | alpha-xone |
xbbg |
npm-publish.yml |
leave blank |
GitHub environment npm is intentionally not required because current repository credentials cannot create it. Add an environment only if an admin wants reviewer-based release approvals; if you do, update both the workflow environment: and all npm trusted publisher entries to the exact same environment name.
After a successful OIDC publish, set each package's npm Publishing access to require 2FA and disallow tokens, then revoke any temporary publish tokens.
npm-publish.yml intentionally publishes only stable npm versions (vX.Y.Z). Python-style pre-release tags such as vX.Y.Zb1 still trigger the workflow glob but are skipped because they are not valid npm semver versions for this package family.
| Workflow | File | Purpose |
|---|---|---|
| Bump Version | semantic_version.yml |
Calculate version, update CHANGELOG and README release marker, create tag + GitHub release |
| JS GitHub Release | js_github_release.yml |
Build, validate, and attach GitHub-only JS tarballs for @xbbg/core on js-vX.Y.Z |
| npm Publish Retry | npm-publish.yml |
Manual retry of trusted npm publishing for a stable vX.Y.Z version |
Use this workflow when you want GitHub release assets for the JS packages without npm publishing.
Go to GitHub Actions > JS GitHub Release > Run workflow
Parameters:
| Parameter | Description |
|---|---|
version |
Package version to stamp into the JS tarballs; the workflow creates or reuses the js-vX.Y.Z tag |
notes |
Optional maintainer notes appended to the GitHub release body |
draft |
Create the GitHub release as a draft |
What happens automatically:
- Validates the requested version and targets the current workflow commit
- Creates or reuses the
js-vX.Y.Ztag without touching the globalvX.Y.Zrelease flow - Builds native assets for the supported JS targets
- Stamps both JS package families with the selected version
- Packs and validates the GitHub release tarballs
- Attaches the tarballs to a GitHub release on
js-vX.Y.Z
Attached artifacts (currently supported):
@xbbg/corewrapper +darwin-arm64,linux-x64,win32-x64platform tarballs
Docker images are not part of this release. CI images stay in GHCR and do not bundle Bloomberg SDK files.
Use this workflow only when a stable npm release needs to be retried after the canonical vX.Y.Z tag flow. Do not use it for GitHub-only JS assets; use js_github_release.yml and a js-vX.Y.Z tag for that case.
Go to GitHub Actions > Publish JS Packages > Run workflow.
Parameters:
| Parameter | Description |
|---|---|
version |
Stable npm version/tag to publish, such as v1.2.3; pre-release forms are rejected for npm publishing |
What happens automatically:
- Validates the stable semver version and skips non-npm pre-release tags from the
v*trigger - Builds the supported native platform packages (
linux-x64,win32-x64,darwin-arm64) - Installs JS package dependencies before stamping package versions so
package-lock.jsonstays consistent - Runs a packed-install smoke test before publishing
- Publishes missing packages in dependency order: platform packages first, then
@xbbg/core - Uses npm trusted publishing/OIDC with provenance from GitHub Actions; no npm token is required for normal releases
The npm Trusted Publisher configuration must match the workflow filename exactly: npm-publish.yml, repository xbbg-org/xbbg, and blank environment unless a matching GitHub environment is intentionally added.
# Install the SDK into vendor/blpapi-sdk/ and let the build discover it
bash ./scripts/sdktool.sh
# Windows PowerShell: .\scripts\sdktool.ps1
# Build wheel (includes Rust extension)
uv build
# Build sdist only (no Rust compilation)
uv build --sdist# Latest release tags
git tag --sort=-version:refname | head -5
# Local dev version (from setuptools_scm)
python -c "from setuptools_scm import get_version; print(get_version())"
# Installed package version
python -c "import xbbg; print(xbbg.__version__)"pip index versions xbbg| Branch | Purpose |
|---|---|
main |
v1.x development (Rust-backed stable line) |
release/0.x |
v0.x maintenance releases (pure-Python stable line) |
feat/* |
New features (PRs to main) |
fix/* |
Bug fixes (PRs to main or release/0.x) |
chore/* |
Maintenance tasks |
Note: When releasing from
release/0.x, the downstreamupdate-readmeandupdate-indexworkflows will targetmainby default. Review and revert any unintended changes tomainafter arelease/0.xrelease.
- Delete merged branches
- Update CHANGELOG.md on main
- Trigger release workflow when ready
- Check workflow logs in GitHub Actions
- Common issues:
- Empty CHANGELOG
[Unreleased]section (blocked by validation) - Version already exists on PyPI
- Bloomberg SDK download URL changed
- Rust compilation error
- Empty CHANGELOG
PyPI rejects duplicate versions. To fix:
- Increment pre-release number (e.g.,
b3→b4) - Or fix issues and bump patch version
- Ensure
BLPAPI_ROOTpoints to the Bloomberg SDK directory (must containinclude/andlib/) - Ensure Rust toolchain is installed (
rustup show) - For bindgen issues, set
LIBCLANG_PATH(see.cargo/config.tomlcomments) - CI uses pregenerated bindings (
BLPAPI_PREGENERATED_BINDINGS) to skip bindgen entirely
When asked to create a release:
- Review pending changes: Read
CHANGELOG.md[Unreleased]section - Check for uncommitted changes: Run
git status - Determine version bump:
- Breaking changes →
major - New features →
minor - Bug fixes only →
patch - Pre-release → add
alpha/beta/rc
- Breaking changes →
- Guide user to GitHub Actions to trigger the
semantic_version.ymlworkflow for the canonicalvX.Y.Zrelease - For GitHub-only JS package assets, guide the user to
js_github_release.ymlwith an explicit version; it builds the supported@xbbg/coreJS tarballs and tagsjs-vX.Y.Z
Do NOT manually:
- Edit version numbers in code for Python releases (managed by
setuptools_scmfrom git tags) - Create
vX.Y.Zgit tags directly (the canonical release workflow handles this) - Reuse
vX.Y.Ztags for JS-only GitHub assets; usejs-vX.Y.Zinstead so the PyPI/npm publish workflows do not trigger - Upload to PyPI manually (OIDC trusted publishing only)
- Upload npm packages manually except for emergency recovery or first-time package seeding; normal npm releases must go through
npm-publish.ymltrusted publishing on a stablevX.Y.Ztag
## [Unreleased]
### Added
- New feature description (#PR_NUMBER)
### Changed
- Modified behavior description (#PR_NUMBER)
### Deprecated
- Feature that will be removed in future versions
### Removed
- Feature removed in this release
### Fixed
- Bug fix description (#ISSUE_NUMBER)
### Security
- Security fix description (CVE if applicable)- Write from the user's perspective ("Users can now..." not "We added...")
- Be specific about what changed and why it matters
- Link to relevant issues/PRs with
(#123)format - Group related changes together
- Mention breaking changes prominently
- Include migration instructions for breaking changes
- Leave the
[Unreleased]section empty - Use vague descriptions ("Various improvements")
- Include internal implementation details users don't need
- Forget to categorize changes
- Leave placeholder text
## [Unreleased]
### Added
- Native Arrow carrier with explicit `backend="native"`, `backend="pyarrow"` for real PyArrow tables, and a Narwhals default that preserves legacy PyArrow-backed behavior when PyArrow is installed (#173)
- Output format control with `Format` enum (long, semi_long, long_typed, long_metadata)
- `bta()` function for Bloomberg Technical Analysis (#175)
- `get_sdk_info()` as replacement for deprecated `getBlpapiVersion()`
### Changed
- All API functions now accept `backend` and `format` parameters
- Internal pipeline uses xbbg native Arrow tables with explicit optional conversion backends
- **BREAKING**: Deprecated `wide` output removed; use `semi_long` or pivot `long` results explicitly
### Deprecated
- `connect()` / `disconnect()` - engine auto-initializes in v1.0
- `getBlpapiVersion()` - use `get_sdk_info()` instead
### Fixed
- Empty DataFrame handling in helper functions with LONG format output (#180)
- Memory leak in streaming subscriptions (#182)## [Unreleased]
- Various bug fixes
- Performance improvements
- TODO: add more details
- Updated some stuff| Type | When to Use |
|---|---|
| alpha | Early testing, API may change significantly |
| beta | Feature complete, testing for bugs |
| rc | Release candidate, final testing before stable |
The release workflow validates:
- Non-empty:
[Unreleased]must have content (workflow fails if empty) - No placeholders: Warns if TODO/FIXME/WIP/TBD detected
- Format check: Warns if standard categories not found
Before triggering a release, ensure:
-
CHANGELOG.md[Unreleased]section is populated with all changes - Changes are categorized correctly (Added, Changed, Deprecated, Removed, Fixed, Security)
- No placeholder text (TODO, FIXME, WIP, TBD) remains
- Issue/PR numbers are referenced where applicable
- Breaking changes are clearly marked