From da9b6f1ea673cb481e228709ab95bcb36fe01eb6 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Tue, 27 Oct 2026 10:25:13 +0100 Subject: [PATCH] fix(pnpr): print the S3 key prefix in config check without debug formatting (#17416) The storage summary formatted `Option` with `{:?}`, so it showed `prefix: Some("pnpr")` or `prefix: None`. It now prints the normalized prefix the store uses for its keys, and nothing when there is none. The custom object store line gets the same treatment. --- .changeset/config-check-s3-prefix.md | 5 ++++ pnpr/crates/pnpr/src/config_check.rs | 15 ++++++++--- pnpr/crates/pnpr/tests/tooling.rs | 37 ++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 .changeset/config-check-s3-prefix.md diff --git a/.changeset/config-check-s3-prefix.md b/.changeset/config-check-s3-prefix.md new file mode 100644 index 0000000000..7d89e3cea4 --- /dev/null +++ b/.changeset/config-check-s3-prefix.md @@ -0,0 +1,5 @@ +--- +"@pnpm/pnpr": patch +--- + +`pnpr config check` now prints the S3 key prefix as plain text, such as `prefix: pnpr/`, and leaves it out when none is set. It printed `prefix: Some("pnpr")` or `prefix: None`. diff --git a/pnpr/crates/pnpr/src/config_check.rs b/pnpr/crates/pnpr/src/config_check.rs index 8d612aefe0..4bacc4e953 100644 --- a/pnpr/crates/pnpr/src/config_check.rs +++ b/pnpr/crates/pnpr/src/config_check.rs @@ -1,6 +1,7 @@ use miette::IntoDiagnostic as _; use pnpr_config::{ BackendConfig, Config, ConfigSource, FeatureOverrides, HostedStoreConfig, MaxUsers, + normalize_key_prefix, }; use pnpr_package_name::Ecosystem; use pnpr_registry::{Registries, Registry}; @@ -142,11 +143,17 @@ fn describe_storage_backend(config: &Config) -> String { let display_path = config.storage.hosted_dir.display(); format!("local filesystem ({display_path})") } - HostedStoreConfig::S3(settings) => { - format!("S3 (bucket: {}, prefix: {:?})", settings.bucket, settings.prefix) - } + HostedStoreConfig::S3(settings) => match settings.normalized_prefix().as_str() { + "" => format!("S3 (bucket: {})", settings.bucket), + prefix => { + format!("S3 (bucket: {}, prefix: {})", settings.bucket, prefix.escape_debug()) + } + }, HostedStoreConfig::ObjectStore { prefix, .. } => { - format!("custom object store (prefix: {prefix:?})") + match normalize_key_prefix(Some(prefix)).as_str() { + "" => "custom object store".to_string(), + prefix => format!("custom object store (prefix: {})", prefix.escape_debug()), + } } } } diff --git a/pnpr/crates/pnpr/tests/tooling.rs b/pnpr/crates/pnpr/tests/tooling.rs index aa206b1431..63cd4c7b09 100644 --- a/pnpr/crates/pnpr/tests/tooling.rs +++ b/pnpr/crates/pnpr/tests/tooling.rs @@ -513,6 +513,43 @@ defaultRegistry: assert!(output.contains("Default registries: npm=local, cargo=crates"), "{output}"); } +#[test] +fn test_config_check_reports_the_s3_key_prefix() { + let dir = TempDir::new().unwrap(); + let report = |prefix: &str| { + let yaml = format!( + r" +storage: '{}' +cache: '{}' +s3: + bucket: packages + region: auto + endpoint: https://storage.example.com +{prefix} +registries: + local: + type: hosted + packages: + '@acme/*': + publish: $authenticated +", + dir.path().join("hosted").display(), + dir.path().join("cache").display(), + ); + let config_file = dir.path().join("pnpr.yaml"); + std::fs::write(&config_file, yaml).unwrap(); + let report = pnpr::config_check::check_config(Some(&config_file)).unwrap(); + pnpr::config_check::format_report(&report) + }; + + let output = report(" prefix: /pnpr"); + assert!(output.contains("Storage: S3 (bucket: packages, prefix: pnpr/)\n"), "{output}"); + let output = report(""); + assert!(output.contains("Storage: S3 (bucket: packages)\n"), "{output}"); + let output = report(r#" prefix: "pn\npr""#); + assert!(output.contains(r"Storage: S3 (bucket: packages, prefix: pn\npr/)"), "{output}"); +} + #[test] fn test_config_check_hides_an_unparsable_database_url() { let dir = TempDir::new().unwrap();