mirror of
https://github.com/meilisearch/meilisearch.git
synced 2025-12-08 21:55:42 +00:00
Introduce the first working version of the tool
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -7806,6 +7806,7 @@ dependencies = [
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"reqwest",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
|
||||
@@ -22,6 +22,7 @@ reqwest = { version = "0.12.24", features = [
|
||||
"json",
|
||||
"rustls-tls",
|
||||
], default-features = false }
|
||||
semver = "1.0.27"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = "1.0.145"
|
||||
sha2 = "0.10.9"
|
||||
|
||||
@@ -23,7 +23,7 @@ pub fn default_dashboard_url() -> String {
|
||||
|
||||
/// Run benchmarks from a workload
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct BenchDeriveArgs {
|
||||
pub struct BenchArgs {
|
||||
/// Common arguments shared with other commands
|
||||
#[command(flatten)]
|
||||
common: CommonArgs,
|
||||
@@ -59,7 +59,7 @@ pub struct BenchDeriveArgs {
|
||||
binary_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
pub fn run(args: BenchDeriveArgs) -> anyhow::Result<()> {
|
||||
pub fn run(args: BenchArgs) -> anyhow::Result<()> {
|
||||
setup_logs(&args.common.log_filter)?;
|
||||
|
||||
// fetch environment and build info
|
||||
|
||||
@@ -12,7 +12,7 @@ use tokio::task::JoinHandle;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::dashboard::DashboardClient;
|
||||
use super::BenchDeriveArgs;
|
||||
use super::BenchArgs;
|
||||
use crate::common::assets::{self, Asset};
|
||||
use crate::common::client::Client;
|
||||
use crate::common::command::{run_commands, Command};
|
||||
@@ -40,7 +40,7 @@ async fn run_workload_commands(
|
||||
meili_client: &Arc<Client>,
|
||||
workload_uuid: Uuid,
|
||||
workload: &BenchWorkload,
|
||||
args: &BenchDeriveArgs,
|
||||
args: &BenchArgs,
|
||||
run_number: u16,
|
||||
) -> anyhow::Result<JoinHandle<anyhow::Result<File>>> {
|
||||
let report_folder = &args.report_folder;
|
||||
@@ -95,7 +95,7 @@ pub async fn execute(
|
||||
invocation_uuid: Uuid,
|
||||
master_key: Option<&str>,
|
||||
workload: BenchWorkload,
|
||||
args: &BenchDeriveArgs,
|
||||
args: &BenchArgs,
|
||||
binary_path: Option<&Path>,
|
||||
) -> anyhow::Result<()> {
|
||||
assets::fetch_assets(assets_client, &workload.assets, &args.common.asset_folder).await?;
|
||||
@@ -143,7 +143,7 @@ async fn execute_run(
|
||||
workload_uuid: Uuid,
|
||||
master_key: Option<&str>,
|
||||
workload: &BenchWorkload,
|
||||
args: &BenchDeriveArgs,
|
||||
args: &BenchArgs,
|
||||
binary_path: Option<&Path>,
|
||||
run_number: u16,
|
||||
) -> anyhow::Result<tokio::task::JoinHandle<anyhow::Result<std::fs::File>>> {
|
||||
|
||||
@@ -1,16 +1,34 @@
|
||||
use std::collections::HashSet;
|
||||
use std::{collections::HashSet, process::Stdio};
|
||||
|
||||
use anyhow::Context;
|
||||
use clap::Parser;
|
||||
use xtask::{bench::BenchDeriveArgs, test::TestDeriveArgs};
|
||||
use semver::{Prerelease, Version};
|
||||
use xtask::{bench::BenchArgs, test::TestArgs};
|
||||
|
||||
/// This is the version of the crate but also the current Meilisearch version
|
||||
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
/// List features available in the workspace
|
||||
#[derive(Parser, Debug)]
|
||||
struct ListFeaturesDeriveArgs {
|
||||
struct ListFeaturesArgs {
|
||||
/// Feature to exclude from the list. Use a comma to separate multiple features.
|
||||
#[arg(short, long, value_delimiter = ',')]
|
||||
exclude_feature: Vec<String>,
|
||||
}
|
||||
|
||||
/// Create a git tag for the current version
|
||||
///
|
||||
/// The tag will of the form prototype-v<version>-<name>.<increment>
|
||||
#[derive(Parser, Debug)]
|
||||
struct PrototypeArgs {
|
||||
/// Name of the prototype to generate
|
||||
name: String,
|
||||
/// If true refuses to increment the tag if it already exists
|
||||
/// else refuses to generate new tag and expect the tag to exist.
|
||||
#[arg(long)]
|
||||
generate_new: bool,
|
||||
}
|
||||
|
||||
/// Utilitary commands
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about)]
|
||||
@@ -18,9 +36,10 @@ struct ListFeaturesDeriveArgs {
|
||||
#[command(bin_name = "cargo xtask")]
|
||||
#[allow(clippy::large_enum_variant)] // please, that's enough...
|
||||
enum Command {
|
||||
ListFeatures(ListFeaturesDeriveArgs),
|
||||
Bench(BenchDeriveArgs),
|
||||
Test(TestDeriveArgs),
|
||||
ListFeatures(ListFeaturesArgs),
|
||||
Bench(BenchArgs),
|
||||
GeneratePrototype(PrototypeArgs),
|
||||
Test(TestArgs),
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
@@ -28,12 +47,13 @@ fn main() -> anyhow::Result<()> {
|
||||
match args {
|
||||
Command::ListFeatures(args) => list_features(args),
|
||||
Command::Bench(args) => xtask::bench::run(args)?,
|
||||
Command::GeneratePrototype(args) => generate_prototype(args)?,
|
||||
Command::Test(args) => xtask::test::run(args)?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn list_features(args: ListFeaturesDeriveArgs) {
|
||||
fn list_features(args: ListFeaturesArgs) {
|
||||
let exclude_features: HashSet<_> = args.exclude_feature.into_iter().collect();
|
||||
let metadata = cargo_metadata::MetadataCommand::new().no_deps().exec().unwrap();
|
||||
let features: Vec<String> = metadata
|
||||
@@ -46,3 +66,106 @@ fn list_features(args: ListFeaturesDeriveArgs) {
|
||||
let features = features.join(" ");
|
||||
println!("{features}")
|
||||
}
|
||||
|
||||
fn generate_prototype(args: PrototypeArgs) -> anyhow::Result<()> {
|
||||
let PrototypeArgs { name, generate_new: create_new } = args;
|
||||
|
||||
if name.rsplit_once(['.', '-']).filter(|(_, t)| t.chars().all(char::is_numeric)).is_some() {
|
||||
anyhow::bail!(
|
||||
"The increment must not be part of the name and will be rather incremented by this command."
|
||||
);
|
||||
}
|
||||
|
||||
// 1. Fetch the crate version
|
||||
let version = Version::parse(VERSION).context("while semver-parsing the crate version")?;
|
||||
|
||||
// 2. Pull tags from remote and retrieve last prototype tag
|
||||
std::process::Command::new("git")
|
||||
.arg("fetch")
|
||||
.arg("--tags")
|
||||
.stderr(Stdio::inherit())
|
||||
.stdout(Stdio::inherit())
|
||||
.status()?;
|
||||
|
||||
let output = std::process::Command::new("git")
|
||||
.arg("tag")
|
||||
.args(["--list", "prototype-v*"])
|
||||
.stderr(Stdio::inherit())
|
||||
.output()?;
|
||||
let output =
|
||||
String::try_from(output.stdout).context("while converting the tag list into a string")?;
|
||||
|
||||
let mut highest_increment = None;
|
||||
for tag in output.lines() {
|
||||
let Some(version) = tag.strip_prefix("prototype-v") else {
|
||||
continue;
|
||||
};
|
||||
let Ok(version) = Version::parse(version) else {
|
||||
continue;
|
||||
};
|
||||
let Ok(proto) = PrototypePrerelease::from_str(version.pre.as_str()) else {
|
||||
continue;
|
||||
};
|
||||
if proto.name() == name {
|
||||
highest_increment = match highest_increment {
|
||||
Some(last) if last < proto.increment() => Some(proto.increment()),
|
||||
Some(last) => Some(last),
|
||||
None => Some(proto.increment()),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Generate the new tag name (without git, just a string)
|
||||
let increment = match (create_new, highest_increment) {
|
||||
(true, None) => 0,
|
||||
(true, Some(increment)) => anyhow::bail!(
|
||||
"A prototype with the name `{name}` already exists with increment `{increment}`"
|
||||
),
|
||||
(false, None) => anyhow::bail!(
|
||||
"Prototype `{name}` is missing and must exist to be incremented.\n\
|
||||
Use the --generate-new flag to create a new prototype with an increment at 0."
|
||||
),
|
||||
(false, Some(increment)) => {
|
||||
increment.checked_add(1).context("While incrementing by one the increment")?
|
||||
}
|
||||
};
|
||||
|
||||
// Note that we cannot have leading zeros in the increment
|
||||
let pre = format!("{name}.{increment}").parse().context("while parsing pre-release name")?;
|
||||
let tag_name = Version { pre, ..version };
|
||||
println!("prototype-v{tag_name}");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
struct PrototypePrerelease {
|
||||
pre: Prerelease,
|
||||
}
|
||||
|
||||
impl PrototypePrerelease {
|
||||
fn from_str(s: &str) -> anyhow::Result<Self> {
|
||||
Prerelease::new(s)
|
||||
.map_err(Into::into)
|
||||
.and_then(|pre| {
|
||||
if pre.rsplit_once('.').is_some() {
|
||||
Ok(pre)
|
||||
} else {
|
||||
Err(anyhow::anyhow!("Invalid prototype name, missing name or increment"))
|
||||
}
|
||||
})
|
||||
.map(|pre| PrototypePrerelease { pre })
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
self.pre.rsplit_once('.').expect("Missing prototype name").0
|
||||
}
|
||||
|
||||
fn increment(&self) -> u32 {
|
||||
self.pre
|
||||
.as_str()
|
||||
.rsplit_once('.')
|
||||
.map(|(_, tail)| tail.parse().expect("Invalid increment"))
|
||||
.expect("Missing increment")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ pub use workload::TestWorkload;
|
||||
|
||||
/// Run tests from a workload
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct TestDeriveArgs {
|
||||
pub struct TestArgs {
|
||||
/// Common arguments shared with other commands
|
||||
#[command(flatten)]
|
||||
common: CommonArgs,
|
||||
@@ -31,7 +31,7 @@ pub struct TestDeriveArgs {
|
||||
pub add_missing_responses: bool,
|
||||
}
|
||||
|
||||
pub fn run(args: TestDeriveArgs) -> anyhow::Result<()> {
|
||||
pub fn run(args: TestArgs) -> anyhow::Result<()> {
|
||||
let rt = tokio::runtime::Builder::new_current_thread().enable_io().enable_time().build()?;
|
||||
let _scope = rt.enter();
|
||||
|
||||
@@ -40,7 +40,7 @@ pub fn run(args: TestDeriveArgs) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn run_inner(args: TestDeriveArgs) -> anyhow::Result<()> {
|
||||
async fn run_inner(args: TestArgs) -> anyhow::Result<()> {
|
||||
setup_logs(&args.common.log_filter)?;
|
||||
|
||||
// setup clients
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::common::command::{run_commands, Command};
|
||||
use crate::common::instance::Binary;
|
||||
use crate::common::process::{self, delete_db, kill_meili};
|
||||
use crate::common::workload::Workload;
|
||||
use crate::test::TestDeriveArgs;
|
||||
use crate::test::TestArgs;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(untagged)]
|
||||
@@ -81,7 +81,7 @@ pub struct TestWorkload {
|
||||
impl TestWorkload {
|
||||
pub async fn run(
|
||||
mut self,
|
||||
args: &TestDeriveArgs,
|
||||
args: &TestArgs,
|
||||
assets_client: &Client,
|
||||
meili_client: &Arc<Client>,
|
||||
asset_folder: &'static str,
|
||||
|
||||
Reference in New Issue
Block a user