Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(deps): support versioning #116

Merged
merged 2 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ pretty_yaml = "0.5"
yaml_parser = "0.2"
const_format = "0.2"
dialoguer = "0.11"
semver = { version = "1", features = ["serde"] }

[dependencies]
rari-doc.workspace = true
Expand Down
19 changes: 10 additions & 9 deletions crates/rari-cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,15 +229,6 @@ fn main() -> Result<(), Error> {
info!("Using env_file: {}", env_file.display())
}
let cli = Cli::parse();
if !cli.skip_updates {
rari_deps::webref_css::update_webref_css(rari_types::globals::data_dir())?;
rari_deps::web_features::update_web_features(rari_types::globals::data_dir())?;
rari_deps::bcd::update_bcd(rari_types::globals::data_dir())?;
rari_deps::mdn_data::update_mdn_data(rari_types::globals::data_dir())?;
rari_deps::web_ext_examples::update_web_ext_examples(rari_types::globals::data_dir())?;
rari_deps::popularities::update_popularities(rari_types::globals::data_dir())?;
}

let fmt_filter =
filter::Targets::new().with_target("rari_doc", cli.verbose.tracing_level_filter());

Expand All @@ -249,6 +240,7 @@ fn main() -> Result<(), Error> {
let cli_filter = filter::Targets::new()
.with_target("rari", cli_level)
.with_target("rari_tools", cli_level)
.with_target("rari_deps", cli_level)
.with_target("rari_doc", LevelFilter::OFF);

let memory_filter = filter::Targets::new()
Expand All @@ -273,6 +265,15 @@ fn main() -> Result<(), Error> {
.with(memory_layer.clone().with_filter(memory_filter))
.init();

if !cli.skip_updates {
rari_deps::webref_css::update_webref_css(rari_types::globals::data_dir())?;
rari_deps::web_features::update_web_features(rari_types::globals::data_dir())?;
rari_deps::bcd::update_bcd(rari_types::globals::data_dir())?;
rari_deps::mdn_data::update_mdn_data(rari_types::globals::data_dir())?;
rari_deps::web_ext_examples::update_web_ext_examples(rari_types::globals::data_dir())?;
rari_deps::popularities::update_popularities(rari_types::globals::data_dir())?;
}

match cli.command {
Commands::Build(args) => {
let mut settings = Settings::new()?;
Expand Down
4 changes: 4 additions & 0 deletions crates/rari-deps/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ serde_json.workspace = true
chrono.workspace = true
thiserror.workspace = true
reqwest.workspace = true
url.workspace = true
indexmap.workspace = true
tracing.workspace = true
semver.workspace = true

css-syntax-types = { path = "../css-syntax-types" }
tar = "0.4"
Expand Down
5 changes: 3 additions & 2 deletions crates/rari-deps/src/bcd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ use std::collections::HashMap;
use std::fs;
use std::path::Path;

use rari_types::globals::deps;
use rari_utils::io::read_to_string;
use serde_json::Value;

use crate::error::DepsError;
use crate::npm::get_package;

pub fn update_bcd(base_path: &Path) -> Result<(), DepsError> {
if let Some(path) = get_package("@mdn/browser-compat-data", None, base_path)? {
if let Some(path) = get_package("@mdn/browser-compat-data", &deps().bcd, base_path)? {
extract_spec_urls(&path)?;
}
get_package("web-specs", None, base_path)?;
get_package("web-specs", &deps().web_specs, base_path)?;
Ok(())
}

Expand Down
9 changes: 9 additions & 0 deletions crates/rari-deps/src/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use reqwest::blocking::Response;

pub fn get(url: impl AsRef<str>) -> reqwest::Result<Response> {
reqwest::blocking::ClientBuilder::new()
.user_agent("mdn/rari")
.build()?
.get(url.as_ref())
.send()
}
3 changes: 2 additions & 1 deletion crates/rari-deps/src/current.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use chrono::{DateTime, Utc};
use semver::Version;
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize, Default, Debug)]
pub struct Current {
pub latest_last_check: Option<DateTime<Utc>>,
pub version: String,
pub current_version: Option<Version>,
}
2 changes: 2 additions & 0 deletions crates/rari-deps/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ pub enum DepsError {
WebRefMissingTarballError,
#[error("Invalid github version")]
InvalidGitHubVersion,
#[error("Invalid github version")]
VersionNotFound,
}
3 changes: 2 additions & 1 deletion crates/rari-deps/src/external_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use chrono::{DateTime, Duration, Utc};
use rari_utils::io::read_to_string;
use serde::{Deserialize, Serialize};

use crate::client::get;
use crate::error::DepsError;

#[derive(Deserialize, Serialize, Default, Debug)]
Expand All @@ -26,7 +27,7 @@ pub fn get_json(name: &str, url: &str, out_path: &Path) -> Result<Option<PathBuf
fs::remove_dir_all(&package_path)?;
}
fs::create_dir_all(&package_path)?;
let buf = reqwest::blocking::get(url)?.bytes()?;
let buf = get(url)?.bytes()?;

let out_file = package_path.join("data.json");
let file = File::create(out_file).unwrap();
Expand Down
99 changes: 58 additions & 41 deletions crates/rari-deps/src/github_release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,81 +4,98 @@ use std::path::{Path, PathBuf};

use chrono::{Duration, Utc};
use rari_utils::io::read_to_string;
use reqwest::redirect::Policy;
use semver::{Version, VersionReq};
use serde::Deserialize;

use crate::client::get;
use crate::current::Current;
use crate::error::DepsError;
#[derive(Deserialize, Debug, Clone)]
struct VersionEntry {
tag_name: Option<String>,
}

type Releases = Vec<VersionEntry>;

fn get_version(repo: &str, version_req: &VersionReq) -> Result<(Version, String), DepsError> {
let releases = get(format!(
"https://api.github.com/repos/{repo}/releases?per_page=10"
))?;

let releases: Releases = serde_json::from_value(releases.json()?)?;
if let Some(version) = releases.iter().find_map(|k| {
let version = k
.tag_name
.as_ref()
.and_then(|v| Version::parse(v.trim_start_matches('v')).ok());
if version
.as_ref()
.map(|v| version_req.matches(v))
.unwrap_or_default()
{
version.map(|version| (version, k.tag_name.clone().unwrap()))
} else {
None
}
}) {
Ok(version)
} else {
Err(DepsError::VersionNotFound)
}
}
/// Download a github release artifact for a given version (defaults to latest).
pub fn get_artifact(
base_url: &str,
repo: &str,
artifact: &str,
name: &str,
version: Option<&str>,
version_req: &Option<VersionReq>,
out_path: &Path,
) -> Result<Option<PathBuf>, DepsError> {
let version = version.unwrap_or("latest");
let star = VersionReq::default();

let version_req = version_req.as_ref().unwrap_or(&star);
let package_path = out_path.join(name);
let last_check_path = package_path.join("last_check.json");
let now = Utc::now();
let current = read_to_string(last_check_path)
.ok()
.and_then(|current| serde_json::from_str::<Current>(&current).ok())
.unwrap_or_default();
if version != current.version
|| version == "latest"
&& current.latest_last_check.unwrap_or_default() < now - Duration::days(1)
if !current
.current_version
.as_ref()
.map(|v| version_req.matches(v))
.unwrap_or_default()
|| current.latest_last_check.unwrap_or_default() < now - Duration::days(1)
{
let prev_url = format!(
"{base_url}/releases/download/{}/{artifact}",
current.version
);
let url = if version == "latest" {
let client = reqwest::blocking::ClientBuilder::default()
.redirect(Policy::none())
.build()?;
let res = client
.get(format!("{base_url}/releases/latest/download/{artifact}"))
.send()?;
res.headers()
.get("location")
.ok_or(DepsError::InvalidGitHubVersion)?
.to_str()?
.to_string()
} else {
format!("{base_url}/releases/download/{version}/{artifact}")
};
let (version, tag_name) = get_version(repo, version_req)?;
let url = format!("https://github.com/{repo}/releases/download/{tag_name}/{artifact}");

let artifact_path = package_path.join(artifact);
let download_update = if artifact_path.exists() {
prev_url != url
} else {
true
};
let download_update = current.current_version.as_ref() != Some(&version);

if download_update {
tracing::info!("Updating {repo} ({artifact}) to {version}");
if package_path.exists() {
fs::remove_dir_all(&package_path)?;
}
fs::create_dir_all(&package_path)?;
let mut buf = vec![];
let _ = reqwest::blocking::get(url)?.read_to_end(&mut buf)?;
let _ = get(url)?.read_to_end(&mut buf)?;

let file = File::create(artifact_path).unwrap();
let mut buffed = BufWriter::new(file);

buffed.write_all(&buf)?;
}

if version == "latest" {
fs::write(
package_path.join("last_check.json"),
serde_json::to_string_pretty(&Current {
version: version.to_string(),
latest_last_check: Some(now),
})?,
)?;
}
fs::write(
package_path.join("last_check.json"),
serde_json::to_string_pretty(&Current {
current_version: Some(version),
latest_last_check: Some(now),
})?,
)?;
if download_update {
return Ok(Some(package_path));
}
Expand Down
1 change: 1 addition & 0 deletions crates/rari-deps/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod bcd;
pub mod client;
pub mod current;
pub mod error;
pub mod external_json;
Expand Down
4 changes: 3 additions & 1 deletion crates/rari-deps/src/mdn_data.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use std::path::Path;

use rari_types::globals::deps;

use crate::error::DepsError;
use crate::npm::get_package;

pub fn update_mdn_data(base_path: &Path) -> Result<(), DepsError> {
get_package("mdn-data", None, base_path)?;
get_package("mdn-data", &deps().mdn_data, base_path)?;
Ok(())
}
Loading
Loading