Skip to content

Commit b1153c5

Browse files
authored
Add integration tests verifying lockfile stays current after release (#70)
1 parent 6fd40c0 commit b1153c5

2 files changed

Lines changed: 204 additions & 0 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
cargo-changeset: patch
3+
---
4+
Add integration tests verifying lockfile stays current after release
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
use std::fs;
2+
use std::process::Command;
3+
4+
use tempfile::TempDir;
5+
6+
fn init_git_repo(dir: &TempDir) {
7+
Command::new("git")
8+
.args(["init", "--initial-branch=main"])
9+
.current_dir(dir.path())
10+
.output()
11+
.expect("failed to init git repo");
12+
13+
Command::new("git")
14+
.args(["config", "user.email", "test@example.com"])
15+
.current_dir(dir.path())
16+
.output()
17+
.expect("failed to configure git email");
18+
19+
Command::new("git")
20+
.args(["config", "user.name", "Test"])
21+
.current_dir(dir.path())
22+
.output()
23+
.expect("failed to configure git name");
24+
}
25+
26+
fn git_add_and_commit(dir: &TempDir, message: &str) {
27+
Command::new("git")
28+
.args(["add", "-A"])
29+
.current_dir(dir.path())
30+
.output()
31+
.expect("failed to git add");
32+
33+
Command::new("git")
34+
.args(["commit", "-m", message])
35+
.current_dir(dir.path())
36+
.output()
37+
.expect("failed to git commit");
38+
}
39+
40+
fn lockfile_hash(dir: &TempDir) -> Vec<u8> {
41+
let output = Command::new("git")
42+
.args(["hash-object", "Cargo.lock"])
43+
.current_dir(dir.path())
44+
.output()
45+
.expect("failed to hash Cargo.lock");
46+
47+
output.stdout
48+
}
49+
50+
fn write_changeset(dir: &TempDir, filename: &str, package: &str, bump: &str, summary: &str) {
51+
let content = format!(
52+
r#"---
53+
"{package}": {bump}
54+
---
55+
56+
{summary}
57+
"#
58+
);
59+
fs::write(
60+
dir.path().join(".changeset/changesets").join(filename),
61+
content,
62+
)
63+
.expect("write changeset");
64+
}
65+
66+
fn setup_workspace_with_dependency() -> TempDir {
67+
let dir = TempDir::new().expect("create temp dir");
68+
69+
init_git_repo(&dir);
70+
71+
fs::write(
72+
dir.path().join("Cargo.toml"),
73+
r#"[workspace]
74+
members = ["crates/*"]
75+
resolver = "2"
76+
77+
[workspace.dependencies]
78+
crate-a = { path = "crates/crate-a", version = "1.0.0" }
79+
"#,
80+
)
81+
.expect("write workspace Cargo.toml");
82+
83+
fs::create_dir_all(dir.path().join("crates/crate-a/src")).expect("create crate-a dir");
84+
fs::write(
85+
dir.path().join("crates/crate-a/Cargo.toml"),
86+
r#"[package]
87+
name = "crate-a"
88+
version = "1.0.0"
89+
edition = "2021"
90+
"#,
91+
)
92+
.expect("write crate-a Cargo.toml");
93+
fs::write(dir.path().join("crates/crate-a/src/lib.rs"), "").expect("write crate-a lib.rs");
94+
95+
fs::create_dir_all(dir.path().join("crates/crate-b/src")).expect("create crate-b dir");
96+
fs::write(
97+
dir.path().join("crates/crate-b/Cargo.toml"),
98+
r#"[package]
99+
name = "crate-b"
100+
version = "2.0.0"
101+
edition = "2021"
102+
103+
[dependencies]
104+
crate-a = { workspace = true }
105+
"#,
106+
)
107+
.expect("write crate-b Cargo.toml");
108+
fs::write(dir.path().join("crates/crate-b/src/lib.rs"), "").expect("write crate-b lib.rs");
109+
110+
fs::create_dir_all(dir.path().join(".changeset/changesets"))
111+
.expect("create .changeset/changesets dir");
112+
113+
let output = Command::new("cargo")
114+
.args(["generate-lockfile"])
115+
.current_dir(dir.path())
116+
.output()
117+
.expect("failed to run cargo generate-lockfile");
118+
assert!(
119+
output.status.success(),
120+
"cargo generate-lockfile failed: {}",
121+
String::from_utf8_lossy(&output.stderr)
122+
);
123+
124+
git_add_and_commit(&dir, "Initial commit");
125+
126+
dir
127+
}
128+
129+
macro_rules! cargo_changeset {
130+
() => {
131+
assert_cmd::cargo::cargo_bin_cmd!("cargo-changeset")
132+
};
133+
}
134+
135+
#[test]
136+
fn release_lockfile_not_dirtied_by_cargo_check() {
137+
let workspace = setup_workspace_with_dependency();
138+
write_changeset(&workspace, "fix.md", "crate-a", "patch", "Fix a bug");
139+
git_add_and_commit(&workspace, "Add changeset");
140+
141+
cargo_changeset!()
142+
.arg("release")
143+
.current_dir(workspace.path())
144+
.assert()
145+
.success();
146+
147+
let hash_before = lockfile_hash(&workspace);
148+
149+
let check_output = Command::new("cargo")
150+
.args(["check"])
151+
.current_dir(workspace.path())
152+
.output()
153+
.expect("failed to run cargo check");
154+
assert!(
155+
check_output.status.success(),
156+
"cargo check failed: {}",
157+
String::from_utf8_lossy(&check_output.stderr)
158+
);
159+
160+
let hash_after = lockfile_hash(&workspace);
161+
162+
assert_eq!(
163+
hash_before, hash_after,
164+
"cargo check should not change Cargo.lock after release — \
165+
the release commit must include an up-to-date lockfile"
166+
);
167+
}
168+
169+
#[test]
170+
fn release_lockfile_correct_after_minor_bump_with_workspace_dep() {
171+
let workspace = setup_workspace_with_dependency();
172+
write_changeset(&workspace, "feat.md", "crate-a", "minor", "Add a feature");
173+
git_add_and_commit(&workspace, "Add changeset");
174+
175+
cargo_changeset!()
176+
.arg("release")
177+
.current_dir(workspace.path())
178+
.assert()
179+
.success();
180+
181+
let hash_before = lockfile_hash(&workspace);
182+
183+
let check_output = Command::new("cargo")
184+
.args(["check"])
185+
.current_dir(workspace.path())
186+
.output()
187+
.expect("failed to run cargo check");
188+
assert!(
189+
check_output.status.success(),
190+
"cargo check failed: {}",
191+
String::from_utf8_lossy(&check_output.stderr)
192+
);
193+
194+
let hash_after = lockfile_hash(&workspace);
195+
196+
assert_eq!(
197+
hash_before, hash_after,
198+
"cargo check should not change Cargo.lock after minor bump release"
199+
);
200+
}

0 commit comments

Comments
 (0)