Skip to content

Commit a964514

Browse files
fix: correct rollback order, polish release flow (#152)
This commit corrects a bug where rollback would start undoing steps from the beginning, rather than from the last-failed step. Also generally polished the release code. Signed-off-by: Andrew Lilley Brinker <alilleybrinker@gmail.com>
1 parent a5b7bcb commit a964514

File tree

2 files changed

+20
-51
lines changed

2 files changed

+20
-51
lines changed

xtask/src/pipeline.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ where
5252
if self.force_rollback || forward_err.is_some() {
5353
let forward_err = forward_err.unwrap_or_else(StepError::forced_rollback);
5454

55-
for mut step in completed_steps {
55+
for mut step in completed_steps.into_iter().rev() {
5656
if let Err(backward_err) = backward(step.as_mut()) {
5757
bail!(PipelineError::rollback(forward_err, backward_err));
5858
}

xtask/src/release.rs

Lines changed: 19 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::cli::{Bump, Crate};
22
use crate::pipeline::{Pipeline, Step};
33
use crate::step;
4-
use anyhow::{anyhow, bail, Error, Result};
4+
use anyhow::{anyhow, bail, Result};
55
use cargo_metadata::MetadataCommand;
66
use clap::ArgMatches;
77
use pathbuf::pathbuf;
@@ -24,12 +24,15 @@ pub fn run(args: &ArgMatches) -> Result<()> {
2424
.expect("--execute has a default value, so it should never be missing");
2525

2626
log::info!(
27-
"running 'release', bumping the {} number for crate '{}'",
27+
"running 'release', bumping the {} version number for crate '{}'",
2828
bump,
2929
krate
3030
);
3131

32-
let workspace_root = workspace_root()?;
32+
let workspace_root = MetadataCommand::new()
33+
.exec()?
34+
.workspace_root
35+
.into_std_path_buf();
3336

3437
let mut pipeline = Pipeline::new([
3538
step!(CheckDependencies),
@@ -63,19 +66,14 @@ impl Step for CheckDependencies {
6366
}
6467

6568
fn run(&mut self) -> Result<()> {
66-
let mut missing_cmds = Vec::new();
67-
68-
check_cmd(&mut missing_cmds, "git");
69-
check_cmd(&mut missing_cmds, "git-cliff");
70-
check_cmd(&mut missing_cmds, "cargo");
71-
check_cmd(&mut missing_cmds, "cargo-release");
69+
let missing_cmds = ["git", "git-cliff", "cargo", "cargo-release"]
70+
.into_iter()
71+
.inspect(|name| log::info!("checking command '{}'", name))
72+
.filter(|name| which::which(name).is_err())
73+
.collect::<Vec<_>>();
7274

7375
if missing_cmds.is_empty().not() {
74-
let commands = missing_cmds
75-
.iter()
76-
.map(|i| i.name)
77-
.collect::<Vec<_>>()
78-
.join(", ");
76+
let commands = missing_cmds.join(", ");
7977
bail!(
8078
"missing commands: {}; please install before continuing",
8179
commands
@@ -97,13 +95,10 @@ impl Step for CheckGitReady {
9795
let sh = Shell::new()?;
9896

9997
// 1. Make sure the index is up to date (ignore errors).
100-
let _ = cmd!(sh, "git update-index -q --ignore-submodules --refresh")
101-
.quiet()
102-
.run();
98+
let _ = cmd!(sh, "git update-index -q --ignore-submodules --refresh").run();
10399

104100
// 2. Check for unstaged changes in the working tree.
105101
if cmd!(sh, "git diff-files --quiet --ignore-submodules")
106-
.quiet()
107102
.run()
108103
.is_err()
109104
{
@@ -117,7 +112,6 @@ impl Step for CheckGitReady {
117112
sh,
118113
"git diff-index --cached --quiet HEAD --ignore-submodules"
119114
)
120-
.quiet()
121115
.run()
122116
.is_err()
123117
{
@@ -138,7 +132,7 @@ impl Step for CheckGitBranch {
138132
fn run(&mut self) -> Result<()> {
139133
let sh = Shell::new()?;
140134

141-
let current_branch = cmd!(sh, "git rev-parse --abbrev-ref HEAD").quiet().read()?;
135+
let current_branch = cmd!(sh, "git rev-parse --abbrev-ref HEAD").read()?;
142136

143137
if current_branch != "main" {
144138
bail!(
@@ -185,7 +179,6 @@ impl Step for GenerateChangelog {
185179
sh,
186180
"git cliff --config {config} --include-path {include} -o {output}"
187181
)
188-
.quiet()
189182
.run()?;
190183
Ok(())
191184
}
@@ -194,7 +187,7 @@ impl Step for GenerateChangelog {
194187
fn undo(&mut self) -> Result<()> {
195188
let sh = Shell::new()?;
196189
let output = self.output();
197-
cmd!(sh, "rm {output}").quiet().run()?;
190+
cmd!(sh, "rm {output}").run()?;
198191
Ok(())
199192
}
200193
}
@@ -218,23 +211,21 @@ impl Step for CommitChangelog {
218211
let sh = Shell::new()?;
219212
let msg = self.commit_msg();
220213
let changelog = pathbuf![self.krate.name(), "CHANGELOG.md"];
221-
cmd!(sh, "git add {changelog}").quiet().run()?;
222-
cmd!(sh, "git commit --signoff -m \"{msg}\"")
223-
.quiet()
224-
.run()?;
214+
cmd!(sh, "git add {changelog}").run()?;
215+
cmd!(sh, "git commit --signoff -m \"{msg}\"").run()?;
225216
Ok(())
226217
}
227218

228219
fn undo(&mut self) -> Result<()> {
229220
let sh = Shell::new()?;
230-
let last_msg = cmd!(sh, "git log -1 --pretty=%s").quiet().read()?;
221+
let last_msg = cmd!(sh, "git log -1 --pretty=%s").read()?;
231222
let expected_msg = self.commit_msg();
232223

233224
if last_msg != expected_msg {
234225
bail!("last commit isn't CHANGELOG commit; aborting to avoid breaking git history");
235226
}
236227

237-
cmd!(sh, "git reset --hard HEAD~1").quiet().run()?;
228+
cmd!(sh, "git reset --hard HEAD~1").run()?;
238229
Ok(())
239230
}
240231
}
@@ -255,25 +246,3 @@ impl Step for ReleaseCrate {
255246
bail!("not yet implemented");
256247
}
257248
}
258-
259-
/// Check if a command exists on the command line.
260-
fn check_cmd(missing_cmds: &mut Vec<MissingCmd>, name: &'static str) {
261-
if let Err(err) = which::which(name) {
262-
let err = anyhow!(err);
263-
missing_cmds.push(MissingCmd { name, err });
264-
}
265-
}
266-
267-
#[derive(Debug)]
268-
struct MissingCmd {
269-
name: &'static str,
270-
#[allow(unused)]
271-
err: Error,
272-
}
273-
274-
// Figure out the root of the current Cargo workspace.
275-
fn workspace_root() -> Result<PathBuf> {
276-
let metadata = MetadataCommand::new().exec()?;
277-
let root = metadata.workspace_root.into_std_path_buf();
278-
Ok(root)
279-
}

0 commit comments

Comments
 (0)