Skip to content

bug: _parse_artifactory_base_url() ignores PROXY_REGISTRY_URL -- lockfile reinstall fails for virtual subdirectory packages #614

@chkp-roniz

Description

@chkp-roniz

Bug

_parse_artifactory_base_url() in github_downloader.py (line 399) only reads the deprecated ARTIFACTORY_BASE_URL env var. It never checks the canonical PROXY_REGISTRY_URL introduced in #401.

This causes lockfile-based reinstalls of virtual subdirectory packages to fail when only PROXY_REGISTRY_URL is set.

Reproduction

# First install works (uses RegistryConfig.from_env() path)
export PROXY_REGISTRY_URL='https://art.example.com/artifactory/github'
apm marketplace add anthropics/skills
apm install arevlo-design@skills

# Lockfile correctly records:
#   host: art.example.com
#   registry_prefix: artifactory/github

# Clear installed files, reinstall from lockfile
rm -rf .github/prompts
apm install
# FAILS: git clone https://art.example.com/arevlo/claude-code-workflows (missing prefix)

Root Cause

The virtual subdirectory download path (download_package() line 1928) calls _parse_artifactory_base_url() to decide whether to use the Artifactory archive path:

elif dep_ref.is_virtual_subdirectory():
    art_proxy = self._parse_artifactory_base_url()  # only reads ARTIFACTORY_BASE_URL
    if self._is_artifactory_only() and art_proxy:
        return self._download_subdirectory_from_artifactory(...)
    return self.download_subdirectory_package(...)  # falls through to git clone

_parse_artifactory_base_url() returns None because it only checks ARTIFACTORY_BASE_URL:

def _parse_artifactory_base_url(self) -> Optional[tuple]:
    base_url = os.environ.get('ARTIFACTORY_BASE_URL', '').strip().rstrip('/')  # <-- ignores PROXY_REGISTRY_URL
    if not base_url:
        return None

Meanwhile, build_download_ref() in drift.py correctly restores host and artifactory_prefix on dep_ref from the lockfile, but the virtual subdirectory path never checks dep_ref.is_artifactory() -- unlike the non-virtual path (line 1939) which does.

Two Issues in One

Issue A: _parse_artifactory_base_url() doesn't read PROXY_REGISTRY_URL.

Issue B: The virtual subdirectory path doesn't handle "Mode 1: explicit FQDN from lockfile" (dep_ref.is_artifactory() check is missing). The non-virtual path at line 1939 handles it correctly:

# Non-virtual (correct -- checks both modes):
use_artifactory = dep_ref.is_artifactory()          # Mode 1: lockfile FQDN
if not use_artifactory:
    art_proxy = self._parse_artifactory_base_url()   # Mode 2: env var
    if art_proxy and self._should_use_artifactory_proxy(dep_ref):
        use_artifactory = True

# Virtual subdirectory (missing Mode 1):
art_proxy = self._parse_artifactory_base_url()       # Mode 2 only
if self._is_artifactory_only() and art_proxy:         # no dep_ref.is_artifactory() check

Suggested Fix

Fix A: Make _parse_artifactory_base_url() read canonical var first

def _parse_artifactory_base_url(self) -> Optional[tuple]:
    import urllib.parse as urlparse
    base_url = os.environ.get('PROXY_REGISTRY_URL', '').strip().rstrip('/')
    if not base_url:
        base_url = os.environ.get('ARTIFACTORY_BASE_URL', '').strip().rstrip('/')
    if not base_url:
        return None
    # ... rest unchanged

This aligns with how RegistryConfig.from_env() and is_enforce_only() already handle the canonical/deprecated var precedence.

Fix B: Add Mode 1 check to virtual subdirectory path

elif dep_ref.is_virtual_subdirectory():
    if dep_ref.is_artifactory():
        # Mode 1: lockfile restored FQDN + prefix
        return self._download_subdirectory_from_artifactory(
            dep_ref, target_path,
            (dep_ref.host, dep_ref.artifactory_prefix, "https"),
            progress_task_id, progress_obj,
        )
    art_proxy = self._parse_artifactory_base_url()
    if self._is_artifactory_only() and art_proxy:
        return self._download_subdirectory_from_artifactory(
            dep_ref, target_path, art_proxy, progress_task_id, progress_obj,
        )
    return self.download_subdirectory_package(dep_ref, target_path, progress_task_id, progress_obj)

Both fixes are needed: Fix A covers the env-var-only scenario, Fix B covers lockfile-based reinstalls where dep_ref already carries the Artifactory metadata.

Affected Versions

Present on main as of 81082e2 (v0.8.11). Introduced when PROXY_REGISTRY_URL was added in #401 but _parse_artifactory_base_url() was not updated.

Impact

  • Users setting only PROXY_REGISTRY_URL (recommended canonical var) cannot reinstall virtual subdirectory packages from lockfile
  • Users setting ARTIFACTORY_BASE_URL (deprecated) are unaffected
  • Non-virtual packages and virtual file packages are unaffected (different code paths)

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedDeprecated: use status/accepted. Kept for issue history; will be removed in milestone 0.10.0.bugDeprecated: use type/bug. Kept for issue history; will be removed in milestone 0.10.0.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions