From dbd5a80fff54b64185836aa75b41e29e35872b4d Mon Sep 17 00:00:00 2001 From: Fabricio Aguiar Date: Wed, 10 Dec 2025 08:29:55 -0300 Subject: [PATCH 1/2] Improve error handling in Quay client HTTP requests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enhances error reporting when external Quay.io API requests fail by checking HTTP response status before attempting JSON parsing. Changes: - Add status code validation in manifest.rs before JSON deserialization - Add status code validation in tag.rs before JSON deserialization - Return clear error messages with HTTP status codes - Prevent confusing "JSON parsing" errors when getting HTML error pages This improves debugging by showing actual HTTP errors (e.g., "403 Forbidden") instead of cryptic "expected value at line 1 column 1" JSON parsing failures. Network tests now fail properly with actionable error messages when external services have authentication or permission issues. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4 Signed-off-by: Fabricio Aguiar rh-pre-commit.version: 2.3.2 rh-pre-commit.check-secrets: ENABLED --- quay/src/v1/manifest.rs | 7 +++++++ quay/src/v1/tag.rs | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/quay/src/v1/manifest.rs b/quay/src/v1/manifest.rs index 2facd84c8..94740e0bb 100644 --- a/quay/src/v1/manifest.rs +++ b/quay/src/v1/manifest.rs @@ -78,6 +78,13 @@ impl Client { })?; let resp = req.send().await?; + + // Check if the response was successful + if !resp.status().is_success() { + let status = resp.status(); + return Err(anyhow::anyhow!("Request failed with status {}", status)); + } + let json = resp.json::().await?; Ok(json.labels) diff --git a/quay/src/v1/tag.rs b/quay/src/v1/tag.rs index 370e63986..eeb7af7a7 100644 --- a/quay/src/v1/tag.rs +++ b/quay/src/v1/tag.rs @@ -50,6 +50,14 @@ impl Client { .query(&[("onlyActiveTags", actives_only)]); let resp = req.send().await?; + + // Check if the response was successful + if !resp.status().is_success() { + let status = resp.status(); + yield Err(anyhow::anyhow!("Request failed with status {}", status)); + return; + } + let paginated_tags = resp.json::().await?.tags; for tag in paginated_tags { yield Ok(tag); From 48173ac5e7f3bb409fa3809614ab28ac328cb38d Mon Sep 17 00:00:00 2001 From: Fabricio Aguiar Date: Wed, 10 Dec 2025 08:57:07 -0300 Subject: [PATCH 2/2] Fix Quay.io API filter parameter causing 403 Forbidden errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Quay.io labels API returns 403 Forbidden when using filter parameters, but works fine without filters. This change removes the server-side filtering and implements client-side filtering instead. Changes: - Remove filter parameter from get_labels calls in both test and plugin code - Add client-side filtering using starts_with() to match expected prefixes - Tests now pass instead of failing with 403 Forbidden errors 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4 Signed-off-by: Fabricio Aguiar rh-pre-commit.version: 2.3.2 rh-pre-commit.check-secrets: ENABLED --- .../src/plugins/internal/metadata_fetch_quay.rs | 10 +++++++--- quay/tests/net/mod.rs | 15 ++++++++++----- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/cincinnati/src/plugins/internal/metadata_fetch_quay.rs b/cincinnati/src/plugins/internal/metadata_fetch_quay.rs index 7f7fdc194..d971c0b08 100644 --- a/cincinnati/src/plugins/internal/metadata_fetch_quay.rs +++ b/cincinnati/src/plugins/internal/metadata_fetch_quay.rs @@ -123,15 +123,19 @@ impl InternalPlugin for QuayMetadataFetchPlugin { self.label_filter.clone(), ); - let quay_labels = client + let all_labels = client .get_labels( repo.clone(), manifestref.clone(), - Some(label_filter.clone()), + None, // Remove filter to avoid 403 Forbidden - filter client-side instead ) - .await? + .await?; + + // Filter client-side for labels matching the expected prefix + let quay_labels = all_labels .into_iter() .map(Into::into) + .filter(|(key, _): &(String, String)| key.starts_with(&label_filter)) .collect::>(); labels_with_releaseinfo.push((quay_labels, (release_id, release_version))); diff --git a/quay/tests/net/mod.rs b/quay/tests/net/mod.rs index 2eeea538a..fa01786c7 100644 --- a/quay/tests/net/mod.rs +++ b/quay/tests/net/mod.rs @@ -60,14 +60,19 @@ fn test_public_get_labels() { let fetch_labels = client.get_labels( repo.to_string(), digest, - Some("io.openshift.upgrades.graph".to_string()), + None, // Remove filter to avoid 403 Forbidden - filter client-side instead ); let labels = rt.block_on(fetch_labels).unwrap(); + + // Filter client-side for labels matching the expected prefix + let filtered_labels: Vec<(String, String)> = labels + .into_iter() + .map(Into::into) + .filter(|(key, _)| key.starts_with("io.openshift.upgrades.graph")) + .collect(); + assert_eq!( - labels - .into_iter() - .map(Into::into) - .collect::>(), + filtered_labels, vec![( "io.openshift.upgrades.graph.previous.remove".to_string(), "0.0.0".to_string()