Skip to content

Commit 7594a0b

Browse files
fix(vdev): release prepare vrl version pinning (vectordotdev#24158)
* Add --dry-run to release prepare * Add error handling and checks to pin_vrl_version * Add wrapper to toml * Remove wrapper, parse as Table instead * Fix vrl pinning logic * Enable preserve_order feature in toml crate * Use dependency instead of whole toml * Fix dry run docs * Fix dry run wording * refactor to use toml_edit * Add update_vrl_to_version to add unit test * Use indoc in prepare.rs * Remove preserve_order feature
1 parent 6913528 commit 7594a0b

3 files changed

Lines changed: 66 additions & 33 deletions

File tree

Cargo.lock

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

vdev/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ serde_yaml.workspace = true
4343
sha2 = "0.10.9"
4444
tempfile.workspace = true
4545
toml.workspace = true
46+
toml_edit = { version = "0.22", default-features = false }
4647
semver.workspace = true
4748
indoc.workspace = true
4849
git2 = { version = "0.20.2" }

vdev/src/commands/release/prepare.rs

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use crate::utils::command::run_command;
55
use crate::utils::{git, paths};
6-
use anyhow::{Result, anyhow};
6+
use anyhow::{Context, Result, anyhow};
77
use reqwest::blocking::Client;
88
use semver::Version;
99
use std::fs::File;
@@ -14,7 +14,7 @@ use std::path::{Path, PathBuf};
1414
use std::process::Command;
1515
use std::{env, fs};
1616
use toml::Value;
17-
use toml::map::Map;
17+
use toml_edit::DocumentMut;
1818

1919
const ALPINE_PREFIX: &str = "FROM docker.io/alpine:";
2020
const ALPINE_DOCKERFILE: &str = "distribution/docker/alpine/Dockerfile";
@@ -42,6 +42,10 @@ pub struct Cli {
4242
/// You can find the latest version here: <https://www.debian.org/releases/>.
4343
#[arg(long)]
4444
debian_version: Option<String>,
45+
46+
/// Dry run. Enabling this will make it so no PRs will be created and no branches will be pushed upstream.
47+
#[arg(long, default_value_t = false)]
48+
dry_run: bool,
4549
}
4650

4751
struct Prepare {
@@ -53,6 +57,7 @@ struct Prepare {
5357
latest_vector_version: Version,
5458
release_branch: String,
5559
release_preparation_branch: String,
60+
dry_run: bool,
5661
}
5762

5863
impl Cli {
@@ -74,6 +79,7 @@ impl Cli {
7479
"prepare-v-{}-{}-{}-website",
7580
self.version.major, self.version.minor, self.version.patch
7681
),
82+
dry_run: self.dry_run,
7783
};
7884
prepare.run()
7985
}
@@ -106,7 +112,11 @@ impl Prepare {
106112

107113
self.create_new_release_md()?;
108114

109-
self.open_release_pr()
115+
if !self.dry_run {
116+
self.open_release_pr()?;
117+
}
118+
119+
Ok(())
110120
}
111121

112122
/// Steps 1 & 2
@@ -117,48 +127,28 @@ impl Prepare {
117127
git::checkout_main_branch()?;
118128

119129
git::checkout_or_create_branch(self.release_branch.as_str())?;
120-
git::push_and_set_upstream(self.release_branch.as_str())?;
130+
if !self.dry_run {
131+
git::push_and_set_upstream(self.release_branch.as_str())?;
132+
}
121133

122134
// Step 2: Create a new release preparation branch
123135
// The branch website contains 'website' to generate vector.dev preview.
124136
git::checkout_or_create_branch(self.release_preparation_branch.as_str())?;
125-
git::push_and_set_upstream(self.release_preparation_branch.as_str())?;
137+
if !self.dry_run {
138+
git::push_and_set_upstream(self.release_preparation_branch.as_str())?;
139+
}
126140
Ok(())
127141
}
128142

129143
/// Step 3
130144
fn pin_vrl_version(&self) -> Result<()> {
131145
debug!("pin_vrl_version");
132146
let cargo_toml_path = &self.repo_root.join("Cargo.toml");
133-
let contents = fs::read_to_string(cargo_toml_path).expect("Failed to read Cargo.toml");
134-
135-
// Needs this hybrid approach to preserve ordering.
136-
let mut lines: Vec<String> = contents.lines().map(String::from).collect();
137-
147+
let contents = fs::read_to_string(cargo_toml_path).context("Failed to read Cargo.toml")?;
138148
let vrl_version = self.vrl_version.to_string();
139-
for line in &mut lines {
140-
if line.trim().starts_with("vrl = { git = ") {
141-
if let Ok(mut vrl_toml) = line.parse::<Value>() {
142-
let vrl_dependency: &mut Value = vrl_toml
143-
.get_mut("vrl")
144-
.expect("line should start with 'vrl'");
145-
146-
let mut new_dependency_value = Map::new();
147-
new_dependency_value
148-
.insert("version".to_string(), Value::String(vrl_version.clone()));
149-
let features = vrl_dependency
150-
.get("features")
151-
.expect("missing 'features' key");
152-
new_dependency_value.insert("features".to_string(), features.clone());
153-
154-
*line = format!("vrl = {}", Value::from(new_dependency_value));
155-
}
156-
break;
157-
}
158-
}
149+
let updated_contents = update_vrl_to_version(&contents, &vrl_version)?;
159150

160-
lines.push(String::new()); // File should end with a newline.
161-
fs::write(cargo_toml_path, lines.join("\n")).expect("Failed to write Cargo.toml");
151+
fs::write(cargo_toml_path, updated_contents).context("Failed to write Cargo.toml")?;
162152
run_command("cargo update -p vrl");
163153
git::commit(&format!(
164154
"chore(releasing): Pinned VRL version to {vrl_version}"
@@ -420,6 +410,26 @@ impl Prepare {
420410

421411
// FREE FUNCTIONS AFTER THIS LINE
422412

413+
/// Transforms a Cargo.toml string by replacing vrl's git dependency with a version dependency.
414+
/// Updates the vrl entry in [workspace.dependencies] from git + branch to a version.
415+
fn update_vrl_to_version(cargo_toml_contents: &str, vrl_version: &str) -> Result<String> {
416+
let mut doc = cargo_toml_contents
417+
.parse::<DocumentMut>()
418+
.context("Failed to parse Cargo.toml")?;
419+
420+
// Navigate to workspace.dependencies.vrl
421+
let vrl_table = doc["workspace"]["dependencies"]["vrl"]
422+
.as_inline_table_mut()
423+
.context("vrl in workspace.dependencies should be an inline table")?;
424+
425+
// Remove git and branch, add version
426+
vrl_table.remove("git");
427+
vrl_table.remove("branch");
428+
vrl_table.insert("version", vrl_version.into());
429+
430+
Ok(doc.to_string())
431+
}
432+
423433
fn get_latest_version_from_vector_tags() -> Result<Version> {
424434
let tags = run_command("git tag --list --sort=-v:refname");
425435
let latest_tag = tags
@@ -527,10 +537,31 @@ fn get_latest_vrl_tag_and_changelog() -> Result<String> {
527537
#[cfg(test)]
528538
mod tests {
529539
use crate::commands::release::prepare::{
530-
format_vrl_changelog_block, insert_block_after_changelog,
540+
format_vrl_changelog_block, insert_block_after_changelog, update_vrl_to_version,
531541
};
532542
use indoc::indoc;
533543

544+
#[test]
545+
fn test_update_vrl_to_version() {
546+
let input = indoc! {r#"
547+
[workspace.dependencies]
548+
some-other-dep = "1.0.0"
549+
vrl = { git = "https://github.com/vectordotdev/vrl.git", branch = "main", features = ["arbitrary", "cli", "test", "test_framework"] }
550+
another-dep = "2.0.0"
551+
"#};
552+
553+
let result = update_vrl_to_version(input, "0.28.0").expect("should succeed");
554+
555+
let expected = indoc! {r#"
556+
[workspace.dependencies]
557+
some-other-dep = "1.0.0"
558+
vrl = { features = ["arbitrary", "cli", "test", "test_framework"] , version = "0.28.0" }
559+
another-dep = "2.0.0"
560+
"#};
561+
562+
assert_eq!(result, expected);
563+
}
564+
534565
#[test]
535566
fn test_insert_block_after_changelog() {
536567
let vrl_changelog = "### [0.2.0]\n- Feature\n- Fix";

0 commit comments

Comments
 (0)