Repository navigation
Programmatic Python API for custom release workflows #1407
Description
Activity
- addedfeatureA new feature or a feature requestA new feature or a feature requesttriagewaiting for initial maintainer reviewwaiting for initial maintainer review
on Jan 2, 2026 The undocumented goals of the future are to minimize the command function complexity and instead call an external structure to execute each piece of the workflow. I have not landed on a design yet but that goal changes the core structure of PSR where the CLI functions are only an interface into the grander library.
I find the idea of a context or defined api a bit interesting as that would define a more rigid exposed contract to the user as opposed to normal python imports (available today because of how python works). Which is limiting to development on my side as I'm not sure what 3rd party scripts are using. So this sounds more ideal.
In my fork you will find a few different branches that redefine the core structure like a project class that helps to facilitate caching, increase performance, and reduce duplication of actions. I do plan to separate a stamp files command, a separate print out release notes command and rearchitect the config. Other goals are to convert to all composite object structures which separate out which HVCS or parsers used and enable more custom plugins. These are all tangential to your proposal but will significantly impact work as me moving around files and moving functions will be conflicting.
I'll be slow to respond as I'm busy today but less busy this weekend.
I don't want to say stop working, I just feel bad that there is conflicting efforts. Most people don't put the work in that you are and just ask for new features. If you find something that you want to work on that I haven't started and you don't anticipate conflicts then let me know and make it a reality.
Hi @codejedi365, thanks for the thoughtful response and for sharing context on the v11 plans.
I want to clarify that the burst of issues/PRs isn't meant to pressure you 😁 I'm actively exploring this space, that's on my plate right now, and wanted to capture everything while it's fresh. The goal is to let you batch reviews whenever you have time, so we can work asynchronously. No rush on your end.
To give you the full picture: I'm instrumenting a monorepo with multiple independently-released packages. Our release process needs to be atomic: if any step fails, the whole transaction rolls back (no side effect ie no tag pushed, no artifacts published, no notifications sent, except on a dev channel to log the release error). The workflow looks like:
- Manual trigger: we have a Github action workflow with a
manual_dispatchtrigger to launch release - Determine next version: analyze commits, compute the next semantic version
- Create tag: we use dynamic versioning inferred from VCS tags (setuptools-scm style), so the tag must exist before building. This relates to Support for VCS tag-based dynamic versioning during build #1318 PSR currently builds before tagging, which doesn't work for our setup. But I can work around it today by decomposing into multiple CLI calls (something like
semantic-release version --skip-build, thenuv build, then the rest), so no big deal, that's not actually why I need more flexibility - Build wheel
- Build Docker image packages the wheel into a container
- Run integration + E2E tests validates the container before release
- Publish if all tests pass: push wheel to private PyPI registry, push image to container registry, send Slack notification with release notes to consumers
- Rollback on failure if any step fails: delete the local tag (before it's pushed), send error notification to a dev Slack channel, exit with error
The key requirement is that steps 1-5 must succeed before any persistent external side effects (pushing tag, publishing artifacts, notifying users). This kind of staged, transactional release process is very custom, I'm not expecting PSR to support this out of the box, but would be straightforward with a programmatic API that exposes the building blocks to me.
I think this pattern (transactional releases with custom validation gates between steps) is broadly useful beyond my specific environment.
On the other PRs
The supporting features I submitted stem from the same project:
- feat(changelog): Support remote git repositories as template sources #1404 We share changelog/release notes templates across repos, so storing them in a central GitHub repo and pointing to them is cleaner than duplicating in each project
- fix(changelog): support custom Jinja extensions in release notes templates #1405 Our templates use custom filters
- feat(changelog): Add
changelog.output_dirconfiguration option #1406 In our monorepo, I prefer changelogs written at the package root, not the repo root
These are smaller, more self-contained changes that are less likely to conflict with the v11 refactoring. Happy for you to prioritize these for review if that's easier whenever you have time!
On the API design
I'm completely flexible here. My proposal was the most immediate, minimal-change extraction I could think of, but if you have a more comprehensive design in mind for v11, I'm happy to abandon my PR entirely and contribute to your approach instead. I can wait for you to document the v11 architecture and then help implement pieces that align with my needs if that can help, just let me know.
A few options that work for me:
- You document the v11 vision when you have time, and I contribute to areas that overlap with my needs if you're open to it
- I focus on the smaller PRs (feat(changelog): Support remote git repositories as template sources #1404, fix(changelog): support custom Jinja extensions in release notes templates #1405, feat(changelog): Add
changelog.output_dirconfiguration option #1406) which seem lower-conflict, while the API discussion continues. If you find time to review them this weekend or whenever, that would be awesome - You point me to specific areas where help would be useful
Let me know what works best for you. I'm here to contribute, not to create extra work 😆
- Manual trigger: we have a Github action workflow with a
- addedconfirmedPrevent from becoming stalePrevent from becoming staleand removedtriagewaiting for initial maintainer reviewwaiting for initial maintainer review
on Apr 4, 2026 It has been 90 days since the last update on this confirmed issue. @python-semantic-release/team can you provide an update on the status of this issue?
- addedneeds-updateNeeds status update from maintainersNeeds status update from maintainers
on Jul 3, 2026
Feature request
Description
Python-semantic-release operates primarily as a CLI tool, which works well for standard CI/CD pipelines but limits integration with custom Python scripts and applications. This proposal adds a programmatic Python API allowing users to import and call semantic release functionality directly from code.
The API would expose a
SemanticReleaseContextconfiguration object and functions for building release history, rendering changelogs and release notes, and computing the next version.Use cases
Teams often want to post release notes to Slack, Discord, or other services after a release. Today this requires parsing CLI output or reading generated files. A programmatic API would let them call
render_release_notes()and pass the result directly to their notification client.Monorepo maintainers sometimes need custom release coordination beyond what the CLI supports. A programmatic API lets them orchestrate releases with Python scripts, calling core functions in whatever order their workflow requires.
Testing release configuration currently means mocking subprocess calls. With a programmatic API, teams can import functions directly and write unit tests that verify their commit parser produces expected version bumps.
Possible implementation
A
SemanticReleaseContextclass would encapsulate configuration, loadable frompyproject.tomlor constructed with explicit parameters:Core functions would accept the context and return Python objects:
Existing approaches in the JS ecosystem
The JavaScript semantic-release package provides a programmatic API returning a result object with release information, commits, and changelog content.
Nx Release programmatic API exposes separate functions for versioning, changelog generation, and publishing through their programmatic API, allowing custom logic between phases.
Both recognize that releases involve special cases a CLI cannot fully address. A programmatic API lets users build exactly what they need.
Invoking the CLI via
subprocess.run()is possible but has drawbacks: string parsing is fragile, intermediate results are inaccessible, exceptions become exit codes, and testing is harder. A native Python API provides proper types, meaningful exceptions, IDE integration, and composability with other tools.