diff --git a/fluxer_app/src/features/app/config/Config.ts b/fluxer_app/src/features/app/config/Config.ts index af303bf9e..12ab7a113 100644 --- a/fluxer_app/src/features/app/config/Config.ts +++ b/fluxer_app/src/features/app/config/Config.ts @@ -24,6 +24,16 @@ if (!parsedBuildInfo.success) { } const buildInfo = parsedBuildInfo.output; +const SERVED_RELEASE_CHANNEL_META_SELECTOR = 'meta[name="fluxer-release-channel"]'; + +function servedReleaseChannel(): 'stable' | 'canary' | null { + if (typeof document === 'undefined') { + return null; + } + const value = document.querySelector(SERVED_RELEASE_CHANNEL_META_SELECTOR)?.content; + return value === 'stable' || value === 'canary' ? value : null; +} + function clientReleaseChannel(value: (typeof buildInfo)['PUBLIC_RELEASE_CHANNEL']): 'stable' | 'canary' { switch (value) { case 'stable': @@ -36,5 +46,5 @@ function clientReleaseChannel(value: (typeof buildInfo)['PUBLIC_RELEASE_CHANNEL' export default { PUBLIC_BUILD_VERSION: buildInfo.PUBLIC_BUILD_VERSION, - PUBLIC_RELEASE_CHANNEL: clientReleaseChannel(buildInfo.PUBLIC_RELEASE_CHANNEL), + PUBLIC_RELEASE_CHANNEL: servedReleaseChannel() ?? clientReleaseChannel(buildInfo.PUBLIC_RELEASE_CHANNEL), } as const; diff --git a/fluxer_app_proxy/src/config.rs b/fluxer_app_proxy/src/config.rs index f07342ef4..75efcafb5 100644 --- a/fluxer_app_proxy/src/config.rs +++ b/fluxer_app_proxy/src/config.rs @@ -362,6 +362,7 @@ pub struct AppProxyConfig { pub csp: CspConfig, pub same_origin_hosts: Vec, pub manifest_scope_extensions: Vec, + pub release_channel: Option<&'static str>, pub self_hosted: bool, } @@ -477,11 +478,31 @@ impl AppProxyConfig { "FLUXER_APP_PROXY_MANIFEST_SCOPE_EXTENSIONS", &cfg::read_env("FLUXER_APP_PROXY_MANIFEST_SCOPE_EXTENSIONS", ""), ), + release_channel: parse_release_channel( + "RELEASE_CHANNEL", + &cfg::read_env("RELEASE_CHANNEL", ""), + ), self_hosted: cfg::read_bool_env("FLUXER_SELF_HOSTED", false), } } } +fn parse_release_channel(name: &'static str, raw: &str) -> Option<&'static str> { + match raw.trim().to_ascii_lowercase().as_str() { + "" => None, + "stable" => Some("stable"), + "canary" => Some("canary"), + _ => { + warn_invalid(&InvalidAppProxyEnvironmentError::new( + name, + raw, + "stable or canary", + )); + None + } + } +} + fn parse_manifest_scope_extensions(name: &'static str, raw: &str) -> Vec { let mut origins: Vec = Vec::new(); for value in raw @@ -591,6 +612,21 @@ mod tests { ); } + #[test] + fn release_channel_accepts_only_stable_or_canary() { + assert_eq!( + parse_release_channel("TEST_CHANNEL", " Stable "), + Some("stable") + ); + assert_eq!( + parse_release_channel("TEST_CHANNEL", "canary"), + Some("canary") + ); + assert_eq!(parse_release_channel("TEST_CHANNEL", ""), None); + assert_eq!(parse_release_channel("TEST_CHANNEL", "development"), None); + assert_eq!(parse_release_channel("TEST_CHANNEL", "\">