feat: rename apm.lock to apm.lock.yaml for IDE syntax highlighting#280
feat: rename apm.lock to apm.lock.yaml for IDE syntax highlighting#280danielmeppiel merged 7 commits intomainfrom
Conversation
Co-authored-by: danielmeppiel <51440732+danielmeppiel@users.noreply.github.com>
Co-authored-by: danielmeppiel <51440732+danielmeppiel@users.noreply.github.com>
|
@copilot validate this does not impact our GitHub Action: found in microsoft/apm-action repository, which allows users to pack and unpack, among other capabilities |
The The action's TypeScript code (
The one cross-version note: bundles packed by new APM (containing |
There was a problem hiding this comment.
Pull request overview
Renames the APM lockfile to apm.lock.yaml (to enable YAML syntax highlighting in IDEs) and updates the CLI/test/docs surface area accordingly, including a one-time migration path for existing apm.lock users and backward compatibility for unpacking older bundles.
Changes:
- Introduces
LOCKFILE_NAME/_LEGACY_LOCKFILE_NAME, updatesget_lockfile_path(), and addsmigrate_lockfile_if_needed()forapm.lock→apm.lock.yaml. - Updates CLI flows to read/write the new lockfile name, and adds bundle unpack fallback for legacy bundles.
- Updates tests and Starlight documentation to reference
apm.lock.yaml, and adds a changelog entry.
Reviewed changes
Copilot reviewed 43 out of 43 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| src/apm_cli/deps/lockfile.py | Defines new lockfile name constants, updates lockfile path helper, adds legacy→new migration helper. |
| src/apm_cli/commands/install.py | Runs migration early in install and switches lockfile reads to get_lockfile_path(). |
| src/apm_cli/commands/prune.py | Reads lockfile via get_lockfile_path() instead of hardcoded filename. |
| src/apm_cli/commands/_helpers.py | Reads lockfile via get_lockfile_path() instead of hardcoded filename. |
| src/apm_cli/integration/mcp_integrator.py | Defaults MCP lockfile persistence to get_lockfile_path(). |
| src/apm_cli/bundle/packer.py | Packs using apm.lock.yaml and reads lockfile via get_lockfile_path(). |
| src/apm_cli/bundle/unpacker.py | Unpacks preferring apm.lock.yaml, falling back to legacy apm.lock for older bundles. |
| tests/test_lockfile.py | Updates get_lockfile_path() expectations and adds migration unit tests. |
| tests/unit/test_unpacker.py | Updates bundle fixtures to write apm.lock.yaml and adds legacy-bundle unpack test. |
| tests/unit/test_packer.py | Updates packer fixtures and error expectations to apm.lock.yaml. |
| tests/unit/test_transitive_deps.py | Updates transitive deps tests to write/read apm.lock.yaml. |
| tests/unit/test_transitive_mcp.py | Updates transitive MCP tests to use apm.lock.yaml. |
| tests/unit/test_uninstall_transitive_cleanup.py | Updates uninstall transitive cleanup tests to use apm.lock.yaml. |
| tests/unit/test_mcp_lifecycle_e2e.py | Updates MCP lifecycle e2e tests to use apm.lock.yaml. |
| tests/test_enhanced_discovery.py | Updates enhanced discovery tests to write apm.lock.yaml. |
| tests/integration/test_selective_install_mcp.py | Updates selective MCP install integration tests to use apm.lock.yaml. |
| tests/integration/test_plugin_e2e.py | Updates plugin e2e tests to assert apm.lock.yaml existence and parse it. |
| tests/integration/test_pack_unpack_e2e.py | Updates pack/unpack integration test to assert apm.lock.yaml. |
| tests/integration/test_diff_aware_install_e2e.py | Updates helper to read apm.lock.yaml. |
| tests/integration/test_deployed_files_e2e.py | Updates helper and lockfile deletion paths to apm.lock.yaml. |
| docs/src/content/docs/reference/primitive-types.md | Updates references from apm.lock to apm.lock.yaml. |
| docs/src/content/docs/reference/manifest-schema.md | Updates schema text to require apm.lock.yaml. |
| docs/src/content/docs/reference/lockfile-spec.md | Updates lockfile spec wording to apm.lock.yaml. |
| docs/src/content/docs/reference/cli-commands.md | Updates CLI reference to apm.lock.yaml. |
| docs/src/content/docs/introduction/why-apm.md | Updates introductory references to the new lockfile name. |
| docs/src/content/docs/introduction/what-is-apm.md | Updates introductory references to the new lockfile name. |
| docs/src/content/docs/integrations/ide-tool-integration.md | Updates integration docs to reference apm.lock.yaml. |
| docs/src/content/docs/integrations/github-rulesets.md | Updates rulesets docs to reference apm.lock.yaml. |
| docs/src/content/docs/integrations/gh-aw.md | Updates GH Agentic Workflows docs to reference apm.lock.yaml. |
| docs/src/content/docs/integrations/ci-cd.md | Updates CI/CD docs to reference apm.lock.yaml. |
| docs/src/content/docs/guides/plugins.md | Updates plugin guide references to apm.lock.yaml. |
| docs/src/content/docs/guides/pack-distribute.md | Updates pack/distribute guide to reference apm.lock.yaml in examples. |
| docs/src/content/docs/guides/org-packages.md | Updates org packages guide references to apm.lock.yaml. |
| docs/src/content/docs/guides/dependencies.md | Updates dependencies guide section headings and examples to apm.lock.yaml. |
| docs/src/content/docs/guides/agent-workflows.md | Updates workflow guide references to apm.lock.yaml. |
| docs/src/content/docs/getting-started/quick-start.md | Updates quick start directory layout and text to apm.lock.yaml. |
| docs/src/content/docs/getting-started/migration.md | Updates migration doc instructions to commit/remove apm.lock.yaml. |
| docs/src/content/docs/enterprise/teams.md | Updates enterprise teams doc to reference apm.lock.yaml. |
| docs/src/content/docs/enterprise/security.md | Updates security doc references to apm.lock.yaml. |
| docs/src/content/docs/enterprise/making-the-case.md | Updates “making the case” doc references to apm.lock.yaml. |
| docs/src/content/docs/enterprise/governance.md | Updates governance doc references and examples to apm.lock.yaml. |
| docs/src/content/docs/enterprise/adoption-playbook.md | Updates adoption playbook references to apm.lock.yaml. |
| CHANGELOG.md | Adds an Unreleased entry describing the lockfile rename/migration. |
Comments suppressed due to low confidence (1)
src/apm_cli/bundle/unpacker.py:98
- When neither lockfile exists in the bundle, the error message always says
apm.lock.yaml not foundeven if the code just checked bothapm.lock.yamland legacyapm.lock. Consider mentioning both filenames or using the attempted filename(s) in the message to reduce confusion for users unpacking older bundles.
if not lockfile_path.exists():
raise FileNotFoundError(
"apm.lock.yaml not found in the bundle -- the bundle may be incomplete."
)
| try: | ||
| lockfile = cls.read(project_root / "apm.lock") | ||
| lockfile = cls.read(get_lockfile_path(project_root)) | ||
| if not lockfile: | ||
| return [] | ||
| return lockfile.get_installed_paths(project_root / "apm_modules") |
| new_path = get_lockfile_path(project_root) | ||
| legacy_path = project_root / _LEGACY_LOCKFILE_NAME | ||
| if not new_path.exists() and legacy_path.exists(): | ||
| legacy_path.rename(new_path) | ||
| return True | ||
| return False |
src/apm_cli/bundle/unpacker.py
Outdated
| from ..deps.lockfile import LockFile, LOCKFILE_NAME, _LEGACY_LOCKFILE_NAME | ||
|
|
||
|
|
| raise FileNotFoundError( | ||
| "apm.lock in the bundle could not be parsed -- the bundle may be corrupt." | ||
| "apm.lock.yaml in the bundle could not be parsed -- the bundle may be corrupt." | ||
| ) |
src/apm_cli/bundle/packer.py
Outdated
| # 1. Read lockfile | ||
| lockfile_path = project_root / "apm.lock" | ||
| lockfile_path = get_lockfile_path(project_root) | ||
| lockfile = LockFile.read(lockfile_path) | ||
| if lockfile is None: | ||
| raise FileNotFoundError( |
tests/integration/test_plugin_e2e.py
Outdated
|
|
||
| # Lock file created | ||
| assert (temp_project / "apm.lock").exists(), "apm.lock should be created" | ||
| assert (temp_project / "apm.lock.yaml").exists(), "apm.lock should be created" |
CHANGELOG.md
Outdated
| ### Changed | ||
|
|
||
| - Lockfile renamed from `apm.lock` to `apm.lock.yaml` for IDE syntax highlighting; existing `apm.lock` files are automatically migrated to `apm.lock.yaml` on the next `apm install` (#TBD) |
| """ | ||
| if lock_path is None: | ||
| lock_path = Path.cwd() / "apm.lock" | ||
| lock_path = get_lockfile_path(Path.cwd()) |
| ## Abstract | ||
|
|
||
| `apm.lock` records the exact resolved state of every dependency in an APM | ||
| `apm.lock.yaml` records the exact resolved state of every dependency in an APM | ||
| project. It is the receipt of what was installed — commit SHAs, source URLs, |
| # Migrate legacy apm.lock → apm.lock.yaml if needed (one-time, transparent) | ||
| migrate_lockfile_if_needed(Path.cwd()) | ||
|
|
||
| # Capture old MCP servers and configs from lockfile BEFORE | ||
| # _install_apm_dependencies regenerates it (which drops the fields). | ||
| # We always read this — even when --only=apm — so we can restore the | ||
| # field after the lockfile is regenerated by the APM install step. | ||
| old_mcp_servers: builtins.set = builtins.set() | ||
| old_mcp_configs: builtins.dict = {} | ||
| _lock_path = Path.cwd() / "apm.lock" | ||
| _lock_path = get_lockfile_path(Path.cwd()) | ||
| _existing_lock = LockFile.read(_lock_path) |
|
@copilot review the PR comments and fix if needed and appropriate. In addition, integration tests that ran seem to be failing at https://github.com/microsoft/apm/actions/runs/23045967973, ensure integration tests do pass. |
…blic constant, messages Co-authored-by: danielmeppiel <51440732+danielmeppiel@users.noreply.github.com>
Co-authored-by: danielmeppiel <51440732+danielmeppiel@users.noreply.github.com>
All 10 PR review comments addressed in commits 0f5c07f and 5e32d00:
Re: integration test failure — |
The lockfile was named
apm.lock(a YAML file without.yamlextension), causing IDEs to skip syntax highlighting. Renames it toapm.lock.yamlwith automatic one-time migration for existing users.Description
The lockfile is now
apm.lock.yaml. Existingapm.lockfiles are silently renamed on the nextapm install.Core changes
lockfile.py—get_lockfile_path()returnsapm.lock.yaml; exposesLOCKFILE_NAME/LEGACY_LOCKFILE_NAMEpublic constants; addsmigrate_lockfile_if_needed(project_root)which renamesapm.lock→apm.lock.yamlwhen the new file is absent (withOSErrorhandling and debug logging so installs proceed even on read-only filesystems)lockfile.py—installed_paths_for_project()falls back to reading legacyapm.lockwhenapm.lock.yamlis absent, ensuring transitive dependency discovery works before the firstapm installafter upgradeinstall.py— callsmigrate_lockfile_if_needed()at the top of the install flow before any lockfile reads; user-facing log messages updated to referenceapm.lock.yamlpacker.py— callsmigrate_lockfile_if_needed()before reading the lockfile, soapm packworks even if only a legacyapm.lockexists; writesapm.lock.yamlinto bundlesunpacker.py— triesapm.lock.yamlfirst, falls back toapm.lockfor backward compat with old bundles; error messages now use the actual filename read (lockfile_path.name)prune.py/_helpers.py/mcp_integrator.py— replace all hardcoded"apm.lock"path strings withget_lockfile_path();update_lockfile()docstring updated to referenceapm.lock.yamlapm-action compatibility
The
microsoft/apm-actionGitHub Action (pack/unpack/install modes) is fully compatible with this change. The action's TypeScript code never referencesapm.lockdirectly — all lockfile-sensitive operations are delegated to the APM CLI. The tar-based fallback restore path is also unaffected, as it extracts files without inspecting the lockfile. The one cross-version note: bundles produced by the new APM (containingapm.lock.yaml) cannot be unpacked by an old APM CLI; users pinningapm-versionon their restore job should keep it in sync with their pack job.Tests
apm.lock.yamlTestMigrateLockfileIfNeeded(migrates, no-op when new file exists, no-op when no legacy file)test_unpack_legacy_lockfile_backward_compatfor old bundles containingapm.lockapm.lock.yamlDocs / changelog
CHANGELOG.mdentry added under[Unreleased]with PR feat: rename apm.lock to apm.lock.yaml for IDE syntax highlighting #280lockfile-spec.mdmigration section updated to document theapm.lock→apm.lock.yamlfilename migrationType of change
Testing
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.