Skip to content

feat(api): Add programmatic Python API for custom workflows#1408

Open
bilelomrani1 wants to merge 1 commit intopython-semantic-release:masterfrom
bilelomrani1:feat/programmatic-api
Open

feat(api): Add programmatic Python API for custom workflows#1408
bilelomrani1 wants to merge 1 commit intopython-semantic-release:masterfrom
bilelomrani1:feat/programmatic-api

Conversation

@bilelomrani1
Copy link

@bilelomrani1 bilelomrani1 commented Jan 2, 2026

Summary

Related issue: #1407

This PR adds a first-class programmatic Python API that allows users to import and use semantic release functionality directly from Python code without going through the CLI.

The API consists of two new modules:

  • context.py: A SemanticReleaseContext dataclass that encapsulates all configuration, with a from_config_file() factory method for loading from pyproject.toml
  • operations.py: Core functions (build_release_history, render_changelog, render_release_notes, compute_next_version)

This enables use cases like posting release notes to Slack, custom monorepo release orchestration, and unit testing release configuration.

Scope

This PR introduces the API surface only. It does not refactor the CLI to use this API internally. The implementation reuses existing internal functions from cli/config.py and cli/changelog_writer.py.

This is intentionally the first in a series of stacked PRs. Keeping the API introduction separate from the internal refactoring makes review easier and allows the API design to be validated before deeper changes are made. Subsequent PRs will refactor the CLI to use this API internally, consolidating duplicated logic. So this PR indeed adds a decent amount of LOC but I'm expecting the future ones to remove a lot of duplicated code.

Future refactoring opportunities

Once this API is validated, the CLI could be refactored to use it internally:

  1. RuntimeContext inheritance: RuntimeContext could extend SemanticReleaseContext, adding only CLI-specific fields (global_cli_options, masker)

  2. CLI as thin wrapper: Commands like changelog, version, and publish could become thin wrappers that call the core API functions

  3. Shared config building: The config loading logic in _from_raw_config mirrors RuntimeContext.from_raw_config and could be consolidated

  4. Template rendering: render_changelog and render_release_notes currently import from cli/changelog_writer.py; this logic could be moved to operations.py with the CLI importing from it instead

  5. Test simplification: Tests could directly instantiate SemanticReleaseContext with mock objects instead of setting up config files or mocking CLI invocations. Unit tests for changelog rendering, version computation, and release history building could call API functions directly, making tests more focused and easier to maintain. We can keep the existing test infra for testing the CLI itself

Example usage

from semantic_release import (
    SemanticReleaseContext,
    build_release_history,
    render_release_notes,
    render_changelog,
    compute_next_version,
)

# Load configuration from pyproject.toml
ctx = SemanticReleaseContext.from_config_file()

# Build release history from git
history = build_release_history(ctx)
print(f"Found {len(history.released)} releases")

# Compute what the next version would be
next_version = compute_next_version(ctx)
current_version = list(history.released.keys())[0]

# Require manual approval for major version bumps
if next_version.major > current_version.major:
    if not confirm_major_release(next_version):
        sys.exit(1)

# Render release notes and post to Slack
notes = render_release_notes(ctx, history, current_version)
slack_client.post_message(
    channel="#releases",
    text=f"*v{current_version}* has been released!\n\n{notes}"
)

# Generate full changelog for documentation site
changelog = render_changelog(ctx, history)
docs_path = Path("docs/changelog.md")
docs_path.write_text(changelog)

PR Completion Checklist

  • Reviewed & followed the Contributor Guidelines

  • Changes Implemented & Validation pipeline succeeds

  • Commits follow the Conventional Commits standard
    and are separated into the proper commit type and scope (recommended order: test, build, feat/fix, docs)

  • Appropriate Unit tests added/updated

  • Appropriate End-to-End tests added/updated

  • Appropriate Documentation added/updated and syntax validated for sphinx build (see Contributor Guidelines)

@bilelomrani1 bilelomrani1 force-pushed the feat/programmatic-api branch from ae6c394 to a568fb1 Compare January 2, 2026 18:52
@codejedi365
Copy link
Contributor

codejedi365 commented Jan 2, 2026

Before you put a significant amount of work into this, let's discuss further in your issue because I've already been working towards this, but a vision for something that you wanna do and I just wanna make sure that we are not duplicating efforts. And creating more merge conflicts than necessary.

@bilelomrani1
Copy link
Author

bilelomrani1 commented Jan 2, 2026

Hi @codejedi365, sure, that was the rationale behind keeping things separate so we can discuss the details. Happy to coordinate. I've opened #1407 with the use cases and proposed API. Would love to see what you've been working on, is there a branch or draft I can look at?
For broader context: I've been looking at instrumenting an internal monorepo with automated semantic release, and PSR looks promising compared to what I've experimented with. I've identified a couple of missing features needed to integrate it into our existing release process, so I'm looking to contribute to help get these merged.

@codejedi365
Copy link
Contributor

Would love to see what you've been working on, is there a branch or draft I can look at?

The main thing to look at is my fork and the branches that exist there but unfortunately I have not documented all the current and future work. Every time I start down the refactor it seems like some other more critical issue is raised from the community so a lot are in partial completion states. I can put in time this weekend and next week to finalize these if you can wait a bit. V11 is attempting to fix many short sided design flaws, eliminate tech debt related to rigid design and prepare for future modularity.

Glad to hear and curious what is missing (besides an API) from your workflow that can be provided to the world community instead of just automating it for your environment? Is this unique to your environment or can the scripts you provide illustrate a larger better release workflow?

Let's move this conversation over to the proposal issue.

@bilelomrani1
Copy link
Author

Moving the detailed discussion to #1407 as suggested. Keeping this PR open for reference, but happy to close it or adapt it based on how the API design discussion evolves.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants