From af8ff3868748412cb658c803ebc8a71edc3cd8fb Mon Sep 17 00:00:00 2001 From: Alexander Petric Date: Tue, 1 Sep 2026 17:31:43 -0400 Subject: [PATCH] fix: tolerate string app_id in GHES app config deserialization (#10923) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: tolerate string app_id in GHES app config deserialization Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_018Rh73nHumzCbyd4Gwf6kw6 * fix: address review — strict app_id validation, drop dead variant Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_018Rh73nHumzCbyd4Gwf6kw6 * chore: update ee-repo-ref to b52c6471d517d979a9887f207a36347b1af376c8 This commit updates the EE repository reference after PR #767 was merged in windmill-ee-private. Previous ee-repo-ref: ab2dc653719f9d65eb10964d1e2b5bc1b94d6535 New ee-repo-ref: b52c6471d517d979a9887f207a36347b1af376c8 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Fable 5 Co-authored-by: windmill-internal-app[bot] --- backend/ee-repo-ref.txt | 2 +- backend/windmill-types/src/more_serde.rs | 57 +++++++++++++++++++ .../instanceSettings/GhesAppSettings.svelte | 12 +++- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/backend/ee-repo-ref.txt b/backend/ee-repo-ref.txt index 0f92d02c72..3956300c4f 100644 --- a/backend/ee-repo-ref.txt +++ b/backend/ee-repo-ref.txt @@ -1 +1 @@ -6efe7a73c745c2e1377a34498523c00d89010a3d +b52c6471d517d979a9887f207a36347b1af376c8 diff --git a/backend/windmill-types/src/more_serde.rs b/backend/windmill-types/src/more_serde.rs index 6eb24b60f4..f9cbe739c5 100644 --- a/backend/windmill-types/src/more_serde.rs +++ b/backend/windmill-types/src/more_serde.rs @@ -38,6 +38,25 @@ pub fn is_default(t: &T) -> bool { &T::default() == t } +pub fn maybe_number<'de, T, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, + T: FromStr + serde::Deserialize<'de>, + ::Err: Display, +{ + #[derive(Deserialize)] + #[serde(untagged)] + enum NumericOrString { + String(String), + RawT(T), + } + + match NumericOrString::::deserialize(deserializer)? { + NumericOrString::String(s) => T::from_str(&s).map_err(serde::de::Error::custom), + NumericOrString::RawT(i) => Ok(i), + } +} + pub fn maybe_number_opt<'de, T, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, @@ -85,3 +104,41 @@ where { serde::Deserialize::deserialize(deserializer).map(Some) } + +#[cfg(test)] +mod tests { + use serde::Deserialize; + + #[derive(Deserialize)] + struct WithMaybeNumber { + #[serde(deserialize_with = "super::maybe_number")] + n: i64, + } + + #[test] + fn maybe_number_accepts_number() { + let v: WithMaybeNumber = serde_json::from_value(serde_json::json!({ "n": 12345 })).unwrap(); + assert_eq!(v.n, 12345); + } + + #[test] + fn maybe_number_accepts_string() { + let v: WithMaybeNumber = + serde_json::from_value(serde_json::json!({ "n": "12345" })).unwrap(); + assert_eq!(v.n, 12345); + } + + #[test] + fn maybe_number_rejects_non_numeric_string() { + assert!( + serde_json::from_value::(serde_json::json!({ "n": "abc" })).is_err() + ); + } + + #[test] + fn maybe_number_rejects_null() { + assert!( + serde_json::from_value::(serde_json::json!({ "n": null })).is_err() + ); + } +} diff --git a/frontend/src/lib/components/instanceSettings/GhesAppSettings.svelte b/frontend/src/lib/components/instanceSettings/GhesAppSettings.svelte index da63e8d64a..acd18130da 100644 --- a/frontend/src/lib/components/instanceSettings/GhesAppSettings.svelte +++ b/frontend/src/lib/components/instanceSettings/GhesAppSettings.svelte @@ -283,7 +283,17 @@ placeholder: '12345', disabled: fieldsDisabled }} - bind:value={$values['github_enterprise_app'].app_id} + bind:value={ + () => $values['github_enterprise_app'].app_id, + (v) => { + // The backend expects app_id as a positive integer (i64). Reject + // fractional/out-of-range values instead of truncating them, and store + // undefined (never a string or 0) so the config omits the key when unset. + const n = typeof v === 'string' ? Number(v.trim() || NaN) : (v ?? NaN) + $values['github_enterprise_app'].app_id = + Number.isSafeInteger(n) && n > 0 ? n : undefined + } + } />