Skip to content
This repository has been archived by the owner on Dec 21, 2024. It is now read-only.

Commit

Permalink
chore(deno-embed): embed deno in toolchain (#374)
Browse files Browse the repository at this point in the history
  • Loading branch information
NathanFlurry committed Sep 12, 2024
1 parent df04fa3 commit 2b4e24b
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 249 deletions.
18 changes: 4 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/backend-embed/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ async fn main() -> Result<()> {
// Install Deno
let temp_dir = tempfile::tempdir().unwrap();
let data_dir = temp_dir.path().to_path_buf();
let deno = rivet_deno_embed::get_or_download_default_executable(&data_dir).await?;
let deno = rivet_deno_embed::get_or_download_executable(&data_dir).await?;

// Get path to artifacts path
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR")?;
Expand Down
11 changes: 8 additions & 3 deletions packages/deno-embed/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ edition = "2021"

[dependencies]
anyhow = "1.0"
fd-lock = "4.0.2"
reqwest = { version = "0.11", default-features = false, features = ["stream", "blocking", "rustls-tls"] }
tempfile = "3.2"
tokio = { version = "1.38.1", features = ["full"] }

[build-dependencies]
dirs = "5.0.1"
reqwest = { version = "0.11", default-features = false, features = ["blocking", "json", "rustls-tls"] }
serde_json = "1.0.128"
zip = "0.5"

[dev-dependencies]
tempfile = "3.12.0"

106 changes: 106 additions & 0 deletions packages/deno-embed/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
use dirs::cache_dir;
use reqwest::blocking::Client;
use serde_json::Value;
use std::{env, fs, path::Path};
use zip::ZipArchive;

const GITHUB_API_URL: &str = "https://api.github.com/repos/denoland/deno";
const DENO_VERSION: &str = "1.46.3";
const USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"));

fn main() -> Result<(), Box<dyn std::error::Error>> {
let target = env::var("TARGET")?;
let out_dir = env::var("OUT_DIR")?;
let cache_dir = get_cache_dir()?;

let release_data = fetch_release_data()?;
let asset = find_matching_asset(&release_data, &target)?;
let zip_path = download_binary_if_needed(&asset, &cache_dir)?;
let output_path = extract_and_save_binary(&zip_path, &out_dir)?;

println!("cargo:rustc-env=DENO_BINARY_PATH={}", output_path.display());
println!("cargo:rustc-env=DENO_VERSION={DENO_VERSION}");

Ok(())
}

fn fetch_release_data() -> Result<Value, Box<dyn std::error::Error>> {
let release_url = format!("{}/releases/tags/v{}", GITHUB_API_URL, DENO_VERSION);
println!("Fetching release information from: {}", release_url);

let client = Client::new();
let response = client
.get(&release_url)
.header(reqwest::header::USER_AGENT, USER_AGENT)
.send()?;
let status = response.status();
if !status.is_success() {
let error_text = response.text()?;
eprintln!("Error response: {}", error_text);
return Err(format!("HTTP request failed with status {}: {}", status, error_text).into());
}
Ok(response.json()?)
}

fn find_matching_asset<'a>(
release_data: &'a Value,
target: &str,
) -> Result<&'a Value, Box<dyn std::error::Error>> {
let assets = release_data["assets"].as_array().ok_or("No assets found")?;
assets
.iter()
.find(|asset| {
let name = asset["name"].as_str().unwrap();
name.contains(target)
})
.ok_or_else(|| "No matching asset found for the target".into())
}

fn download_binary_if_needed(
asset: &Value,
cache_dir: &Path,
) -> Result<std::path::PathBuf, Box<dyn std::error::Error>> {
let download_url = asset["browser_download_url"].as_str().unwrap();
let file_name = asset["name"].as_str().unwrap();
let zip_path = cache_dir.join(file_name);

if !zip_path.exists() {
println!("Downloading Deno binary from: {}", download_url);

let client = Client::new();
let response = client
.get(download_url)
.header(reqwest::header::USER_AGENT, USER_AGENT)
.send()?
.error_for_status()?;

let mut file = fs::File::create(&zip_path)?;
std::io::copy(&mut response.bytes()?.as_ref(), &mut file)?;
} else {
println!("Using cached Deno binary: {}", zip_path.display());
}

Ok(zip_path)
}

fn extract_and_save_binary(
zip_path: &Path,
out_dir: &str,
) -> Result<std::path::PathBuf, Box<dyn std::error::Error>> {
let file = fs::File::open(zip_path)?;
let mut archive = ZipArchive::new(file)?;
let mut file = archive.by_index(0)?;
let output_path = Path::new(out_dir).join("deno");

let mut output_file = fs::File::create(&output_path)?;
std::io::copy(&mut file, &mut output_file)?;

Ok(output_path)
}

fn get_cache_dir() -> Result<std::path::PathBuf, Box<dyn std::error::Error>> {
let system_cache_dir = cache_dir().ok_or("Failed to get system cache directory")?;
let deno_cache_dir = system_cache_dir.join("deno-embed").join(DENO_VERSION);
fs::create_dir_all(&deno_cache_dir)?;
Ok(deno_cache_dir)
}
Loading

0 comments on commit 2b4e24b

Please sign in to comment.