mod common;
use std::fs;
use callisto_cli::cli::{
AddArgs, GlobalArgs, InitArgs, OutputFormat, PlanPublishArgs, PublishArgs, StatusArgs, VersionArgs,
};
use callisto_cli::commands;
use common::setup_polyglot_git_repo;
#[test]
fn test_full_polyglot_workspace_release_lifecycle() {
let dir = setup_polyglot_git_repo();
let root = dir.path();
let global = GlobalArgs {
format: OutputFormat::Json,
cwd: root.to_path_buf(),
dry_run: false,
};
let init_res = commands::init::handle(InitArgs { yes: true }, &global);
assert!(init_res.is_ok());
let add_res = commands::add::handle(
AddArgs {
packages: vec!["core-crate:minor".to_string(), "@myorg/web-app:patch".to_string()],
summary: Some("Improve the core API and the web UI".to_string()),
},
&global,
);
assert!(add_res.is_ok());
assert!(root.join(".changeset").exists());
let status_res = commands::status::handle(
StatusArgs {
strict: false,
strict_graph: false,
check: false,
},
&global,
);
assert!(status_res.is_ok());
let version_res = commands::version::handle(
VersionArgs {
refresh_lockfiles: false,
strict: false,
strict_graph: false,
allow_empty_changesets: false,
},
&global,
);
assert!(version_res.is_ok());
let updated_cargo = fs::read_to_string(root.join("crates/core/Cargo.toml")).unwrap();
assert!(updated_cargo.contains("version = \"0.2.0\""));
let updated_pkg = fs::read_to_string(root.join("packages/web/package.json")).unwrap();
assert!(updated_pkg.contains("\"version\": \"1.0.1\""));
let plan_res = commands::plan_publish::handle(PlanPublishArgs { only: vec![] }, &global);
assert!(plan_res.is_ok());
let dry_run_global = GlobalArgs {
dry_run: true,
..global.clone()
};
let publish_res = commands::publish::handle(PublishArgs { only: vec![] }, &dry_run_global);
assert!(publish_res.is_ok());
}
#[test]
fn test_cst_comment_preservation_on_version_bump() {
let dir = setup_polyglot_git_repo();
let root = dir.path();
let cargo_toml = r#"[package]
name = "core-crate"
version = "0.1.0" # Important inline comment
# Important section comment
edition = "2021"
"#;
fs::write(root.join("crates/core/Cargo.toml"), cargo_toml).unwrap();
let global = GlobalArgs {
format: OutputFormat::Json,
cwd: root.to_path_buf(),
dry_run: false,
};
commands::add::handle(
AddArgs {
packages: vec!["core-crate:patch".to_string()],
summary: Some("Patch update".to_string()),
},
&global,
)
.unwrap();
commands::version::handle(
VersionArgs {
refresh_lockfiles: false,
strict: false,
strict_graph: false,
allow_empty_changesets: false,
},
&global,
)
.unwrap();
let updated_cargo = fs::read_to_string(root.join("crates/core/Cargo.toml")).unwrap();
assert!(updated_cargo.contains("version = \"0.1.1\""));
assert!(updated_cargo.contains("# Important inline comment"));
assert!(updated_cargo.contains("# Important section comment"));
}
#[test]
fn test_compose_pr_body_before_version_and_subpkg_changelog() {
let dir = setup_polyglot_git_repo();
let root = dir.path();
let global = GlobalArgs {
format: OutputFormat::Text,
cwd: root.to_path_buf(),
dry_run: false,
};
commands::add::handle(
AddArgs {
packages: vec!["core-crate:minor".to_string()],
summary: Some("Add new core component API".to_string()),
},
&global,
)
.unwrap();
{
use callisto_cli::runner::CliCommandRunner;
use callisto_cli::workspace::load_workspace;
use callisto_graph::commands::PrBodyOptions;
use callisto_graph::infer::NoInference;
let runner = CliCommandRunner;
let ws = load_workspace(&global, &runner).unwrap();
let opts = PrBodyOptions {
existing_body: None,
labels: vec![],
branch: None,
};
let report = callisto_graph::commands::compose_pr_body(&ws, &NoInference, &opts).unwrap();
assert!(!report.body.is_empty(), "PR body must not be empty before versioning");
assert!(
report.body.contains("core-crate"),
"PR body must mention the changed package 'core-crate', got:\n{}",
report.body
);
assert!(
report.body.contains("minor"),
"PR body must show the bump severity, got:\n{}",
report.body
);
}
let compose_res = commands::compose_pr_body::handle(
callisto_cli::cli::ComposePrBodyArgs {
existing_body: None,
labels: Vec::new(),
branch: None,
},
&global,
);
assert_eq!(compose_res.unwrap(), std::process::ExitCode::SUCCESS);
commands::version::handle(
VersionArgs {
refresh_lockfiles: false,
strict: false,
strict_graph: false,
allow_empty_changesets: false,
},
&global,
)
.unwrap();
let changelog_path = root.join("crates/core/CHANGELOG.md");
assert!(changelog_path.exists(), "crates/core/CHANGELOG.md must exist!");
let changelog_content = fs::read_to_string(&changelog_path).unwrap();
assert!(changelog_content.contains("0.2.0"));
assert!(
changelog_content.contains("Add new core component API"),
"changelog must contain the real changeset summary 'Add new core component API', \
but got:\n{changelog_content}"
);
}
#[test]
fn test_dry_run_flag_preserves_disk_state() {
let dir = setup_polyglot_git_repo();
let root = dir.path();
let global_dry = GlobalArgs {
format: OutputFormat::Json,
cwd: root.to_path_buf(),
dry_run: true,
};
commands::init::handle(
InitArgs { yes: true },
&GlobalArgs {
dry_run: false,
..global_dry.clone()
},
)
.unwrap();
commands::add::handle(
AddArgs {
packages: vec!["core-crate:minor".to_string()],
summary: Some("New feature".to_string()),
},
&GlobalArgs {
dry_run: false,
..global_dry.clone()
},
)
.unwrap();
let version_res = commands::version::handle(
VersionArgs {
refresh_lockfiles: false,
strict: false,
strict_graph: false,
allow_empty_changesets: false,
},
&global_dry,
);
assert!(version_res.is_ok());
let cargo_content = fs::read_to_string(root.join("crates/core/Cargo.toml")).unwrap();
assert!(cargo_content.contains("version = \"0.1.0\""));
}
#[test]
fn test_add_dry_run_does_not_write_changeset_file() {
let dir = setup_polyglot_git_repo();
let root = dir.path();
let global_dry = GlobalArgs {
format: OutputFormat::Text,
cwd: root.to_path_buf(),
dry_run: true,
};
let add_res = commands::add::handle(
AddArgs {
packages: vec!["core-crate:patch".to_string()],
summary: Some("Dry run should not write anything".to_string()),
},
&global_dry,
);
assert!(add_res.is_ok());
let changeset_dir = root.join(".changeset");
let has_changeset_files = changeset_dir.exists()
&& fs::read_dir(&changeset_dir)
.unwrap()
.filter_map(|e| e.ok())
.any(|e| e.path().extension().is_some_and(|ext| ext == "md"));
assert!(
!has_changeset_files,
"callisto add --dry-run must not write a changeset file to disk, but found one in {}",
changeset_dir.display()
);
}