diff --git a/.github/ISSUE_TEMPLATE/minor-release.md b/.github/ISSUE_TEMPLATE/minor-release.md index bdf7150d13994..791012eda7682 100644 --- a/.github/ISSUE_TEMPLATE/minor-release.md +++ b/.github/ISSUE_TEMPLATE/minor-release.md @@ -80,8 +80,8 @@ Automated steps include: commit. This makes it easier to cherry-pick to master after the release. - [ ] Merge release preparation branch into the release branch. - `git switch "${RELEASE_BRANCH}" && git merge --ff-only "${PREP_BRANCH}"` - - [ ] Tag new release + - [ ] Create new ephemeral GitHub PAT and update the `HOMEBREW_PAT` [secret](https://github.com/vectordotdev/vector/settings/secrets/actions/HOMEBREW_PAT). - [ ] `git tag v"${NEW_VECTOR_VERSION}" -a -m v"${NEW_VECTOR_VERSION}"` - [ ] `git push origin v"${NEW_VECTOR_VERSION}"` - [ ] Wait for release workflow to complete. diff --git a/vdev/src/app.rs b/vdev/src/app.rs index e5360a639844f..ebca836d37440 100644 --- a/vdev/src/app.rs +++ b/vdev/src/app.rs @@ -5,7 +5,7 @@ use std::{ fmt::Write as _, path::PathBuf, process::{Command, ExitStatus}, - sync::{LazyLock, OnceLock}, + sync::{LazyLock, OnceLock, RwLock}, time::Duration, }; @@ -30,14 +30,18 @@ pub static SHELL: LazyLock = LazyLock::new(|| env::var_os("SHELL").unwrap_or_else(|| DEFAULT_SHELL.into())); static VERBOSITY: OnceLock = OnceLock::new(); -static PATH: OnceLock = OnceLock::new(); +static PATH: RwLock> = RwLock::new(None); pub fn verbosity() -> &'static LevelFilter { VERBOSITY.get().expect("verbosity is not initialized") } -pub fn path() -> &'static String { - PATH.get().expect("path is not initialized") +pub fn path() -> String { + PATH.read() + .expect("could not read path lock") + .as_ref() + .expect("path is not initialized") + .clone() } pub fn set_repo_dir() -> Result<()> { @@ -89,7 +93,7 @@ pub trait CommandExt { impl CommandExt for Command { /// Create a new command to execute the named script in the repository `scripts` directory. fn script(script: &str) -> Self { - let path: PathBuf = [path(), "scripts", script].into_iter().collect(); + let path: PathBuf = [&path(), "scripts", script].into_iter().collect(); if cfg!(windows) { // On Windows, all scripts must be run through an explicit interpreter. let mut command = Command::new(&*SHELL); @@ -254,5 +258,5 @@ pub fn set_global_verbosity(verbosity: LevelFilter) { } pub fn set_global_path(path: String) { - PATH.set(path).expect("could not set path"); + *PATH.write().expect("could not write path lock") = Some(path); } diff --git a/vdev/src/commands/build/vrl_wasm.rs b/vdev/src/commands/build/vrl_wasm.rs index 9f95422484748..f59c5c1bc09a3 100644 --- a/vdev/src/commands/build/vrl_wasm.rs +++ b/vdev/src/commands/build/vrl_wasm.rs @@ -11,7 +11,7 @@ pub struct Cli {} impl Cli { pub fn exec(self) -> Result<()> { - let vrl_path = Path::new(app::path()).join("lib").join("vrl"); + let vrl_path = Path::new(&app::path()).join("lib").join("vrl"); let args = &["build", "--release", "--target", "wasm32-unknown-unknown"]; for crate_name in ["compiler", "core", "diagnostic", "parser"] { diff --git a/vdev/src/commands/meta/install_git_hooks.rs b/vdev/src/commands/meta/install_git_hooks.rs index 2182cf87376d1..6ae8c540e6294 100644 --- a/vdev/src/commands/meta/install_git_hooks.rs +++ b/vdev/src/commands/meta/install_git_hooks.rs @@ -47,7 +47,7 @@ pub struct Cli {} impl Cli { pub fn exec(self) -> Result<()> { - let hook_dir = Path::new(app::path()).join(".git").join("hooks"); + let hook_dir = Path::new(&app::path()).join(".git").join("hooks"); // Create a new directory named hooks in the .git directory if it // doesn't already exist. diff --git a/vdev/src/commands/release/homebrew.rs b/vdev/src/commands/release/homebrew.rs index 69deeb657401e..8d89d58dbb455 100644 --- a/vdev/src/commands/release/homebrew.rs +++ b/vdev/src/commands/release/homebrew.rs @@ -1,4 +1,4 @@ -use crate::utils::git; +use crate::{app, utils::git}; use anyhow::Result; use sha2::Digest; use std::path::Path; @@ -23,6 +23,7 @@ impl Cli { // Create temporary directory for cloning the homebrew-brew repository let td = TempDir::new()?; env::set_current_dir(td.path())?; + trace!("Cloned at {td:?}"); debug!( "Cloning the homebrew repository for username: {}", @@ -50,8 +51,20 @@ fn clone_and_setup_git(username: &str) -> Result<()> { git::clone(&homebrew_repo)?; env::set_current_dir("homebrew-brew")?; + + // Update the global path to the homebrew-brew repo so git operations work correctly + app::set_global_path(env::current_dir()?.to_string_lossy().to_string()); + + // Set the remote URL with credentials to ensure push works + git::set_remote_url("origin", &homebrew_repo)?; + + // Disable credential helper to ensure we use the PAT from the URL + git::set_config_value("credential.helper", "")?; + git::set_config_value("user.name", "vic")?; git::set_config_value("user.email", "vector@datadoghq.com")?; + + git::checkout_or_create_branch("test")?; Ok(()) } @@ -98,7 +111,7 @@ fn commit_and_push_changes(vector_version: &str) -> Result<()> { debug!("Modified lines {:?}", git::get_modified_files()); let commit_message = format!("Release Vector {vector_version}"); git::commit(&commit_message)?; - git::push()?; + git::push_branch("test")?; } else { debug!("No changes to push."); } diff --git a/vdev/src/commands/test_vrl.rs b/vdev/src/commands/test_vrl.rs index 6644623acef09..30c82bda9c6c4 100644 --- a/vdev/src/commands/test_vrl.rs +++ b/vdev/src/commands/test_vrl.rs @@ -10,7 +10,7 @@ pub struct Cli {} impl Cli { pub fn exec(self) -> Result<()> { - run_tests(&[app::path(), "lib", "vector-vrl", "tests"])?; + run_tests(&[&app::path(), "lib", "vector-vrl", "tests"])?; Ok(()) } } diff --git a/vdev/src/testing/config.rs b/vdev/src/testing/config.rs index 4a1280406ef1a..5f9e2700a0460 100644 --- a/vdev/src/testing/config.rs +++ b/vdev/src/testing/config.rs @@ -40,7 +40,7 @@ pub struct RustToolchainConfig { impl RustToolchainConfig { fn parse() -> Result { let repo_path = app::path(); - let config_file: PathBuf = [repo_path, "rust-toolchain.toml"].iter().collect(); + let config_file: PathBuf = [&repo_path, "rust-toolchain.toml"].iter().collect(); let contents = fs::read_to_string(&config_file) .with_context(|| format!("failed to read {}", config_file.display()))?; let config: RustToolchainRootConfig = toml::from_str(&contents) @@ -217,7 +217,7 @@ impl ComposeTestConfig { pub fn load(root_dir: &str, integration: &str) -> Result<(PathBuf, Self)> { let (base_dir, use_config_subdir) = test_dir_config(root_dir); - let test_dir: PathBuf = [app::path(), base_dir, root_dir, integration] + let test_dir: PathBuf = [&app::path(), base_dir, root_dir, integration] .iter() .collect(); @@ -262,7 +262,7 @@ impl ComposeTestConfig { let mut configs = BTreeMap::new(); let (base_dir, use_config_subdir) = test_dir_config(root_dir); - let tests_dir: PathBuf = [app::path(), base_dir, root_dir].iter().collect(); + let tests_dir: PathBuf = [&app::path(), base_dir, root_dir].iter().collect(); Self::collect_all_dir(&tests_dir, &mut configs, use_config_subdir)?; diff --git a/vdev/src/testing/mod.rs b/vdev/src/testing/mod.rs index 105a6efe33cd6..a972926104d57 100644 --- a/vdev/src/testing/mod.rs +++ b/vdev/src/testing/mod.rs @@ -11,5 +11,7 @@ pub mod runner; /// Returns the path to the unified test runner Dockerfile. /// Both integration and E2E tests use the same Dockerfile at `tests/e2e/Dockerfile`. pub fn test_runner_dockerfile() -> PathBuf { - [app::path(), "tests", "e2e", "Dockerfile"].iter().collect() + [&app::path(), "tests", "e2e", "Dockerfile"] + .iter() + .collect() } diff --git a/vdev/src/utils/git.rs b/vdev/src/utils/git.rs index 54216c76e2da6..1257fd6034b17 100644 --- a/vdev/src/utils/git.rs +++ b/vdev/src/utils/git.rs @@ -118,6 +118,12 @@ pub fn set_config_value(key: &str, value: &str) -> Result { .check_output() } +pub fn set_remote_url(remote_name: &str, url: &str) -> Result { + Command::new("git") + .args(["remote", "set-url", remote_name, url]) + .check_output() +} + /// Checks if the current directory's repo is clean pub fn check_git_repository_clean() -> Result { Ok(Command::new("git")