Skip to content

Commit

Permalink
feat: ability to skip migration of certain contracts/models (#2026)
Browse files Browse the repository at this point in the history
* initial commit

* Revert "initial commit"

This reverts commit 2975876.

* implement skip_migration logic in DojoMetadata so it is profile specific

* do a clean build and migrate

* fix tests

* fix lints

* fix more tests

* fix more lints

* update dev to use skip_migration

* abstract out skipping logic

* clean old manifest times during build to remove unused manifets

* update example

* fix tests

* add test for remove_items

* fix: use world dispatcher snapshot

---------

Co-authored-by: glihm <dev@glihm.net>
  • Loading branch information
lambda-0x and glihm authored Jun 13, 2024
1 parent af5be66 commit 0b8b0e5
Show file tree
Hide file tree
Showing 81 changed files with 14,494 additions and 63 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ crates/benches/bench_results.txt
**/generated
.vscode
bindings
justfile
3 changes: 3 additions & 0 deletions Cargo.lock

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

21 changes: 20 additions & 1 deletion bin/sozo/src/commands/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ use anyhow::{Context, Result};
use clap::Args;
use dojo_bindgen::{BuiltinPlugins, PluginManager};
use dojo_lang::scarb_internal::compile_workspace;
use dojo_world::manifest::MANIFESTS_DIR;
use dojo_world::metadata::dojo_metadata_from_workspace;
use prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE;
use prettytable::{format, Cell, Row, Table};
use scarb::core::{Config, TargetKind};
use scarb::ops::{CompileOpts, FeaturesOpts, FeaturesSelector};
use sozo_ops::statistics::{get_contract_statistics_for_dir, ContractStatistics};
use tracing::trace;

use crate::commands::clean::CleanArgs;

const BYTECODE_SIZE_LABEL: &str = "Bytecode size [in felts]\n(Sierra, Casm)";
const CONTRACT_CLASS_SIZE_LABEL: &str = "Contract Class size [in bytes]\n(Sierra, Casm)";

Expand Down Expand Up @@ -39,6 +43,18 @@ pub struct BuildArgs {

impl BuildArgs {
pub fn run(self, config: &Config) -> Result<()> {
let ws = scarb::ops::read_workspace(config.manifest_path(), config)?;

let profile_name =
ws.current_profile().expect("Scarb profile is expected at this point.").to_string();

// Manifest path is always a file, we can unwrap safely to get the
// parent folder.
let manifest_dir = ws.manifest_path().parent().unwrap().to_path_buf();

let profile_dir = manifest_dir.join(MANIFESTS_DIR).join(profile_name);
CleanArgs::clean_manifests(&profile_dir)?;

let features_opts =
FeaturesOpts { features: FeaturesSelector::AllFeatures, no_default_features: false };

Expand Down Expand Up @@ -110,9 +126,12 @@ impl BuildArgs {
};
trace!(pluginManager=?bindgen, "Generating bindings.");

let ws = scarb::ops::read_workspace(config.manifest_path(), config).unwrap();
let dojo_metadata = dojo_metadata_from_workspace(&ws);

tokio::runtime::Runtime::new()
.unwrap()
.block_on(bindgen.generate())
.block_on(bindgen.generate(dojo_metadata.skip_migration))
.expect("Error generating bindings");

Ok(())
Expand Down
8 changes: 6 additions & 2 deletions bin/sozo/src/commands/clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl CleanArgs {
/// # Arguments
///
/// * `profile_dir` - The directory where the profile files are located.
pub fn clean_manifests(&self, profile_dir: &Utf8PathBuf) -> Result<()> {
pub fn clean_manifests(profile_dir: &Utf8PathBuf) -> Result<()> {
trace!(?profile_dir, "Cleaning manifests.");
let dirs = vec![profile_dir.join(BASE_DIR), profile_dir.join(ABIS_DIR).join(BASE_DIR)];

Expand Down Expand Up @@ -51,7 +51,7 @@ impl CleanArgs {
// By default, this command cleans the build manifests and scarb artifacts.
trace!("Cleaning Scarb artifacts and build manifests.");
scarb::ops::clean(config)?;
self.clean_manifests(&profile_dir)?;
Self::clean_manifests(&profile_dir)?;

if self.all && profile_dir.exists() {
trace!(?profile_dir, "Removing entire profile directory.");
Expand All @@ -65,6 +65,7 @@ impl CleanArgs {
#[cfg(test)]
mod tests {
use dojo_test_utils::compiler;
use dojo_world::metadata::dojo_metadata_from_workspace;
use dojo_world::migration::TxnConfig;
use katana_runner::KatanaRunner;
use sozo_ops::migration;
Expand All @@ -84,6 +85,8 @@ mod tests {

let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap();

let dojo_metadata = dojo_metadata_from_workspace(&ws);

// Plan the migration to generate some manifests other than base.
config.tokio_handle().block_on(async {
migration::migrate(
Expand All @@ -94,6 +97,7 @@ mod tests {
"dojo_examples",
true,
TxnConfig::default(),
dojo_metadata.skip_migration,
)
.await
.unwrap()
Expand Down
14 changes: 11 additions & 3 deletions bin/sozo/src/commands/dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ pub struct DevArgs {
#[command(flatten)]
pub account: AccountOptions,
}

impl DevArgs {
pub fn run(self, config: &Config) -> Result<()> {
let ws = scarb::ops::read_workspace(config.manifest_path(), config)?;
let dojo_metadata = dojo_metadata_from_workspace(&ws);

let env_metadata = if config.manifest_path().exists() {
dojo_metadata_from_workspace(&ws).env().cloned()
dojo_metadata.env().cloned()
} else {
trace!("Manifest path does not exist.");
None
Expand Down Expand Up @@ -97,6 +97,7 @@ impl DevArgs {
&name,
&context.ws,
previous_manifest.clone(),
dojo_metadata.skip_migration.clone(),
)) {
Ok((manifest, address)) => {
previous_manifest = Some(manifest);
Expand Down Expand Up @@ -131,6 +132,7 @@ impl DevArgs {
&name,
&context.ws,
previous_manifest.clone(),
dojo_metadata.skip_migration.clone(),
)) {
Ok((manifest, address)) => {
previous_manifest = Some(manifest);
Expand Down Expand Up @@ -222,12 +224,14 @@ fn build(context: &mut DevContext<'_>) -> Result<()> {
Ok(())
}

// TODO: fix me
async fn migrate<P, S>(
mut world_address: Option<FieldElement>,
account: &SingleOwnerAccount<P, S>,
name: &str,
ws: &Workspace<'_>,
previous_manifest: Option<DeploymentManifest>,
skip_migration: Option<Vec<String>>,
) -> Result<(DeploymentManifest, Option<FieldElement>)>
where
P: Provider + Sync + Send + 'static,
Expand All @@ -243,9 +247,13 @@ where
return Err(anyhow!("Build project using `sozo build` first"));
}

let new_manifest =
let mut new_manifest =
BaseManifest::load_from_path(&manifest_dir.join(MANIFESTS_DIR).join(BASE_DIR))?;

if let Some(skip_manifests) = skip_migration {
new_manifest.remove_items(skip_manifests);
}

let diff = WorldDiff::compute(new_manifest.clone(), previous_manifest);
let total_diffs = diff.count_diffs();
let config = ws.config();
Expand Down
17 changes: 14 additions & 3 deletions bin/sozo/src/commands/migrate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ impl MigrateArgs {
pub fn run(self, config: &Config) -> Result<()> {
trace!(args = ?self);
let ws = scarb::ops::read_workspace(config.manifest_path(), config)?;
let dojo_metadata = dojo_metadata_from_workspace(&ws);

// This variant is tested before the match on `self.command` to avoid
// having the need to spin up a Katana to generate the files.
Expand All @@ -67,7 +68,7 @@ impl MigrateArgs {
}

let env_metadata = if config.manifest_path().exists() {
dojo_metadata_from_workspace(&ws).env().cloned()
dojo_metadata.env().cloned()
} else {
trace!("Manifest path does not exist.");
None
Expand Down Expand Up @@ -99,15 +100,25 @@ impl MigrateArgs {
&name,
true,
TxnConfig::default(),
dojo_metadata.skip_migration,
)
.await
}),
MigrateCommand::Apply { transaction } => config.tokio_handle().block_on(async {
trace!(name, "Applying migration.");
let txn_config: TxnConfig = transaction.into();

migration::migrate(&ws, world_address, rpc_url, account, &name, false, txn_config)
.await
migration::migrate(
&ws,
world_address,
rpc_url,
account,
&name,
false,
txn_config,
dojo_metadata.skip_migration,
)
.await
}),
_ => unreachable!("other case handled above."),
}
Expand Down
9 changes: 6 additions & 3 deletions bin/sozo/tests/register_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod utils;
use camino::Utf8PathBuf;
use dojo_test_utils::compiler;
use dojo_test_utils::migration::prepare_migration;
use dojo_world::metadata::dojo_metadata_from_workspace;
use dojo_world::migration::TxnConfig;
use katana_runner::KatanaRunner;
use scarb::ops;
Expand All @@ -20,11 +21,13 @@ async fn reregister_models() {

let ws = ops::read_workspace(config.manifest_path(), &config)
.unwrap_or_else(|op| panic!("Error building workspace: {op:?}"));
let dojo_metadata = dojo_metadata_from_workspace(&ws);

let base = config.manifest_path().parent().unwrap();
let target_dir = format!("{}/target/dev", base);
let target_path =
ws.target_dir().path_existent().unwrap().join(ws.config().profile().to_string());

let migration = prepare_migration(base.into(), target_dir.into()).unwrap();
let migration =
prepare_migration(source_project_dir, target_path, dojo_metadata.skip_migration).unwrap();

let sequencer = KatanaRunner::new().expect("Failed to start runner.");

Expand Down
4 changes: 4 additions & 0 deletions crates/dojo-bindgen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ thiserror.workspace = true

cainome.workspace = true
dojo-world = { path = "../dojo-world", features = [ "manifest" ] }

[dev-dependencies]
dojo-test-utils = { path = "../dojo-test-utils", features = [ "build-examples" ] }
scarb = { workspace = true }
41 changes: 30 additions & 11 deletions crates/dojo-bindgen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,17 @@ pub struct PluginManager {

impl PluginManager {
/// Generates the bindings for all the given Plugin.
pub async fn generate(&self) -> BindgenResult<()> {
pub async fn generate(&self, skip_migration: Option<Vec<String>>) -> BindgenResult<()> {
if self.builtin_plugins.is_empty() && self.plugins.is_empty() {
return Ok(());
}

let data =
gather_dojo_data(&self.manifest_path, &self.root_package_name, &self.profile_name)?;
let data = gather_dojo_data(
&self.manifest_path,
&self.root_package_name,
&self.profile_name,
skip_migration,
)?;

for plugin in &self.builtin_plugins {
// Get the plugin builder from the plugin enum.
Expand Down Expand Up @@ -111,10 +115,15 @@ fn gather_dojo_data(
manifest_path: &Utf8PathBuf,
root_package_name: &str,
profile_name: &str,
skip_migration: Option<Vec<String>>,
) -> BindgenResult<DojoData> {
let root_dir: Utf8PathBuf = manifest_path.parent().unwrap().into();
let base_manifest_dir: Utf8PathBuf = root_dir.join("manifests").join(profile_name).join("base");
let base_manifest = BaseManifest::load_from_path(&base_manifest_dir)?;
let mut base_manifest = BaseManifest::load_from_path(&base_manifest_dir)?;

if let Some(skip_manifests) = skip_migration {
base_manifest.remove_items(skip_manifests);
}

let mut models = HashMap::new();
let mut contracts = HashMap::new();
Expand Down Expand Up @@ -244,6 +253,9 @@ fn model_name_from_fully_qualified_path(file_name: &str) -> Option<String> {

#[cfg(test)]
mod tests {
use dojo_test_utils::compiler;
use dojo_world::metadata::dojo_metadata_from_workspace;

use super::*;

#[test]
Expand All @@ -254,14 +266,21 @@ mod tests {

#[test]
fn gather_data_ok() {
let data = gather_dojo_data(
&Utf8PathBuf::from("src/test_data/spawn-and-move/Scarb.toml"),
"dojo_example",
"dev",
)
.unwrap();
let manifest_path = Utf8PathBuf::from("src/test_data/spawn-and-move/Scarb.toml");

let config = compiler::copy_tmp_config(
&Utf8PathBuf::from("../../examples/spawn-and-move"),
&Utf8PathBuf::from("../dojo-core"),
);

let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap();
let dojo_metadata = dojo_metadata_from_workspace(&ws);

let data =
gather_dojo_data(&manifest_path, "dojo_example", "dev", dojo_metadata.skip_migration)
.unwrap();

assert_eq!(data.models.len(), 6);
assert_eq!(data.models.len(), 7);

assert_eq!(data.world.name, "dojo_example");

Expand Down
21 changes: 14 additions & 7 deletions crates/dojo-bindgen/src/plugins/typescript_v2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ function convertQueryToToriiClause(query: Query): Clause | undefined {{
constructor(contractAddress: string, account?: Account) {{
super(contractAddress, account);
}}
{}
}}
",
Expand Down Expand Up @@ -630,6 +630,8 @@ mod tests {
use std::io::Read;

use camino::Utf8PathBuf;
use dojo_test_utils::compiler;
use dojo_world::metadata::dojo_metadata_from_workspace;

use super::*;
use crate::gather_dojo_data;
Expand All @@ -646,12 +648,17 @@ mod tests {
let expected_output_without_header =
expected_output.lines().skip(1).collect::<Vec<&str>>().join("\n");

let data = gather_dojo_data(
&Utf8PathBuf::from("src/test_data/spawn-and-move/Scarb.toml"),
"dojo_examples",
"dev",
)
.unwrap();
let manifest_path = Utf8PathBuf::from("src/test_data/spawn-and-move/Scarb.toml");
let config = compiler::copy_tmp_config(
&Utf8PathBuf::from("../../examples/spawn-and-move"),
&Utf8PathBuf::from("../dojo-core"),
);

let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap();
let dojo_metadata = dojo_metadata_from_workspace(&ws);
let data =
gather_dojo_data(&manifest_path, "dojo_examples", "dev", dojo_metadata.skip_migration)
.unwrap();

let actual_output = TypeScriptV2Plugin::generate_code_content(&data);
let actual_output_without_header =
Expand Down
5 changes: 5 additions & 0 deletions crates/dojo-test-utils/src/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use starknet::macros::felt;
pub fn prepare_migration(
manifest_dir: Utf8PathBuf,
target_dir: Utf8PathBuf,
skip_migration: Option<Vec<String>>,
) -> Result<MigrationStrategy> {
// In testing, profile name is always dev.
let profile_name = "dev";
Expand All @@ -19,6 +20,10 @@ pub fn prepare_migration(
)
.unwrap();

if let Some(skip_manifests) = skip_migration {
manifest.remove_items(skip_manifests);
}

let overlay_manifest = OverlayManifest::load_from_path(
&manifest_dir.join(MANIFESTS_DIR).join(profile_name).join(OVERLAYS_DIR),
)
Expand Down
Loading

0 comments on commit 0b8b0e5

Please sign in to comment.