Unverified Commit e26385b4 authored by Doron Behar's avatar Doron Behar Committed by GitHub
Browse files

prefetch-npm-deps: warn about unresolved lockfile deps (#479805)

parents 6ef9600e 17aec4cd
Loading
Loading
Loading
Loading
+51 −12
Original line number Diff line number Diff line
@@ -11,6 +11,36 @@ use std::{
};
use url::Url;

fn warn_unresolved_packages(
    packages_without_resolved: &[(String, Package)],
    total_count: usize,
) {
    let missing_count = packages_without_resolved.len();
    if missing_count == 0 {
        return;
    }

    let percentage = (missing_count as f64 / total_count as f64) * 100.0;
    eprintln!(
        "warning: {} out of {} packages ({:.1}%) are missing 'resolved' URLs and will not be cached.",
        missing_count, total_count, percentage
    );
    eprintln!("warning: Packages without 'resolved' URLs:");
    for (name, _) in packages_without_resolved.iter().take(10) {
        eprintln!("warning:   - {}", name.trim_start_matches("node_modules/"));
    }
    if missing_count > 10 {
        eprintln!("warning:   ... and {} more", missing_count - 10);
    }
    if percentage > 50.0 {
        eprintln!(
            "warning: More than 50% of packages are missing 'resolved' URLs. This may indicate an issue with the lockfile.\n\
             warning: This is a known issue with some npm versions. See: https://github.com/npm/cli/issues/6301\n\
             warning: Consider regenerating upstream's lockfile with: npm install --package-lock-only (sending an upstream PR is best)"
        );
    }
}

pub(super) fn packages(content: &str) -> anyhow::Result<Vec<Package>> {
    let lockfile: Lockfile = serde_json::from_str(content)?;

@@ -20,18 +50,27 @@ pub(super) fn packages(content: &str) -> anyhow::Result<Vec<Package>> {

            to_new_packages(lockfile.dependencies.unwrap_or_default(), &initial_url)?
        }
        2 | 3 => lockfile
        2 | 3 => {
            let (packages_with_resolved, packages_without_resolved): (Vec<_>, Vec<_>) = lockfile
                .packages
                .unwrap_or_default()
                .into_iter()
            .filter(|(n, p)| !n.is_empty() && matches!(p.resolved, Some(UrlOrString::Url(_))))
                .filter(|(n, _)| !n.is_empty())
                .partition(|(_, p)| matches!(p.resolved, Some(UrlOrString::Url(_))));

            let total_count = packages_with_resolved.len() + packages_without_resolved.len();
            warn_unresolved_packages(&packages_without_resolved, total_count);

            packages_with_resolved
                .into_iter()
                .map(|(n, p)| Package {
                    // Use the package's own name if present (for aliases like string-width-cjs -> string-width),
                    // otherwise extract from the lockfile key
                    name: Some(p.name.unwrap_or(n)),
                    ..p
                })
            .collect(),
                .collect()
        }
        _ => bail!(
            "We don't support lockfile version {}, please file an issue.",
            lockfile.version