diff --git a/CHANGELOG.md b/CHANGELOG.md index 14682c68..f277c990 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,20 +8,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] + +## [0.8.1] - 2026-03-17 + ### Added - Audit hardening — `apm unpack` content scanning, SARIF/JSON/Markdown `--format`/`--output` for CI capture, `SecurityGate` policy engine, non-zero exits on critical findings (#330) -- Install output now shows resolved git ref alongside package name (e.g. `✓ owner/repo @ main (a1b2c3d4)`) (#340) -- One-time info hint when dependencies have no explicit ref: `Tip: Pin versions with #tag or #sha for reproducible installs` (#340) +- Install output now shows resolved git ref alongside package name (e.g. `✓ owner/repo#main (a1b2c3d4)`) (#340) +- `${input:...}` variable resolution for self-defined MCP server headers and env values — by @sergio-sisternes-epam (#344) -### Fixed +### Changed -- File-level downloads from private repos now use OS credential helpers (macOS Keychain, `gh auth login`, Windows Credential Manager) — closes auth gap between folder and file dependencies (#332) -- Lockfile now preserves the host for GitHub Enterprise custom domains so subsequent `apm install` clones from the correct server (#338) +- Pinning hint moved from inline tip to `── Diagnostics ──` section with aggregated count (#347) +- Install ref display uses `#` separator instead of `@` for consistency with dependency syntax (#340) +- Shorthand `@alias` syntax removed from dependency strings — use the dict format `alias:` field instead (#340) -### Removed +### Fixed -- Shorthand `@alias` syntax removed from dependency strings — the `@` separator conflicted with conventions in npm, Go, and Cargo where `@` denotes scope or version. Use the dict format `alias:` field instead (#340) +- File-level downloads from private repos now use OS credential helpers (macOS Keychain, `gh auth login`, Windows Credential Manager) (#332) +- Lockfile now preserves the host for GitHub Enterprise custom domains so subsequent `apm install` clones from the correct server (#338) +- MCP registry validation no longer fails on transient network errors (#337) ## [0.8.0] - 2026-03-16 diff --git a/pyproject.toml b/pyproject.toml index c0cef081..f6bb840b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "apm-cli" -version = "0.8.0" +version = "0.8.1" description = "MCP configuration tool" readme = "README.md" requires-python = ">=3.10" diff --git a/src/apm_cli/commands/install.py b/src/apm_cli/commands/install.py index 457c7c9f..b118782f 100644 --- a/src/apm_cli/commands/install.py +++ b/src/apm_cli/commands/install.py @@ -1359,11 +1359,11 @@ def _collect_descendants(node, visited=None): if _dep_locked_chk and _dep_locked_chk.resolved_commit and _dep_locked_chk.resolved_commit != "cached": short_sha = _dep_locked_chk.resolved_commit[:8] if dep_ref.reference: - ref_str = f" @ {dep_ref.reference} ({short_sha})" + ref_str = f"#{dep_ref.reference} ({short_sha})" else: - ref_str = f" @ {short_sha}" + ref_str = f"#{short_sha}" elif dep_ref.reference: - ref_str = f" @ {dep_ref.reference}" + ref_str = f"#{dep_ref.reference}" _rich_info(f"✓ {display_name}{ref_str} (cached)") installed_count += 1 if not dep_ref.reference: @@ -1765,7 +1765,7 @@ def _collect_descendants(node, visited=None): # Show resolved ref alongside package name for visibility resolved = getattr(package_info, 'resolved_reference', None) - ref_suffix = f" @ {resolved}" if resolved else "" + ref_suffix = f"#{resolved}" if resolved else "" _rich_success(f"✓ {display_name}{ref_suffix}") # Track unpinned deps for aggregated diagnostic diff --git a/tests/unit/test_install_output.py b/tests/unit/test_install_output.py index 6878fef1..8fa9bf05 100644 --- a/tests/unit/test_install_output.py +++ b/tests/unit/test_install_output.py @@ -54,11 +54,11 @@ def _format_cached_ref(dep_ref, locked_dep): if locked_dep and locked_dep.resolved_commit and locked_dep.resolved_commit != "cached": short_sha = locked_dep.resolved_commit[:8] if dep_ref.reference: - ref_str = f" @ {dep_ref.reference} ({short_sha})" + ref_str = f"#{dep_ref.reference} ({short_sha})" else: - ref_str = f" @ {short_sha}" + ref_str = f"#{short_sha}" elif dep_ref.reference: - ref_str = f" @ {dep_ref.reference}" + ref_str = f"#{dep_ref.reference}" return ref_str def test_cached_with_lockfile_and_ref(self): @@ -66,20 +66,20 @@ def test_cached_with_lockfile_and_ref(self): dep = DependencyReference.parse("owner/repo#v1.0.0") locked = MagicMock(resolved_commit="a1b2c3d4e5f6a1b2") result = self._format_cached_ref(dep, locked) - assert result == " @ v1.0.0 (a1b2c3d4)" + assert result == "#v1.0.0 (a1b2c3d4)" def test_cached_with_lockfile_no_ref(self): """Cached dep with lockfile SHA but no user ref shows SHA only.""" dep = DependencyReference.parse("owner/repo") locked = MagicMock(resolved_commit="deadbeef12345678") result = self._format_cached_ref(dep, locked) - assert result == " @ deadbeef" + assert result == "#deadbeef" def test_cached_no_lockfile_with_ref(self): """Cached dep without lockfile shows user ref only.""" dep = DependencyReference.parse("owner/repo#main") result = self._format_cached_ref(dep, None) - assert result == " @ main" + assert result == "#main" def test_cached_no_lockfile_no_ref(self): """Cached dep without lockfile and no ref shows nothing.""" @@ -92,4 +92,4 @@ def test_cached_lockfile_marked_as_cached(self): dep = DependencyReference.parse("owner/repo#v2.0") locked = MagicMock(resolved_commit="cached") result = self._format_cached_ref(dep, locked) - assert result == " @ v2.0" + assert result == "#v2.0" diff --git a/uv.lock b/uv.lock index a3d5a409..a65cb740 100644 --- a/uv.lock +++ b/uv.lock @@ -179,7 +179,7 @@ wheels = [ [[package]] name = "apm-cli" -version = "0.8.0" +version = "0.8.1" source = { editable = "." } dependencies = [ { name = "click" },