feat(api): Add programmatic Python API for custom workflows by bilelomrani1 · Pull Request #1408 · python-semantic-release/python-semantic-release
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: ASemanticReleaseContextdataclass that encapsulates all configuration, with afrom_config_file()factory method for loading from pyproject.tomloperations.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:
-
RuntimeContext inheritance:
RuntimeContextcould extendSemanticReleaseContext, adding only CLI-specific fields (global_cli_options,masker) -
CLI as thin wrapper: Commands like
changelog,version, andpublishcould become thin wrappers that call the core API functions -
Shared config building: The config loading logic in
_from_raw_configmirrorsRuntimeContext.from_raw_configand could be consolidated -
Template rendering:
render_changelogandrender_release_notescurrently import fromcli/changelog_writer.py; this logic could be moved tooperations.pywith the CLI importing from it instead -
Test simplification: Tests could directly instantiate
SemanticReleaseContextwith 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)