fix(init): reject empty/whitespace project names#2200
Open
nadav-y wants to merge 2 commits into
Open
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR tightens project-name handling so apm init and the apm install <pkg> auto-bootstrap path no longer create apm.yml manifests with an empty/whitespace name, aligning upstream behavior with the stricter identity validation introduced in #2155.
Changes:
- Reject empty/whitespace project names in
_validate_project_name. - Add
_resolve_bootstrap_project_name()and use it ininstallauto-bootstrap to fall back to"my-project"whenPath.cwd().name(orPath.home().name) is empty/invalid. - Update
apm initerror messages and add unit/integration tests covering the new validation and interactive re-prompt behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
tests/unit/test_init_command.py |
Adds unit tests for empty/whitespace name validation and bootstrap-name fallback, plus an interactive re-prompt regression test. |
src/apm_cli/commands/install.py |
Routes auto-bootstrap project naming through _resolve_bootstrap_project_name() before writing apm.yml. |
src/apm_cli/commands/init.py |
Updates CLI + interactive error messages to mention non-empty requirement. |
src/apm_cli/commands/_helpers.py |
Extends _validate_project_name to reject empty/whitespace; introduces _resolve_bootstrap_project_name(). |
_validate_project_name only checked for path separators and '..', so an empty or whitespace-only name (e.g. `apm install <pkg>` auto-bootstrapping apm.yml from Path.cwd().name at a container's unset root WORKDIR, or a blank `apm init` prompt) silently wrote `name: ''` into apm.yml. Every later install/lock/compile then failed with "Invalid apm.yml identity: 'name' must be a non-empty string" once microsoft#2155 tightened APMPackage.from_apm_yml's identity check. Reject empty/whitespace names in _validate_project_name, and add _resolve_bootstrap_project_name() so the install auto-bootstrap path falls back to "my-project" instead of writing an empty name. `apm init` had the same gap: when no project_name arg is given, the early _validate_project_name check (guarded by `if project_name and ...`) is skipped entirely, so with --yes the cwd-derived name flowed straight into _get_default_config unvalidated -- silently writing 'name: ""' at a filesystem/drive root. Route it through _resolve_bootstrap_project_name too. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
9e77d13 to
4c30553
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
apm.ymlcan end up with an emptynamefield (name: ''), written byapm itself rather than by a user typo. Once that happens, every later
apm install/apm lock/apm compileon that manifest hard-failswith:
with no way to recover short of hand-editing the file.
Root cause
#2155 tightened
APMPackage.from_apm_yml's identity validation:nameand
versionmust now be non-empty strings, not just present keys. Thatcheck itself is correct and intentional. What's missing is upstream of
it: nothing guaranteed a valid
namebeforeapm.ymlwas written todisk in the first place, so two pre-existing, unrelated code paths could
silently produce
name: '':apm install <pkg>auto-bootstrap (commands/install.py) — when noapm.ymlexists, the project name is derived fromPath.cwd().name(or
Path.home().namefor-g/global installs). That's''at afilesystem/drive root. Concretely: a container image with no
WORKDIRset (Docker's default
WORKDIRis/) runningapm install <pkg> --target claudewritesname: ''straight into theauto-created
apm.yml. This is the confirmed trigger for the reportedbug — verified end-to-end by reproducing an empty
Path.cwd().name.apm initinteractive prompt —rich.Prompt.ask()only substitutesthe default when the raw input is exactly
"". Typing a single spaceat the "Project name" prompt returns
" "(not the default), which thecaller then
.strip()s to""before validation. The old_validate_project_nameonly rejected path separators and'..', notemptiness, so this also silently wrote
name: ''. Separately verifiedand reproduced; not what caused the reported issue, but the same class
of bug through a different entry point.
Fix
_validate_project_namenow rejects empty/whitespace-only names (inaddition to the existing path-separator/
'..'checks)._resolve_bootstrap_project_name()helper, used by theinstall.pyauto-bootstrap path, falls back to
"my-project"(matching the existingplaceholder convention in
commands/deps/cli.py) when the derivedcandidate is invalid.
apm initinteractive-prompt and CLI-arg error messages tomention emptiness, not just path separators.
Test plan
tests/unit/test_init_command.py: new unit tests for_validate_project_name(empty/whitespace) and_resolve_bootstrap_project_name(fallback + passthrough), plus anintegration test that a blank/whitespace
apm initprompt re-promptsinstead of writing
name: ''.and confirmed the fix resolves both.
ruff check/ruff format --checkclean on all touched files.test_init_command.py+test_install_command.pysuites pass(174 tests).
🤖 Generated with Claude Code