Monorepo Semantic Release Configuration¶
Overview¶
This repository uses Python Semantic Release v10 with monorepo support to independently version and release two packages:
- katana-openapi-client - The main Python API client
- katana-mcp-server - The Model Context Protocol server
Each package can be released independently based on commit scopes, allowing them to evolve at their own pace.
Commit Convention¶
We use conventional commits with scopes to control which package(s) get released:
Client Package Releases¶
Commits affecting the main client:
feat(client): add new Products helper methods
fix(client): resolve pagination edge case
perf(client): optimize retry backoff algorithm
Or commits without a scope (defaults to client):
MCP Server Releases¶
Commits affecting the MCP server:
feat(mcp): add inventory tools
fix(mcp): correct stock level calculation
docs(mcp): update usage examples
Both Packages¶
If you want to release both packages (rare), make two separate commits:
git commit -m "feat(client): add domain helpers"
git commit -m "feat(mcp): add tools using new helpers"
How It Works¶
Configuration Files¶
Root pyproject.toml¶
[tool.semantic_release]
tag_format = "client-v{version}"
commit_message = "chore(release): client v{version}"
# Only processes commits with (client) scope or no scope
katana_mcp_server/pyproject.toml¶
[tool.semantic_release]
tag_format = "mcp-v{version}"
commit_message = "chore(release): mcp v{version}"
# Only processes commits with (mcp) scope
Release Workflow¶
The .github/workflows/release.yml workflow runs on every push to main and performs
two independent semantic-release checks:
-
Client Release (
release-clientjob): -
Checks for commits with
feat(client):,fix(client):, or no scope - Creates tag:
client-v{version} -
Builds and publishes to PyPI as
katana-openapi-client -
MCP Server Release (
release-mcpjob): -
Checks for commits with
feat(mcp):,fix(mcp): - Creates tag:
mcp-v{version} - Builds and publishes to PyPI as
katana-mcp-server
Both jobs run in parallel and are independent.
Versioning Strategy¶
Version Bumps¶
| Commit Type | Example | Version Bump |
|---|---|---|
feat: or feat(scope): |
feat(mcp): add search tool |
MINOR (0.1.0 → 0.2.0) |
fix: or fix(scope): |
fix(client): resolve auth bug |
PATCH (0.1.0 → 0.1.1) |
perf: or perf(scope): |
perf(mcp): optimize queries |
PATCH (0.1.0 → 0.1.1) |
feat!: or feat(scope)!: |
feat(client)!: breaking change |
MAJOR (0.1.0 → 1.0.0) |
Other (docs:, chore:, test:) |
docs(mcp): update README |
NO BUMP |
Current Versions¶
- katana-openapi-client:
0.23.0(tracks main client) - katana-mcp-server:
0.1.0a1(alpha release)
Tag Format¶
- Client tags:
client-v0.23.0,client-v0.24.0, etc. - MCP tags:
mcp-v0.1.0a1,mcp-v0.1.0, etc.
This prevents tag conflicts and makes it clear which package each tag refers to.
Publishing to PyPI¶
Automatic Publishing¶
When semantic-release creates a new version:
- A git tag is created (e.g.,
mcp-v0.1.0a1) - The package is built
- Build artifacts are uploaded
- The
publish-*-pypijob publishes to PyPI using trusted publishing
PyPI Trusted Publishers¶
Both packages are configured with PyPI trusted publishers:
- katana-openapi-client: Publishes from
release-clientjob - katana-mcp-server: Publishes from
release-mcpjob
No API tokens needed - authentication via GitHub OIDC.
Automated Dependency Management¶
MCP Client Dependency Updates¶
The MCP server package depends on the client library. When the client releases a new version, the MCP dependency is automatically updated via the Update MCP Client Dependency workflow.
How it works:
- Trigger: Runs after the main
Releaseworkflow completes successfully - Detection: Checks if a new
client-v*tag was created - Update: Updates
katana-openapi-client>=X.Y.Zinkatana_mcp_server/pyproject.toml - Lockfile: Runs
uv sync --all-extrasto updateuv.lock - PR Creation: Creates a PR with title
feat(mcp): update client dependency to vX.Y.Z - Release: When the PR is merged, the
feat(mcp):commit triggers a new MCP release
Why this matters:
- Ensures MCP always declares compatibility with the latest client
- Prevents users from installing MCP with an outdated client version
- Automates a previously manual process documented in issue #XXX
- Maintains semantic versioning (MINOR bump for dependency updates)
Edge cases handled:
- Skips if dependency is already up to date
- Only runs when client actually released (not on every workflow run)
- Requires workflow success before triggering
- Uses separate PR branch for each client version
Manual override: You can still manually update the dependency if needed (see Dependency Between Packages section).
Manual Release (Emergency)¶
If you need to manually trigger a release:
Option 1: Workflow Dispatch¶
Option 2: Manual Tag (MCP only)¶
The release-mcp.yml workflow can be triggered by pushing a tag:
Examples¶
Example 1: Release MCP Server Only¶
# On branch: feature/add-inventory-tools
git add katana_mcp_server/src/katana_mcp/tools/inventory.py
git commit -m "feat(mcp): implement check_inventory tool
- Add CheckInventoryRequest and StockInfo models
- Implement tool using Products domain helper
- Add comprehensive unit tests"
git push origin feature/add-inventory-tools
# Create PR, merge to main
# → Triggers MCP release (e.g., 0.1.0a1 → 0.2.0a1)
Example 2: Release Client Only¶
# On branch: feature/domain-helpers
git add katana_public_api_client/helpers/products.py
git commit -m "feat(client): add Products domain helper class
- Implement CRUD operations
- Add search and filtering methods
- Full test coverage"
git push origin feature/domain-helpers
# Create PR, merge to main
# → Triggers client release (e.g., 0.23.0 → 0.24.0)
Example 3: Release Both (Separate Commits)¶
# First commit for client
git add katana_public_api_client/helpers/inventory.py
git commit -m "feat(client): add Inventory domain helper"
# Second commit for MCP
git add katana_mcp_server/src/katana_mcp/tools/inventory.py
git commit -m "feat(mcp): add inventory tools using new helper"
git push origin feature/inventory-support
# Create PR, merge to main
# → Triggers BOTH releases independently
Changelog Management¶
Each package maintains its own changelog:
- Client:
docs/CHANGELOG.md - MCP Server:
katana_mcp_server/CHANGELOG.md
Semantic-release automatically updates these files on each release.
Testing Release Configuration¶
You can test the release configuration without actually releasing:
Test Client Release¶
Test MCP Release¶
uv run semantic-release version --print --no-commit --no-tag --no-push \
-c katana_mcp_server/pyproject.toml
Note: These commands only work on the main branch or configured release branches.
Troubleshooting¶
"No release will be made"¶
Cause: No commits with feat:, fix:, or perf: since last release
Solution: Ensure your commits follow conventional commit format with appropriate scopes
"Branch isn't in any release groups"¶
Cause: Not on main branch or a configured release branch
Solution: Only main branch triggers releases. Test on feature branches won't work.
Wrong Package Released¶
Cause: Missing or incorrect commit scope
Solution:
- Use
feat(client):orfix(client):for client releases - Use
feat(mcp):orfix(mcp):for MCP releases - Commits without scope default to client
Dependency Between Packages¶
Problem: MCP server depends on client. When the client version bumps, the MCP dependency should be updated.
Solution: This is now automated! The Update MCP Client Dependency workflow automatically:
- Detects when a new client release is published
- Updates the
katana-openapi-client>=X.Y.Zdependency inkatana_mcp_server/pyproject.toml - Updates the
uv.lockfile - Creates a PR with the conventional commit message
feat(mcp): update client dependency to vX.Y.Z - When merged, triggers a new MCP release (MINOR version bump due to
feat(mcp):)
Manual Override: If you need to update the dependency without waiting for a client release, you can:
- Manually update
katana_mcp_server/pyproject.toml - Run
uv sync --all-extrasto update the lockfile - Commit with
feat(mcp): update to client v0.24.0(or appropriate message)
Best Practices¶
- Use descriptive commit scopes: Always include
(client)or(mcp)scope for clarity - Keep changes focused: Avoid mixing client and MCP changes in single commits
- Update dependencies: When MCP needs newer client version, update pyproject.toml explicitly
- Test before merging: Ensure all CI checks pass before merging to
main - Review changelogs: Check generated changelog entries before releases
Future Enhancements¶
Potential improvements to the release process:
- Pre-release automation: Automatically create pre-release versions for alpha/beta
- Release notes templates: Custom templates for each package type
- Manual version override: Allow manual version specification via workflow_dispatch