-
Notifications
You must be signed in to change notification settings - Fork 88
[BUG] apm install fails validation for SSH-accessible generic Git hosts (non-GitHub/non-ADO) #583
Description
Describe the bug
apm install fails the pre-install validation step when targeting a self-hosted Git server (e.g., a GitLab instance) that is accessible via SSH but not via unauthenticated HTTPS. The validation probes the repository with git ls-remote over HTTPS only, receives a 401/fatal prompt-disabled error, and rejects the package — even though the subsequent clone would succeed over SSH using the user's configured SSH keys.
To Reproduce
- Have a repository hosted on a self-hosted Git server (e.g., git.example.org) accessible via SSH keys but not unauthenticated HTTPS.
- Run:
apm install git@git.example.org:org/group/repo.git - See error...
[*] Validating 1 package...
Trying git ls-remote for git.example.org
git ls-remote rc=128: fatal: could not read Username for 'https://git.example.org': terminal prompts disabled
[x] git@git.example.org:org/group/repo.git -- not accessible or doesn't exist
All packages failed validation. Nothing to install.
Expected behavior
Validation succeeds and the package is installed. APM should try SSH (git ls-remote git@host:path.git) before falling back to HTTPS for generic (non-GitHub, non-ADO) hosts — the same transport preference already used in the clone step (_clone_with_fallback).
Root cause
In install.py, the _package_exists_and_accessible function always calls git ls-remote with an HTTPS URL for generic hosts, even though no token is available and HTTPS may require credentials. The actual clone path (_clone_with_fallback) already tries SSH first for generic hosts, creating an inconsistency between validation and installation.
Suggested Fix
# For generic hosts, try SSH first (no credentials needed when SSH
# keys are configured) before falling back to HTTPS.
urls_to_try = []
if is_generic:
ssh_url = ado_downloader._build_repo_url(
dep_ref.repo_url, use_ssh=True, dep_ref=dep_ref
)
urls_to_try = [ssh_url, package_url] # package_url is the HTTPS fallback
else:
urls_to_try = [package_url]
result = None
for probe_url in urls_to_try:
result = subprocess.run(
["git", "ls-remote", "--heads", "--exit-code", probe_url],
capture_output=True, text=True, timeout=30, env=validate_env,
)
if result.returncode == 0:
break
Additional context
The regression window is narrow: the bug only surfaces when all three of the following are true:
The host is not github.com or dev.azure.com (generic host path)
No APM-managed token is configured for the host (GITHUB_APM_PAT / ADO_APM_PAT are absent)
The repository is accessible via SSH but requires credentials over HTTPS