Publishing is automated by .github/workflows/release.yml using PyPI
Trusted Publishing (OIDC). No API
token or secret is stored in the repository.
On https://pypi.org, sign in and add a pending publisher (Account settings → Publishing → Add a pending publisher) with:
| Field | Value |
|---|---|
| PyPI project name | causalts |
| Owner | bloomberg |
| Repository name | causal-ts |
| Workflow filename | release.yml |
| Environment name | pypi |
Owner is the GitHub org that owns the repository
(github.com/bloomberg/...),
not your PyPI username. The GitHub OIDC token asserts
repository_owner = bloomberg, and PyPI matches it against this value.
In the repository, go to Settings → Environments → New environment, name it
pypi, and add protections:
- Required reviewers — a maintainer must approve before the
publishjob runs (a human gate on every PyPI push). - Deployment branches and tags — restrict to protected tags matching
v*.
- Bump
project.versioninpyproject.toml(e.g.0.25.1→0.25.2) and merge it tomain. Confirm thetestmatrix is green. In the same PR, bump the other version-bearing files — they are not derived frompyproject.tomland go stale silently:CHANGELOG.md— a new section plus the compare links at the bottomdocs/_static/switcher.json— only the stable entry'sname(the label in the dropdown). Itsversionkeys are Read the Docs slugs (stable,latest), not release numbers, so no new entry is needed per releasedocs/conf.py— theannouncementribbon, if the release is worth advertising.claude-plugin/plugin.json— the packaged skill's own version
- Create and publish a GitHub Release whose tag is the version prefixed
with
v(e.g.v0.25.2). The tag must exactly matchpyproject.toml;release.ymlfails the build otherwise. - The workflow runs tests → builds sdist/wheel → smoke-tests the wheel on
Python 3.10–3.14 → waits for
pypienvironment approval → publishes.
Trigger the release workflow manually from the Actions tab
(workflow_dispatch). It runs tests, builds, and smoke-tests the wheel but
skips publishing (the publish job only runs on a release event).
- Python 3.10–3.13 run the full optional-extra profile
(
.[dev,dowhy,tigramite]); Python 3.14 runs the core profile (.[dev]) because DoWhy does not yet advertise 3.14 support. The wheel is still smoke-tested on 3.14. - The existing
v0.25.0GitHub Release predates this workflow and will not trigger it retroactively; the first automated publish isv0.25.1.