Skip to content

Commit 37ef1c7

Browse files
authored
Add xtask tasks for simplifying the release process (#22)
* Add a `cargo xtask bump` command for updating versions This should only affect publishable crates. * Add a `cargo xtask publish` command * Remove ci/publish.sh * Allow `cargo xtask bump` to create a release commit with `--git-commit` * Normalize both tasks to use '--git' * Fix formatting * Update README
1 parent 53d9805 commit 37ef1c7

File tree

9 files changed

+390
-100
lines changed

9 files changed

+390
-100
lines changed

Cargo.lock

Lines changed: 50 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ After building:
118118

119119

120120

121+
### Development
122+
123+
Run `cargo xtask --help` to read up on the in-tree development tools.
124+
125+
126+
121127
### License
122128

123129
`openvino-rs` is released under the same license as OpenVINO™: the [Apache License Version

ci/publish.sh

Lines changed: 0 additions & 87 deletions
This file was deleted.

crates/xtask/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ publish = false
1010
anyhow = "1.0"
1111
bindgen = "0.58.1"
1212
structopt = { version = "0.3", features = ["color", "suggestions"] }
13+
toml = "0.5.8"
14+
semver = "0.11"

crates/xtask/src/bump.rs

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
use crate::util::{get_crates, Crate};
2+
use anyhow::{anyhow, Context, Result};
3+
use std::fs;
4+
use std::process::Command;
5+
use structopt::StructOpt;
6+
7+
#[derive(Debug, StructOpt)]
8+
#[structopt(name = "bump")]
9+
pub struct BumpCommand {
10+
/// Do not modify the Cargo.toml files; instead, simply print the actions that would have been
11+
/// taken.
12+
#[structopt(long = "dry-run")]
13+
dry_run: bool,
14+
/// Add a conventional Git commit message for the bump changes; equivalent to `git commit -a -m
15+
/// 'Release v[bumped version]'`.
16+
#[structopt(long)]
17+
git: bool,
18+
/// What part of the semver version to change: major | minor | patch | <version string>
19+
#[structopt(name = "KIND")]
20+
bump: Bump,
21+
}
22+
23+
impl BumpCommand {
24+
pub fn execute(&self) -> Result<()> {
25+
// Find the publishable crates.
26+
let publishable_crates: Vec<Crate> =
27+
get_crates()?.into_iter().filter(|c| c.publish).collect();
28+
29+
// Check that all of the versions are the same.
30+
if !publishable_crates
31+
.windows(2)
32+
.all(|w| w[0].version == w[1].version)
33+
{
34+
anyhow!(
35+
"Not all crate versions are the same: {:?}",
36+
publishable_crates
37+
);
38+
}
39+
40+
// Change the version.
41+
let mut next_version = semver::Version::parse(&publishable_crates[0].version)?;
42+
match &self.bump {
43+
Bump::Major => next_version.increment_major(),
44+
Bump::Minor => next_version.increment_minor(),
45+
Bump::Patch => next_version.increment_patch(),
46+
Bump::Custom(v) => next_version = semver::Version::parse(v)?,
47+
}
48+
49+
// Update the Cargo.toml files.
50+
let next_version_str = &next_version.to_string();
51+
for c in publishable_crates.iter() {
52+
update_version(c, &publishable_crates, next_version_str, self.dry_run)?;
53+
}
54+
55+
// Update the Cargo.lock file.
56+
if !self.dry_run {
57+
assert!(Command::new("cargo").arg("fetch").status()?.success());
58+
}
59+
60+
// Add a Git commit.
61+
let commit_message = format!("'Release v{}'", next_version_str);
62+
if self.git {
63+
println!("> add Git commit: {}", &commit_message);
64+
if !self.dry_run && self.git {
65+
assert!(Command::new("git")
66+
.arg("commit")
67+
.arg("-a")
68+
.arg("-m")
69+
.arg(&commit_message)
70+
.status()
71+
.with_context(|| format!("failed to run `git commit` command"))?
72+
.success());
73+
}
74+
}
75+
76+
Ok(())
77+
}
78+
}
79+
80+
/// Enumerate the ways a version can change.
81+
#[derive(Debug)]
82+
pub enum Bump {
83+
Major,
84+
Minor,
85+
Patch,
86+
Custom(String),
87+
}
88+
89+
impl std::str::FromStr for Bump {
90+
type Err = anyhow::Error;
91+
fn from_str(s: &str) -> Result<Self, Self::Err> {
92+
Ok(match s {
93+
"major" => Self::Major,
94+
"minor" => Self::Minor,
95+
"patch" => Self::Patch,
96+
_ => Self::Custom(s.into()),
97+
})
98+
}
99+
}
100+
101+
/// Update the version of `krate` and any dependencies in `crates` to match the version passed in
102+
/// `next_version`. Adapted from
103+
/// https://github.com/bytecodealliance/wasmtime/blob/main/scripts/publish.rs
104+
fn update_version(
105+
krate: &Crate,
106+
crates: &[Crate],
107+
next_version: &str,
108+
dry_run: bool,
109+
) -> Result<()> {
110+
let contents = fs::read_to_string(&krate.path)?;
111+
let mut new_contents = String::new();
112+
let mut reading_dependencies = false;
113+
for line in contents.lines() {
114+
let mut rewritten = false;
115+
116+
// Update top-level `version = "..."` line.
117+
if !reading_dependencies && line.starts_with("version =") {
118+
println!(
119+
"> bump `{}` {} => {}",
120+
krate.name, krate.version, next_version
121+
);
122+
new_contents.push_str(&line.replace(&krate.version.to_string(), next_version));
123+
rewritten = true;
124+
}
125+
126+
// Check whether we have reached the `[dependencies]` section.
127+
reading_dependencies = if line.starts_with("[") {
128+
line.contains("dependencies")
129+
} else {
130+
reading_dependencies
131+
};
132+
133+
// Find dependencies and update them as well.
134+
for other in crates {
135+
if !reading_dependencies || !line.starts_with(&format!("{} ", other.name)) {
136+
continue;
137+
}
138+
if !line.contains(&other.version.to_string()) {
139+
if !line.contains("version =") {
140+
continue;
141+
}
142+
panic!(
143+
"{:?} has a dependency on {} but doesn't list version {}",
144+
krate.path, other.name, other.version
145+
);
146+
}
147+
println!(
148+
"> bump dependency `{}` {} => {}",
149+
other.name, other.version, next_version
150+
);
151+
rewritten = true;
152+
new_contents.push_str(&line.replace(&other.version, next_version));
153+
break;
154+
}
155+
156+
// All other lines are printed as-is.
157+
if !rewritten {
158+
new_contents.push_str(line);
159+
}
160+
161+
new_contents.push_str("\n");
162+
}
163+
164+
if !dry_run {
165+
fs::write(&krate.path, new_contents)?;
166+
}
167+
168+
Ok(())
169+
}

crates/xtask/src/codegen.rs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::util::path_to_crates;
12
use anyhow::{anyhow, ensure, Context, Result};
23
use bindgen;
34
use std::fs::{File, OpenOptions};
@@ -76,7 +77,7 @@ impl CodegenCommand {
7677
None => {
7778
// Equivalent to:
7879
// crates/xtask/src/codegen.rs/../../../openvino-sys/upstream/inference-engine...
79-
self.path_to_crates()?.join(DEFAULT_HEADER_FILE)
80+
path_to_crates()?.join(DEFAULT_HEADER_FILE)
8081
}
8182
})
8283
}
@@ -92,22 +93,11 @@ impl CodegenCommand {
9293
}
9394
None => {
9495
// Equivalent to: crates/xtask/src/codegen.rs/../../../openvino-sys/src/generated
95-
self.path_to_crates()?.join(DEFAULT_OUTPUT_DIRECTORY)
96+
path_to_crates()?.join(DEFAULT_OUTPUT_DIRECTORY)
9697
}
9798
})
9899
}
99100

100-
fn path_to_crates(&self) -> Result<PathBuf> {
101-
Ok(PathBuf::from(file!())
102-
.parent()
103-
.with_context(|| format!("Failed to get parent of path."))?
104-
.parent()
105-
.with_context(|| format!("Failed to get parent of path."))?
106-
.parent()
107-
.with_context(|| format!("Failed to get parent of path."))?
108-
.into())
109-
}
110-
111101
fn generate_type_bindings<P: AsRef<Path>>(&self, header_file: P) -> Result<bindgen::Bindings> {
112102
bindgen::Builder::default()
113103
.header(header_file.as_ref().to_string_lossy())

0 commit comments

Comments
 (0)