use cuddle_ci::{Context, MainAction, PullRequestAction}; use dagger_sdk::{Container, HostDirectoryOptsBuilder, PortForward, ServiceUpOptsBuilder}; const UPDATE_DEPLOYMENT_IMAGE: &str = "docker.io/kasperhermansen/update-deployment:1690401410"; const CADDY_IMAGE: &str = "caddy:2.10.0"; const ZOLA_PLATFORM: &str = "x86_64"; const ZOLA_VERSION: &str = "v0.21.0"; const DEBIAN_EDITION: &str = "bookworm"; const DEBIAN_PLATFORM: &str = "amd64"; #[derive(Clone)] pub struct BlogComponent { client: dagger_sdk::Query, } impl BlogComponent { pub async fn run(&self) -> eyre::Result<()> { let (_, container) = build(self.client.clone()).await?; container .as_service() .up_opts( ServiceUpOptsBuilder::default() .ports(vec![PortForward { backend: 8000, frontend: 8000, protocol: dagger_sdk::NetworkProtocol::Tcp, }]) .build()?, ) .await?; Ok(()) } } #[async_trait::async_trait] impl PullRequestAction for BlogComponent { async fn execute_pull_request(&self, _ctx: &mut Context) -> eyre::Result<()> { let (tag, container) = build(self.client.clone()).await?; deploy(self.client.clone(), tag, container).await?; Ok(()) } } #[async_trait::async_trait] impl MainAction for BlogComponent { async fn execute_main(&self, _ctx: &mut Context) -> eyre::Result<()> { let (tag, container) = build(self.client.clone()).await?; deploy(self.client.clone(), tag, container).await?; Ok(()) } } async fn build(client: dagger_sdk::Query) -> eyre::Result<(i64, Container)> { let src = client.host().directory_opts( ".", HostDirectoryOptsBuilder::default() .exclude(vec![".git", "node_modules", "public", "ci", "target"]) .build()?, ); // let github_zola_download: String = format!("https://github.com/barnumbirr/zola-debian/releases/download/v{ZOLA_VERSION}/zola_{ZOLA_VERSION}_{DEBIAN_PLATFORM}_{DEBIAN_EDITION}.deb"); let node_cache = client.cache_volume("node_cache"); let debian_cache = client.cache_volume("debian_cache"); let styles_file = client .container() .from("node:16") .with_workdir("/app") .with_directory(".", src.clone()) .with_mounted_cache("node_modules", node_cache) .with_exec(vec!["yarn"]) .with_exec(vec!["yarn", "compile"]) .file("static/styles/styles.css"); let tag = chrono::Utc::now().timestamp(); let zola_download_link = format!("https://github.com/getzola/zola/releases/download/{ZOLA_VERSION}/zola-{ZOLA_VERSION}-{ZOLA_PLATFORM}-unknown-linux-gnu.tar.gz"); let dist_dir = client .container_opts( dagger_sdk::QueryContainerOptsBuilder::default() .platform(format!("linux/{DEBIAN_PLATFORM}")) .build()?, ) .from(format!("debian:{DEBIAN_EDITION}")) // .with_exec(vec!["apt", "update"]) // .with_exec(vec!["apt", "install", "wget", "-y"]) .with_workdir("/mnt") .with_file("/mnt/zola.tar.gz", client.http(zola_download_link)) .with_exec(vec!["tar", "-xvf", "/mnt/zola.tar.gz"]) .with_exec(vec!["mv", "/mnt/zola", "/usr/local/bin/zola"]) // .with_mounted_cache("/mnt", debian_cache) // .with_exec(vec!["wget", &github_zola_download]) // .with_exec(vec![ // "dpkg", // "-i", // format!("zola_{ZOLA_VERSION}_{DEBIAN_PLATFORM}_{DEBIAN_EDITION}.deb").as_str(), // ]) .with_workdir("/app") .with_directory(".", src) .with_file("static/styles/styles.css", styles_file) .with_exec(vec!["zola", "build"]) .directory("public"); let caddy_file = client.host().directory("deployment").file("Caddyfile"); let dep_image = client .container() .from(CADDY_IMAGE) .with_directory("/usr/share/caddy", dist_dir) .with_file("/etc/caddy/Caddyfile", caddy_file); Ok((tag, dep_image)) } async fn deploy(client: dagger_sdk::Query, tag: i64, container: Container) -> eyre::Result<()> { container .publish(format!("kasperhermansen/kasperhermansen-blog:{tag}")) .await?; client .container() .from(UPDATE_DEPLOYMENT_IMAGE) .with_env_variable("GIT_USERNAME", "kjuulh") .with_env_variable("GIT_PASSWORD", std::env::var("GIT_PASSWORD").unwrap()) .with_exec(vec![ "update-deployment", "--repo", "https://git.front.kjuulh.io/kjuulh/blog-deployment.git", "--service", "blog", "--image", &format!("kasperhermansen/kasperhermansen-blog:{tag}"), ]) .exit_code() .await?; Ok(()) } #[tokio::main] async fn main() -> eyre::Result<()> { let _ = dotenvy::dotenv(); dagger_sdk::connect(|client| async move { let blog_component = &BlogComponent { client }; let run = std::env::var("RUN").unwrap_or_default(); if !run.is_empty() { blog_component.run().await?; return Ok(()); } cuddle_ci::CuddleCI::default() .with_main(blog_component) .execute(std::env::args()) .await?; Ok(()) }) .await?; Ok(()) }