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
20 changes: 13 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "apm-cli"
version = "0.8.0"
version = "0.8.1"
Comment on lines 6 to +7
description = "MCP configuration tool"
readme = "README.md"
requires-python = ">=3.10"
Expand Down
8 changes: 4 additions & 4 deletions src/apm_cli/commands/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
Comment on lines 1360 to +1366
_rich_info(f"✓ {display_name}{ref_str} (cached)")
installed_count += 1
if not dep_ref.reference:
Expand Down Expand Up @@ -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
Expand Down
14 changes: 7 additions & 7 deletions tests/unit/test_install_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,32 +54,32 @@ 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):
"""Cached dep with lockfile SHA and user ref shows both."""
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."""
Expand All @@ -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"
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading