Skip to content
Open
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
12 changes: 12 additions & 0 deletions src/apm_cli/bundle/local_bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,13 @@ def _read_bundle_lockfile(bundle_dir: Path) -> dict[str, Any] | None:
return data


def _has_pack_manifest(bundle_dir: Path) -> bool:
"""Whether ``apm.lock.yaml`` carries the pack manifest written by ``apm pack``."""
lockfile = _read_bundle_lockfile(bundle_dir)
pack = (lockfile or {}).get("pack")
return isinstance(pack, dict) and bool(pack)


def _extract_pack_targets(lockfile: dict[str, Any] | None) -> list[str]:
"""Return list of pack targets from a parsed bundle lockfile."""
if not lockfile:
Expand Down Expand Up @@ -345,6 +352,11 @@ def detect_local_bundle(path: Path) -> LocalBundleInfo | None:
if path.is_dir():
if not (path / "plugin.json").is_file():
return None
if (path / "apm.yml").is_file() and not _has_pack_manifest(path):
# An APM source package that happens to ship a plugin.json is a normal
# local dependency, not a bundle: only packed bundles carry the pack
# manifest in apm.lock.yaml.
return None
return _build_info(
path,
is_archive=False,
Expand Down
21 changes: 21 additions & 0 deletions tests/unit/bundle/test_local_bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,27 @@ def _make_plugin_bundle(
return bundle


def test_detect_local_bundle_skips_source_package_with_apm_yml(tmp_path: Path) -> None:
"""A source package with apm.yml and plugin.json is a dependency, not a bundle."""
package = tmp_path / "demo-pkg"
package.mkdir()
(package / "apm.yml").write_text("name: demo-pkg\n", encoding="utf-8")
(package / "plugin.json").write_text(json.dumps({"id": "demo-pkg"}), encoding="utf-8")

assert detect_local_bundle(package) is None


def test_detect_local_bundle_keeps_packed_bundle_with_apm_yml(tmp_path: Path) -> None:
"""A packed bundle stays a bundle even when it also ships an apm.yml."""
bundle = _make_plugin_bundle(tmp_path)
(bundle / "apm.yml").write_text("name: demo-pkg\n", encoding="utf-8")

info = detect_local_bundle(bundle)

assert info is not None
assert info.source_dir == bundle


def _make_plugin_tarball(tmp_path: Path, bundle_dir: Path) -> Path:
"""Archive a bundle directory into .tar.gz."""
tmp_path.mkdir(parents=True, exist_ok=True)
Expand Down