Skip to content

Latest commit

 

History

History
200 lines (157 loc) · 9.13 KB

File metadata and controls

200 lines (157 loc) · 9.13 KB

Release process

Every package releases independently. The default path is a coordinated release-all workflow; per-package workflows are for urgent or partial releases.

Normal releases are tag-from-main: each publish creates a tag (<pkg>==<version>) pointing at the release commit on main. Patches are the exception — they are cut from package-release/<pkg>/v* branches created lazily from a release tag, and their tags point at the backport branch, not main.

Releases are driven by GitHub Actions workflows. They handle version bumps, changelog generation (via towncrier), tagging, PyPI publishing, GitHub releases, and changelog updates on main.

Version model

Packages use the OpenTelemetry beta versioning format MAJOR.MINORbN (e.g. 1.0b0). version.py carries a .dev suffix during development (e.g. 1.0b0.dev); the prepare workflow drops it at release time.

Version cadence on main:

  • The post-release bump advances the minor automatically. After each successful release of X.YbN, the release workflow opens a PR bumping main to the next unreleased minor X.(Y+1)b0.dev. main therefore always sits on an unreleased minor line, and the next release from main is that minor.
  • Patches come from release branch. To patch an already-released version you cut a backport branch from its tag (see Backport patch) — this is the same procedure whether the release is the latest or an older one.
  • Major bumps are maintainer-led. Trigger the Bump package major version workflow (documented below) when you're ready to move a package to the next major line. The Bump package minor version workflow exists to jump the minor ahead of a release without shipping; it happens only when a maintainer explicitly asks for it.

Release model

Unlike opentelemetry-python-contrib, we do not maintain a long-lived release branch for every minor. Normal releases tag main directly; patch branches are created on demand from a release tag when patching an already-released version.

opentelemetry-python-contrib This repo
Normal release Long-lived package-release/<pkg>/v* branch Tag on main
Tag target Commit on the release branch Commit on main
Patch a released version Commits + tags on the release branch Branch from the tag (lazy)
Branch sprawl One branch per package per minor Branches only for patches

Bulk release (default)

For releasing every package that has towncrier changelog fragments:

  1. Run the Prepare release workflow against main. Leave the package input empty for the bulk case.
    • Finds packages with fragments under .changelog/.
    • Opens one combined PR on main that drops .dev suffixes and runs towncrier build for each eligible package.
    • Labels the PR release.
  2. Review and merge the prepare PR.
  3. The Release all workflow runs automatically when a labelled prepare PR merges (or trigger it manually against main).
    • Publishes each ready package to PyPI.
    • Creates a GitHub release tag (<pkg>==<version>) on main for each.
    • Opens a PR bumping released packages to the next minor .dev version.

Packages without changelog fragments are skipped during prepare and logged in the workflow output.

Single-package release

Use when only one package needs to ship, or the rest of the workspace is not ready for a bulk release. The version type (patch vs minor vs major) depends on what's currently in version.py on main — see Version model.

  1. Run Prepare release against main and set the package input to the target package. The workflow opens a PR that drops the .dev suffix and runs towncrier build for just that package (still labelled release).
  2. Review and merge the prepare PR.
  3. Either wait for Release all to fire on the merged prepare PR, or run Release package against main for that one package.

Bumping to the next minor or major

The minor advances automatically as the last step of every release (see Version model). Jumping the minor ahead of a release, or moving to the next major line, is a maintainer decision:

Merge the bump PR first, then follow the normal bulk or single-package release flow. Prepare release picks up the new dev version verbatim.

Backport patch (older line)

Patching any already-released version — the latest or an older one — comes from a branch cut from that version's tag.

  1. Create package-release/<pkg>/v<X>.<Y>bx from the <pkg>==<X>.<Y>b<N> tag if it does not exist yet.
  2. Cherry-pick or develop the fix on the branch.
  3. Run Prepare backport patch against the backport branch. Bumps the patch version and runs towncrier build.
  4. Review and merge the prepare PR into the backport branch.
  5. Run Release package against the backport branch.
    • Tags the backport branch and opens a PR copying changelog updates to main.

Pre-existing static ## Unreleased entries

Several packages carry CHANGELOG entries that pre-date towncrier (added before the towncrier marker was inserted). towncrier build does not fold them into the generated release section. Before the first towncrier release of a given package, fold those entries by hand into the new release section produced by towncrier build (or convert them into fragments first). The do-not-edit comment in each CHANGELOG.md flags this.

Adding a new publishable package

When a new package is ready to ship:

  1. Add its name to the packages= list under [release_packages] in eachdist.ini. Packages not listed here are skipped by the release workflows.
  2. Add the package to the dropdown options in the workflow files that offer a package selector: release-package.yml, prepare-release.yml, prepare-backport-patch.yml, bump-package-minor.yml, and bump-package-major.yml.
  3. Create the PyPI project and register two trusted publishers (ManagePublishingAdd a new pending publisher), one for each workflow that publishes. For detailed instructions, refer to PyPI's documentation on Creating a PyPI project with a Trusted Publisher or Adding a Trusted Publisher to an existing PyPI project. Note that creating a pending publisher does not reserve the project name on PyPI:
Field Entry 1 Entry 2
PyPI project name e.g. opentelemetry-util-genai same
Owner open-telemetry open-telemetry
Repository name opentelemetry-python-genai opentelemetry-python-genai
Workflow name release-package.yml release-all.yml
Environment name pypi pypi
  1. Optionally reserve the package name to prevent name-squatting shortly after the introductory PR lands on main by navigating to https://pypi.org/manage/organization/opentelemetry/projects/, scrolling to the bottom (Add project to organization), and using the form.

All packages share the same environment. The first upload from CI activates each publisher.

Troubleshooting

No packages found during Prepare release

At least one publishable package needs a towncrier fragment under .changelog/ (any file other than .gitkeep / .gitignore).

PyPI publish failed mid-workflow

Re-run the release workflow (Release package or Release all). Trusted Publishing only works from GitHub Actions, there is no repo-stored PyPI token for manual twine upload.

If the wheel was built but upload failed, fix the underlying issue (PyPI project missing, trusted publisher misconfigured, environment approval pending) and re-run. The workflow uses skip-existing, so a partial upload is safe to retry.

After a successful PyPI upload, re-running picks up remaining steps (GitHub release tag + follow-up PRs) if those failed.

Version still has a .dev suffix at release time

Merge the prepare PR first. Release workflows require a non-.dev version in version.py.

Out of scope

  • A backport workflow (create backport branches manually from release tags when needed).