33
44use crate :: utils:: command:: run_command;
55use crate :: utils:: { git, paths} ;
6- use anyhow:: { Result , anyhow} ;
6+ use anyhow:: { Context , Result , anyhow} ;
77use reqwest:: blocking:: Client ;
88use semver:: Version ;
99use std:: fs:: File ;
@@ -14,7 +14,7 @@ use std::path::{Path, PathBuf};
1414use std:: process:: Command ;
1515use std:: { env, fs} ;
1616use toml:: Value ;
17- use toml :: map :: Map ;
17+ use toml_edit :: DocumentMut ;
1818
1919const ALPINE_PREFIX : & str = "FROM docker.io/alpine:" ;
2020const 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
4751struct 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
5863impl 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+
423433fn 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) ]
528538mod 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