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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed

- `apm deps update` was a no-op -- rewrote to delegate to the install engine so lockfile, deployed files, and integration state are all refreshed correctly -- by @webmaxru (#493)

## [0.8.6] - 2026-03-27

### Added
Expand Down
9 changes: 6 additions & 3 deletions docs/src/content/docs/guides/dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -554,11 +554,14 @@ dependencies:
### Updating Dependencies

```bash
# Update all dependencies to latest versions
# Update all dependencies to latest refs
apm deps update

# Update specific dependency
apm deps update apm-sample-package
# Update specific dependency (use the owner/repo form from apm.yml)
apm deps update owner/apm-sample-package

# Update with verbose output
apm deps update --verbose

Comment thread
danielmeppiel marked this conversation as resolved.
# Install with updates (equivalent to update)
apm install --update
Expand Down
28 changes: 22 additions & 6 deletions docs/src/content/docs/reference/cli-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -717,22 +717,38 @@ apm deps clean --yes

#### `apm deps update` - Update APM dependencies

Update installed APM dependencies to their latest versions.
Re-resolve git references to their latest commits, download updated content,
re-integrate primitives, and regenerate the lockfile.

```bash
apm deps update [PACKAGE]
apm deps update [PACKAGES...] [OPTIONS]
```

**Arguments:**
- `PACKAGE` - Optional. Update specific package only
- `PACKAGES` - Optional. One or more packages to update. Omit to update all.

**Options:**
- `--verbose, -v` - Show detailed update information
- `--force` - Overwrite locally-authored files on collision
- `--target, -t` - Force deployment to a specific target (copilot, claude, cursor, opencode, vscode, agents, all)
- `--parallel-downloads` - Max concurrent downloads (default: 4)

**Examples:**
```bash
# Update all APM dependencies to latest versions
# Update all APM dependencies to latest refs
apm deps update

# Update specific package to latest version
apm deps update compliance-rules
# Update a specific package (short name or full owner/repo)
apm deps update owner/compliance-rules

# Update multiple packages
apm deps update org/pkg-a org/pkg-b

Comment thread
danielmeppiel marked this conversation as resolved.
# Update with verbose output
apm deps update --verbose

# Force overwrite local files on collision
apm deps update --force
```

### `apm mcp` - Browse MCP server registry
Expand Down
4 changes: 0 additions & 4 deletions src/apm_cli/commands/deps/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
_get_detailed_context_counts,
_get_package_display_info,
_get_detailed_package_info,
_update_single_package,
_update_all_packages,
)

__all__ = [
Expand All @@ -29,6 +27,4 @@
"_get_detailed_context_counts",
"_get_package_display_info",
"_get_detailed_package_info",
"_update_single_package",
"_update_all_packages",
]
108 changes: 2 additions & 106 deletions src/apm_cli/commands/deps/_utils.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
"""Utility helpers for APM dependency commands."""

from pathlib import Path
from typing import Any, Dict, List, Optional
from typing import Any, Dict

from ...constants import APM_DIR, APM_MODULES_DIR, APM_YML_FILENAME, SKILL_MD_FILENAME
from ...constants import APM_DIR, APM_YML_FILENAME, SKILL_MD_FILENAME
from ...models.apm_package import APMPackage
from ...deps.github_downloader import GitHubPackageDownloader


def _scan_installed_packages(apm_modules_dir: Path) -> list:
Expand Down Expand Up @@ -221,106 +220,3 @@ def _get_detailed_package_info(package_path: Path) -> Dict[str, Any]:
'workflows': 0,
'hooks': 0
}


def _update_single_package(package_name: str, project_deps: List, apm_modules_path: Path, logger=None):
"""Update a specific package."""
if logger is None:
from ...core.command_logger import CommandLogger
logger = CommandLogger("deps-update")

# Find the dependency reference for this package
target_dep = None
for dep in project_deps:
if dep.get_display_name() == package_name or dep.repo_url.split('/')[-1] == package_name:
target_dep = dep
break

if not target_dep:
logger.error(f"Package '{package_name}' not found in apm.yml dependencies")
return

# Find the installed package directory using namespaced structure
# GitHub: owner/repo (2 parts)
# Azure DevOps: org/project/repo (3 parts)
package_dir = None
if target_dep.alias:
package_dir = apm_modules_path / target_dep.alias
else:
# Parse path from repo_url
repo_parts = target_dep.repo_url.split('/')
if target_dep.is_azure_devops() and len(repo_parts) >= 3:
# ADO structure: apm_modules/org/project/repo
package_dir = apm_modules_path / repo_parts[0] / repo_parts[1] / repo_parts[2]
elif len(repo_parts) >= 2:
package_dir = apm_modules_path / repo_parts[0] / repo_parts[1]
else:
# Fallback to simple name matching
package_dir = apm_modules_path / package_name

if not package_dir.exists():
logger.error(f"Package '{package_name}' not installed in apm_modules/")
logger.progress(f"Run 'apm install' to install it first")
return

try:
downloader = GitHubPackageDownloader()
logger.progress(f"Updating {target_dep.repo_url}...")

# Download latest version
package_info = downloader.download_package(target_dep, package_dir)

logger.success(f"Updated {target_dep.repo_url}")

except Exception as e:
logger.error(f"Failed to update {package_name}: {e}")


def _update_all_packages(project_deps: List, apm_modules_path: Path, logger=None):
"""Update all packages."""
if logger is None:
from ...core.command_logger import CommandLogger
logger = CommandLogger("deps-update")

if not project_deps:
logger.progress("No APM dependencies to update")
return

logger.start(f"Updating {len(project_deps)} APM dependencies...")

downloader = GitHubPackageDownloader()
updated_count = 0

for dep in project_deps:
# Determine package directory using namespaced structure
# GitHub: apm_modules/owner/repo (2 parts)
# Azure DevOps: apm_modules/org/project/repo (3 parts)
if dep.alias:
package_dir = apm_modules_path / dep.alias
else:
# Parse path from repo_url
repo_parts = dep.repo_url.split('/')
if dep.is_azure_devops() and len(repo_parts) >= 3:
# ADO structure
package_dir = apm_modules_path / repo_parts[0] / repo_parts[1] / repo_parts[2]
elif len(repo_parts) >= 2:
package_dir = apm_modules_path / repo_parts[0] / repo_parts[1]
else:
# Fallback to simple repo name (shouldn't happen)
package_dir = apm_modules_path / dep.repo_url

if not package_dir.exists():
logger.warning(f"{dep.repo_url} not installed - skipping")
continue

try:
logger.verbose_detail(f" Updating {dep.repo_url}...")
package_info = downloader.download_package(dep, package_dir)
updated_count += 1
logger.success(f" {dep.repo_url}")

except Exception as e:
logger.error(f" Failed to update {dep.repo_url}: {e}")
continue

logger.success(f"Updated {updated_count} of {len(project_deps)} packages")
Loading
Loading