use std::path::Path;
use anyhow::{Context, Result};
use yah_mesofact_bundle::publish_bundle;
use yah_object_store::R2ObjectStore;
pub use yah_mesofact_bundle::PublishReport;
pub async fn publish_bundle_to_r2(
bundle_dir: &Path,
account_id: &str,
bucket: &str,
access_key: &str,
secret_key: &str,
) -> Result<PublishReport> {
let bundle_dir = bundle_dir.to_path_buf();
let account_id = account_id.to_string();
let bucket = bucket.to_string();
let access_key = access_key.to_string();
let secret_key = secret_key.to_string();
tokio::task::spawn_blocking(move || -> Result<PublishReport> {
let store = R2ObjectStore::new(account_id, bucket, access_key, secret_key)
.context("building R2ObjectStore for bundle publish")?;
let report = publish_bundle(&store, &bundle_dir)
.with_context(|| format!("publishing bundle from {}", bundle_dir.display()))?;
Ok(report)
})
.await
.context("bundle publish task panicked")?
}
#[cfg(test)]
mod tests {
use std::collections::BTreeMap;
use std::fs;
use tempfile::TempDir;
use yah_mesofact_bundle::{
publish_bundle, BundleHash, BundleManifest, BundleRuntime, SCHEMA_VERSION,
};
use yah_object_store::InMemoryObjectStore;
#[test]
fn cloud_can_publish_a_bundle_through_the_crate_surface() {
let store = InMemoryObjectStore::new();
let src = TempDir::new().unwrap();
fs::create_dir_all(src.path().join("app")).unwrap();
fs::write(src.path().join("app/index.html"), b"<html>").unwrap();
let mut content = BTreeMap::new();
content.insert("app/index.html".to_string(), BundleHash::of(b"<html>"));
let manifest = BundleManifest {
schema_version: SCHEMA_VERSION,
requires_contract: yah_mesofact_bundle::BUNDLE_CONTRACT_VERSION,
name: "yah-marketing".to_string(),
runtime: BundleRuntime::Mesofact {
version: "0.8.18".into(),
},
content,
};
fs::write(
src.path().join("manifest.toml"),
manifest.to_toml_string().unwrap(),
)
.unwrap();
let report = publish_bundle(&store, src.path()).unwrap();
assert_eq!(report.digest, manifest.digest());
assert_eq!(report.uploaded.len(), 1);
assert!(report.manifest_uploaded);
}
}