fix(ci): stop verifying published assets against the CDN (#2738)

This commit is contained in:
Hampus authored and GitHub committed 2026-09-13 18:04:08 +02:00
1 parent 7375ac9d80
commit 7d34d25497
1 file changed
+1 -94
+1 -94
View File
@@ -12,17 +12,11 @@ use base64::Engine;
use base64::engine::general_purpose::STANDARD as BASE64; use base64::engine::general_purpose::STANDARD as BASE64;
use chrono::Utc; use chrono::Utc;
use clap::{Args, ValueEnum}; use clap::{Args, ValueEnum};
use reqwest::Client;
use serde_json::{Map, Value, json}; use serde_json::{Map, Value, json};
use std::collections::{BTreeMap, BTreeSet}; use std::collections::{BTreeMap, BTreeSet};
use std::env; use std::env;
use std::fs::{self, File}; use std::fs::{self, File};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::Semaphore;
use tokio::task::JoinSet;
use tokio::time::sleep;
const DEFAULT_PUBLIC_ASSET_BASE_URL: &str = "https://fluxerstatic.com"; const DEFAULT_PUBLIC_ASSET_BASE_URL: &str = "https://fluxerstatic.com";
const DEFAULT_APP_PROXY_TIME_FREEZE_ENABLED: &str = "true"; const DEFAULT_APP_PROXY_TIME_FREEZE_ENABLED: &str = "true";
@@ -35,10 +29,6 @@ const CANONICAL_ASSETS_DIR: &str = "/assets";
const AMD64_PLATFORM: &str = "linux/amd64"; const AMD64_PLATFORM: &str = "linux/amd64";
const ARM64_PLATFORM: &str = "linux/arm64"; const ARM64_PLATFORM: &str = "linux/arm64";
const PARITY_DIFF_LIMIT: usize = 20; const PARITY_DIFF_LIMIT: usize = 20;
const ASSET_READ_CONCURRENCY: usize = 16;
const ASSET_READ_ATTEMPTS: u32 = 3;
const ASSET_READ_RETRY_DELAY: Duration = Duration::from_secs(2);
const ASSET_READ_TIMEOUT: Duration = Duration::from_secs(30);
#[derive(Debug, Args, Clone)] #[derive(Debug, Args, Clone)]
pub struct BuildAppProxyArgs { pub struct BuildAppProxyArgs {
@@ -365,10 +355,7 @@ async fn verify_published_assets_step() -> Result<()> {
unproduced.join(", ") unproduced.join(", ")
); );
match env_string("PUBLIC_ASSET_BASE_URL") { verify_local_assets(&dist, &assets)
Some(base) => verify_remote_assets(&base, &assets).await,
None => verify_local_assets(&dist, &assets),
}
} }
fn verify_local_assets(dist: &Path, assets: &[String]) -> Result<()> { fn verify_local_assets(dist: &Path, assets: &[String]) -> Result<()> {
@@ -391,74 +378,6 @@ fn verify_local_assets(dist: &Path, assets: &[String]) -> Result<()> {
Ok(()) Ok(())
} }
async fn verify_remote_assets(base: &str, assets: &[String]) -> Result<()> {
let client = Client::builder()
.timeout(ASSET_READ_TIMEOUT)
.build()
.context("Failed to build the asset verification HTTP client")?;
let semaphore = Arc::new(Semaphore::new(ASSET_READ_CONCURRENCY));
let mut tasks = JoinSet::new();
for asset in assets {
let permit = semaphore
.clone()
.acquire_owned()
.await
.context("Asset verification semaphore closed")?;
let client = client.clone();
let url = asset_url(base, asset);
let asset = asset.clone();
tasks.spawn(async move {
let _permit = permit;
read_published_asset(&client, &url)
.await
.err()
.map(|error| format!("{asset}: {error}"))
});
}
let mut failures = Vec::new();
while let Some(result) = tasks.join_next().await {
if let Some(failure) = result.context("Asset verification task failed")? {
failures.push(failure);
}
}
failures.sort();
ensure!(
failures.is_empty(),
"{} of {} published assets are not readable at {base}:\n{}",
failures.len(),
assets.len(),
failures.join("\n")
);
println!(
"published asset verification passed - {} assets readable at {base}",
assets.len()
);
Ok(())
}
async fn read_published_asset(client: &Client, url: &str) -> Result<()> {
let mut last_error = None;
for attempt in 1..=ASSET_READ_ATTEMPTS {
match client.get(url).header("range", "bytes=0-0").send().await {
Ok(response) if response.status().is_success() => return Ok(()),
Ok(response) => {
last_error = Some(anyhow!("{url} responded {}", response.status()));
}
Err(error) => last_error = Some(anyhow!("{url} request failed: {error}")),
}
if attempt < ASSET_READ_ATTEMPTS {
sleep(ASSET_READ_RETRY_DELAY).await;
}
}
Err(last_error.unwrap_or_else(|| anyhow!("{url} could not be read")))
}
fn asset_url(base: &str, key: &str) -> String {
format!("{}/{}", base.trim_end_matches('/'), key)
}
fn referenced_assets(source: &str) -> Vec<String> { fn referenced_assets(source: &str) -> Vec<String> {
const PREFIX: &str = "assets/"; const PREFIX: &str = "assets/";
let bytes = source.as_bytes(); let bytes = source.as_bytes();
@@ -1018,18 +937,6 @@ mod tests {
assert_eq!(digests["index.html"], changed["index.html"]); assert_eq!(digests["index.html"], changed["index.html"]);
} }
#[test]
fn asset_url_joins_the_base_and_key_once() {
assert_eq!(
asset_url("https://fluxerstatic.com", "assets/a.js"),
"https://fluxerstatic.com/assets/a.js"
);
assert_eq!(
asset_url("https://fluxerstatic.com/", "assets/a.js"),
"https://fluxerstatic.com/assets/a.js"
);
}
#[test] #[test]
fn assets_image_ref_names_the_canonical_image() { fn assets_image_ref_names_the_canonical_image() {
assert_eq!( assert_eq!(