Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed
- `ossmate version` and `ossmate_mcp.__version__` resolved to the hardcoded literal `"0.0.1"` instead of the installed package version. Both `__init__.py` modules now read from `importlib.metadata.version()` so they always agree with what `pip show` reports. New invariant test [tests/test_versioning.py](tests/test_versioning.py)::`test_init_modules_dont_hardcode_versions` forbids the hardcoded form going forward — caught the day after v0.1.0 shipped to PyPI

## [0.1.0] - 2026-04-19

First public release. Reference implementation of every Claude Code extension surface, packaged as both a plugin and a standalone CLI.
Expand Down
7 changes: 6 additions & 1 deletion cli/ossmate/src/ossmate/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
"""Ossmate — Claude-powered co-maintainer CLI."""

__version__ = "0.0.1"
from importlib.metadata import PackageNotFoundError, version as _pkg_version

try:
__version__ = _pkg_version("ossmate")
except PackageNotFoundError:
__version__ = "0.0.0+source"
7 changes: 6 additions & 1 deletion mcp/ossmate_mcp/src/ossmate_mcp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
"""Ossmate MCP server — OSS maintainer tools exposed via Model Context Protocol."""

__version__ = "0.0.1"
from importlib.metadata import PackageNotFoundError, version as _pkg_version

try:
__version__ = _pkg_version("ossmate-mcp")
except PackageNotFoundError:
__version__ = "0.0.0+source"
22 changes: 22 additions & 0 deletions tests/test_versioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,28 @@ def test_marketplace_manifest_has_two_version_locations(self):
assert "metadata" in data and "version" in data["metadata"]
assert data["plugins"] and "version" in data["plugins"][0]

def test_init_modules_dont_hardcode_versions(self):
"""`__init__.py` files MUST resolve __version__ from importlib.metadata
rather than hardcoding the literal — otherwise `bump_version.py`
misses them and `ossmate version` lies to users (regression caught
in v0.1.0 post-release)."""
for init in (
REPO_ROOT / "cli" / "ossmate" / "src" / "ossmate" / "__init__.py",
REPO_ROOT / "mcp" / "ossmate_mcp" / "src" / "ossmate_mcp" / "__init__.py",
):
text = init.read_text(encoding="utf-8")
assert "importlib.metadata" in text, (
f"{init.relative_to(REPO_ROOT)} must read __version__ from "
f"importlib.metadata — hardcoding drifts on every release"
)
# Belt-and-suspenders: forbid the literal `__version__ = "X.Y.Z"` form.
import re as _re

assert not _re.search(r'^__version__\s*=\s*"\d', text, _re.MULTILINE), (
f"{init.relative_to(REPO_ROOT)} hardcodes __version__ — use "
f"importlib.metadata.version() instead"
)

def test_cli_dep_pin_matches_mcp_version(self, bump):
"""The CLI declares `ossmate-mcp>=X` — X must equal the MCP package
version, otherwise users get an unsolvable resolver state on first
Expand Down
Loading