-
Notifications
You must be signed in to change notification settings - Fork 155
fix(install): allow local packages at --global scope; fix broken tests #937
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ddbc076
cae9f66
64cee38
4b712b7
f119388
c915980
2b4a9be
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,8 +16,8 @@ | |
| from click.testing import CliRunner | ||
|
|
||
| from apm_cli.commands.marketplace import init | ||
| from apm_cli.marketplace.init_template import render_marketplace_yml_template | ||
| from apm_cli.marketplace.yml_schema import load_marketplace_yml | ||
| from apm_cli.marketplace.init_template import render_marketplace_block | ||
| from apm_cli.marketplace.yml_schema import load_marketplace_from_apm_yml | ||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Helpers | ||
|
|
@@ -45,23 +45,22 @@ def _run_init(tmp_path: Path, extra_args=(), catch_exceptions=True): | |
| class TestInitScaffold: | ||
| """Verify scaffold creation behaviour.""" | ||
|
|
||
| def test_creates_marketplace_yml(self, tmp_path: Path): | ||
| """init must write marketplace.yml in the current directory.""" | ||
| def test_creates_apm_yml(self, tmp_path: Path): | ||
| """init must write apm.yml in the current directory.""" | ||
| runner = CliRunner() | ||
| with runner.isolated_filesystem(temp_dir=str(tmp_path)) as cwd: | ||
| result = runner.invoke(init, [], catch_exceptions=False) | ||
| yml_path = Path(cwd) / "marketplace.yml" | ||
| assert yml_path.exists(), "marketplace.yml was not created" | ||
| yml_path = Path(cwd) / "apm.yml" | ||
| assert yml_path.exists(), "apm.yml was not created" | ||
| assert result.exit_code == 0 | ||
|
|
||
| def test_template_content_is_valid_yml(self, tmp_path: Path): | ||
| """The scaffold content must parse without errors.""" | ||
| runner = CliRunner() | ||
| with runner.isolated_filesystem(temp_dir=str(tmp_path)) as cwd: | ||
| runner.invoke(init, [], catch_exceptions=False) | ||
| yml_path = Path(cwd) / "marketplace.yml" | ||
| # load_marketplace_yml must not raise | ||
| parsed = load_marketplace_yml(yml_path) | ||
| yml_path = Path(cwd) / "apm.yml" | ||
| parsed = load_marketplace_from_apm_yml(yml_path) | ||
| assert parsed.name == "my-marketplace" | ||
|
|
||
| def test_success_message_in_output(self, tmp_path: Path): | ||
|
|
@@ -70,18 +69,18 @@ def test_success_message_in_output(self, tmp_path: Path): | |
| with runner.isolated_filesystem(temp_dir=str(tmp_path)): | ||
| result = runner.invoke(init, [], catch_exceptions=False) | ||
| combined = result.output | ||
| assert "marketplace.yml" in combined | ||
| assert "apm.yml" in combined | ||
|
|
||
| def test_verbose_shows_path(self, tmp_path: Path): | ||
| """--verbose must show the output path.""" | ||
| runner = CliRunner() | ||
| with runner.isolated_filesystem(temp_dir=str(tmp_path)) as cwd: # noqa: F841 | ||
| result = runner.invoke(init, ["--verbose"], catch_exceptions=False) | ||
| assert "marketplace.yml" in result.output or "Path" in result.output | ||
| assert "apm.yml" in result.output or "Path" in result.output | ||
|
|
||
| def test_template_contains_packages_example(self, tmp_path: Path): | ||
| """Scaffold must contain at least one example package entry.""" | ||
| template = render_marketplace_yml_template() | ||
| template = render_marketplace_block() | ||
| assert "packages:" in template | ||
| assert "source:" in template | ||
|
|
||
|
|
@@ -96,22 +95,20 @@ def test_second_run_without_force_exits_1(self, tmp_path: Path): | |
| runner.invoke(init, [], catch_exceptions=False) | ||
| result = runner.invoke(init, [], catch_exceptions=False) | ||
| assert result.exit_code == 1 | ||
| assert "already exists" in result.output or "--force" in result.output | ||
| assert "already" in result.output or "--force" in result.output | ||
|
|
||
| def test_force_overwrites_existing(self, tmp_path: Path): | ||
| """--force must overwrite an existing marketplace.yml.""" | ||
| """--force must overwrite an existing marketplace block.""" | ||
| runner = CliRunner() | ||
| with runner.isolated_filesystem(temp_dir=str(tmp_path)) as cwd: | ||
| # First run | ||
| runner.invoke(init, [], catch_exceptions=False) | ||
| yml_path = Path(cwd) / "marketplace.yml" | ||
| yml_path.write_text("corrupted: true\n", encoding="utf-8") | ||
| yml_path = Path(cwd) / "apm.yml" | ||
| # Force overwrite | ||
| result = runner.invoke(init, ["--force"], catch_exceptions=False) | ||
| content = yml_path.read_text(encoding="utf-8") | ||
| assert result.exit_code == 0 | ||
| # The scaffold must have replaced the corrupted content | ||
| assert "my-marketplace" in content | ||
| assert "marketplace:" in content | ||
|
|
||
|
Comment on lines
+101
to
112
|
||
|
|
||
| class TestInitGitignoreWarning: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -121,8 +121,8 @@ def _run_outdated_cwd(extra_args=()): | |
| class TestOutdatedVersionRanges: | ||
| """Verify upgrade classification for version-range entries.""" | ||
|
|
||
| def test_exit_code_always_zero(self, tmp_path: Path): | ||
| """outdated must exit 0 regardless of upgrade availability.""" | ||
| def test_exit_code_one_when_upgradable(self, tmp_path: Path): | ||
| """outdated must exit 1 when upgradable packages exist.""" | ||
| runner = CliRunner() | ||
|
Comment on lines
+124
to
126
|
||
| (tmp_path / "marketplace.yml").write_text(_OUTDATED_YML, encoding="utf-8") | ||
| with runner.isolated_filesystem(temp_dir=str(tmp_path)) as cwd: | ||
|
|
@@ -134,7 +134,7 @@ def test_exit_code_always_zero(self, tmp_path: Path): | |
| side_effect=_side_effect, | ||
| ): | ||
| result = runner.invoke(outdated, [], catch_exceptions=False) | ||
| assert result.exit_code == 0 | ||
| assert result.exit_code == 1 | ||
|
|
||
| def test_package_names_appear_in_output(self, tmp_path: Path): | ||
| """Output must mention every package entry.""" | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing the local-at-user-scope rejection here makes validation accept local filesystem deps for --global, but the install pipeline still skips/blocks them later (e.g. LocalDependencySource.acquire() and the resolve-phase download_callback both treat local deps at USER scope as unsupported). This can leave users with a ~/.apm/apm.yml that records a local path while nothing is actually installed/integrated. Either fully support local deps at USER scope (ensure relative paths resolve consistently, likely by canonicalizing to an absolute path before writing the user manifest and allowing the local copy path in resolve/integration), or keep rejecting them consistently with a single clear error path.