diff --git a/Cargo.lock b/Cargo.lock index d903364a4e..993686fbb2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3910,6 +3910,8 @@ dependencies = [ "anyhow", "assert_cmd", "async-trait", + "base64 0.21.2", + "cargo_utils", "chrono", "clap", "clap_complete", @@ -3927,6 +3929,7 @@ dependencies = [ "test_logs", "tokio", "toml 0.7.6", + "toml_edit", "tracing", "tracing-log", "tracing-subscriber", diff --git a/Cargo.toml b/Cargo.toml index 701ae8158a..ef066206b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = ["crates/*"] anyhow = "1.0.74" assert_cmd = "2.0.12" async-trait = "0.1.73" +base64 = "0.21.2" cargo_metadata = "0.17.0" cargo = "0.72.2" chrono = { version = "0.4.26", default-features = false } diff --git a/crates/cargo_utils/src/local_manifest.rs b/crates/cargo_utils/src/local_manifest.rs index e0f5b24643..f4faeb4912 100644 --- a/crates/cargo_utils/src/local_manifest.rs +++ b/crates/cargo_utils/src/local_manifest.rs @@ -52,8 +52,8 @@ impl LocalManifest { if !path.is_absolute() { anyhow::bail!("can only edit absolute paths, got {}", path.display()); } - let data = - std::fs::read_to_string(path).with_context(|| "Failed to read manifest contents")?; + let data = std::fs::read_to_string(path) + .with_context(|| format!("Failed to read manifest contents. Path: {:?}", path))?; let manifest = data.parse().context("Unable to parse Cargo.toml")?; Ok(LocalManifest { manifest, diff --git a/crates/release_plz/Cargo.toml b/crates/release_plz/Cargo.toml index 40293714ab..fdff9e4b08 100644 --- a/crates/release_plz/Cargo.toml +++ b/crates/release_plz/Cargo.toml @@ -20,6 +20,7 @@ git_cmd = { path = "../git_cmd", version = "0.4.8" } release_plz_core = { path = "../release_plz_core", version = "0.13.1" } anyhow.workspace = true +base64.workspace = true chrono = { workspace = true, features = ["clock"] } clap = { workspace = true, features = ["derive", "env"] } clap_complete.workspace = true @@ -36,6 +37,7 @@ tracing.workspace = true url.workspace = true [dev-dependencies] +cargo_utils = { path = "../cargo_utils" } test_logs = { path = "../test_logs" } assert_cmd.workspace = true @@ -44,3 +46,4 @@ fake.workspace = true expect-test.workspace = true serde_json.workspace = true tempfile.workspace = true +toml_edit.workspace = true diff --git a/crates/release_plz/src/args/mod.rs b/crates/release_plz/src/args/mod.rs index deb60c6074..dc8a8e96ca 100644 --- a/crates/release_plz/src/args/mod.rs +++ b/crates/release_plz/src/args/mod.rs @@ -25,7 +25,7 @@ pub struct CliArgs { pub command: Command, /// Print source location and additional information in logs. /// To change the log level, use the `RUST_FLAG` environment variable. - #[arg(short, long)] + #[arg(short, long, global = true)] pub verbose: bool, /// Path to the release-plz config file. /// Default: `./release-plz.toml`. diff --git a/crates/release_plz/tests/all/changelog.rs b/crates/release_plz/tests/all/changelog.rs index c6ff18e9d6..361d513d3d 100644 --- a/crates/release_plz/tests/all/changelog.rs +++ b/crates/release_plz/tests/all/changelog.rs @@ -1,11 +1,11 @@ -use crate::helpers::test_context::TestContext; +use crate::helpers::{test_context::TestContext, TEST_REGISTRY}; #[tokio::test] #[cfg_attr(not(feature = "docker-tests"), ignore)] async fn release_plz_adds_changelog_on_new_project() { let context = TestContext::new().await; - context.run_release_plz().success(); + context.run_release_pr().success(); let opened_prs = context.opened_release_prs().await; assert_eq!(opened_prs.len(), 1); @@ -17,3 +17,27 @@ async fn release_plz_adds_changelog_on_new_project() { assert_eq!(changed_files.len(), 1,); assert_eq!(changed_files[0].filename, "CHANGELOG.md"); } + +#[tokio::test] +#[cfg_attr(not(feature = "docker-tests"), ignore)] +async fn release_plz_releases_a_new_project() { + let context = TestContext::new().await; + + let crate_name = &context.gitea.repo; + let dest_dir = tempfile::tempdir().unwrap(); + let dest_dir_str = dest_dir.path().to_str().unwrap(); + + let packages = || { + release_plz_core::PackageDownloader::new([crate_name], dest_dir_str) + .with_registry(TEST_REGISTRY.to_string()) + .with_cargo_cwd(context.repo_dir()) + .download() + .unwrap() + }; + // Before running release-plz, no packages should be present. + assert!(packages().is_empty()); + + context.run_release().success(); + + assert_eq!(packages().len(), 1); +} diff --git a/crates/release_plz/tests/all/completion_test.rs b/crates/release_plz/tests/all/completion_test.rs index d66e7421e2..8266511258 100644 --- a/crates/release_plz/tests/all/completion_test.rs +++ b/crates/release_plz/tests/all/completion_test.rs @@ -1,15 +1,15 @@ -use assert_cmd::Command; use clap::ValueEnum; use clap_complete::Shell; +use crate::helpers; + #[test] -fn test_generate_completions() -> anyhow::Result<()> { +fn test_generate_completions() { for &shell in Shell::value_variants() { - Command::cargo_bin(env!("CARGO_PKG_NAME"))? + helpers::cmd::release_plz_cmd() .arg("generate-completions") .arg(shell.to_string()) .assert() .success(); } - Ok(()) } diff --git a/crates/release_plz/tests/all/helpers/cmd.rs b/crates/release_plz/tests/all/helpers/cmd.rs new file mode 100644 index 0000000000..f6dae17976 --- /dev/null +++ b/crates/release_plz/tests/all/helpers/cmd.rs @@ -0,0 +1,5 @@ +use assert_cmd::Command; + +pub fn release_plz_cmd() -> Command { + Command::cargo_bin(env!("CARGO_PKG_NAME")).unwrap() +} diff --git a/crates/release_plz/tests/all/helpers/fake_utils.rs b/crates/release_plz/tests/all/helpers/fake_utils.rs index 9598e13290..f69045aba5 100644 --- a/crates/release_plz/tests/all/helpers/fake_utils.rs +++ b/crates/release_plz/tests/all/helpers/fake_utils.rs @@ -1,7 +1,7 @@ use fake::{Fake, StringFaker}; pub fn fake_id() -> String { - const LETTERS: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const LETTERS: &str = "abcdefghijklmnopqrstuvwxyz"; let f = StringFaker::with(Vec::from(LETTERS), 8); f.fake() } diff --git a/crates/release_plz/tests/all/helpers/gitea/gitea_new.rs b/crates/release_plz/tests/all/helpers/gitea/gitea_new.rs index b4275b9cbd..deea732d75 100644 --- a/crates/release_plz/tests/all/helpers/gitea/gitea_new.rs +++ b/crates/release_plz/tests/all/helpers/gitea/gitea_new.rs @@ -6,7 +6,7 @@ use serde_json::json; use crate::helpers::{fake_utils, reqwest_utils::ReqwestUtils}; -use super::{GiteaContext, GiteaUser}; +use super::{GiteaContext, GiteaUser, CARGO_INDEX_REPO}; impl GiteaContext { pub async fn new(repo: String) -> Self { @@ -15,6 +15,8 @@ impl GiteaContext { let token = create_token(&user, &client).await; create_repository(&token, &repo, &client).await; + create_repository(&token, CARGO_INDEX_REPO, &client).await; + upload_registry_config(&token, &user.username, &client).await; Self { user, @@ -33,14 +35,15 @@ pub async fn create_token(user: &GiteaUser, client: &reqwest::Client) -> String let token: Token = client .post(super::gitea_endpoint(&format!( - "/users/{}/tokens", + "users/{}/tokens", user.username() ))) .basic_auth(user.username(), Some(&user.password())) .json(&json!({ "name": user.username(), - // edit repositories - "scopes": ["read:repository", "write:repository", "write:user"] + // write:repository, write:user - edit repositories + // write:package - publish packages (for cargo publish) + "scopes": ["read:repository", "write:repository", "write:user", "write:package"] })) .send() .await @@ -56,7 +59,7 @@ pub async fn create_token(user: &GiteaUser, client: &reqwest::Client) -> String async fn create_repository(user_token: &str, repo_name: &str, client: &reqwest::Client) { client - .post(super::gitea_endpoint("/user/repos")) + .post(super::gitea_endpoint("user/repos")) .query(&[("token", user_token)]) .json(&json!({ "name": repo_name, @@ -71,6 +74,30 @@ async fn create_repository(user_token: &str, repo_name: &str, client: &reqwest:: .unwrap(); } +async fn upload_registry_config(user_token: &str, username: &str, client: &reqwest::Client) { + use base64::Engine as _; + let content = { + let cargo_url = format!("http://localhost:3000/api/packages/{username}/cargo"); + format!("{{\"dl\":\"{cargo_url}/api/v1/crates\",\"api\":\"{cargo_url}\"}}") + }; + + client + .post(super::gitea_endpoint(&format!( + "repos/{username}/{CARGO_INDEX_REPO}/contents/config.json" + ))) + .query(&[("token", user_token)]) + .json(&json!({ + "message": "Add config.json", + "content": base64::engine::general_purpose::STANDARD.encode(content.as_bytes()), + })) + .send() + .await + .expect("Failed to upload content") + .ok_if_2xx() + .await + .unwrap(); +} + fn run_create_user_command(user: &GiteaUser) { let email = format!("{}@example.com", user.username()); Command::new("docker") diff --git a/crates/release_plz/tests/all/helpers/gitea/mod.rs b/crates/release_plz/tests/all/helpers/gitea/mod.rs index e7bc4c29e3..634f0c0e3a 100644 --- a/crates/release_plz/tests/all/helpers/gitea/mod.rs +++ b/crates/release_plz/tests/all/helpers/gitea/mod.rs @@ -17,11 +17,14 @@ pub struct GiteaContext { client: reqwest::Client, } +/// Repository name where gitea stores the registry index. +pub const CARGO_INDEX_REPO: &str = "_cargo-index"; + fn gitea_endpoint(endpoint: &str) -> String { let api_url = format!("http://{}/api/v1", gitea_address()); format!("{}/{}", api_url, endpoint) } -fn gitea_address() -> &'static str { +pub fn gitea_address() -> &'static str { "localhost:3000" } diff --git a/crates/release_plz/tests/all/helpers/mod.rs b/crates/release_plz/tests/all/helpers/mod.rs index 2715632a45..c8e04217de 100644 --- a/crates/release_plz/tests/all/helpers/mod.rs +++ b/crates/release_plz/tests/all/helpers/mod.rs @@ -1,4 +1,7 @@ +pub mod cmd; mod fake_utils; pub mod gitea; mod reqwest_utils; pub mod test_context; + +pub const TEST_REGISTRY: &str = "test-registry"; diff --git a/crates/release_plz/tests/all/helpers/test_context.rs b/crates/release_plz/tests/all/helpers/test_context.rs index 035308524e..5e5155ead0 100644 --- a/crates/release_plz/tests/all/helpers/test_context.rs +++ b/crates/release_plz/tests/all/helpers/test_context.rs @@ -5,20 +5,25 @@ use std::{ str::FromStr, }; +use crate::helpers::gitea::CARGO_INDEX_REPO; use assert_cmd::assert::Assert; +use cargo_utils::LocalManifest; use git_cmd::Repo; use release_plz_core::{GitBackend, GitClient, GitPr, Gitea, RepoUrl}; use secrecy::SecretString; use tempfile::TempDir; use tracing::info; -use super::{fake_utils, gitea::GiteaContext}; +use super::{ + fake_utils, + gitea::{gitea_address, GiteaContext}, + TEST_REGISTRY, +}; /// It contains the universe in which release-plz runs. pub struct TestContext { pub gitea: GiteaContext, test_dir: TempDir, - /// Release-plz git client. It's here just for code reuse. git_client: GitClient, } @@ -36,7 +41,7 @@ impl TestContext { let git_client = git_client(&repo_url, &gitea.token); let repo_dir = test_dir.path().join(&gitea.repo); - let _repo = commit_cargo_init(&repo_dir, gitea.user.username()); + let _repo = commit_cargo_init(&repo_dir, &gitea); Self { gitea, test_dir, @@ -44,23 +49,46 @@ impl TestContext { } } - pub fn run_release_plz(&self) -> Assert { + pub fn run_release_pr(&self) -> Assert { let log_level = if std::env::var("ENABLE_LOGS").is_ok() { "DEBUG,hyper=INFO" } else { "ERROR" }; - assert_cmd::Command::cargo_bin(env!("CARGO_PKG_NAME")) - .unwrap() + super::cmd::release_plz_cmd() .current_dir(&self.repo_dir()) .env("RUST_LOG", log_level) .arg("release-pr") + .arg("--verbose") .arg("--git-token") .arg(&self.gitea.token) .arg("--backend") .arg("gitea") .arg("--registry") - .arg("test-registry") + .arg(TEST_REGISTRY) + .assert() + } + + pub fn run_release(&self) -> Assert { + let log_level = if std::env::var("ENABLE_LOGS").is_ok() { + "DEBUG,hyper=INFO" + } else { + "ERROR" + }; + + super::cmd::release_plz_cmd() + .current_dir(&self.repo_dir()) + .env("RUST_LOG", log_level) + .arg("release") + .arg("--verbose") + .arg("--git-token") + .arg(&self.gitea.token) + .arg("--backend") + .arg("gitea") + .arg("--registry") + .arg(TEST_REGISTRY) + .arg("--token") + .arg(format!("Bearer {}", &self.gitea.token)) .assert() } @@ -73,13 +101,14 @@ impl TestContext { } } -fn commit_cargo_init(repo_dir: &Path, username: &str) -> Repo { +fn commit_cargo_init(repo_dir: &Path, gitea: &GiteaContext) -> Repo { + let username = gitea.user.username(); assert_cmd::Command::new("cargo") .current_dir(repo_dir) .arg("init") .assert() .success(); - + edit_cargo_toml(repo_dir); let repo = Repo::new(repo_dir).unwrap(); // config local user repo.git(&["config", "user.name", username]).unwrap(); @@ -87,7 +116,7 @@ fn commit_cargo_init(repo_dir: &Path, username: &str) -> Repo { repo.git(&["config", "user.email", "a@example.com"]) .unwrap(); - create_cargo_config(repo_dir); + create_cargo_config(repo_dir, username); // Generate Cargo.lock assert_cmd::Command::new("cargo") @@ -96,35 +125,49 @@ fn commit_cargo_init(repo_dir: &Path, username: &str) -> Repo { .assert() .success(); - assert_cmd::Command::new("cargo") - .current_dir(repo_dir) - .arg("login") - .arg("--registry") - .arg("test-registry") - .arg("random-token") - .assert() - .success(); - repo.add_all_and_commit("Initial commit").unwrap(); repo.git(&["push"]).unwrap(); repo } -fn create_cargo_config(repo_dir: &Path) { - // matches the docker compose file - let cargo_config = r#" -[registries] -test-registry = { index = "http://127.0.0.1:35504/git" } +fn edit_cargo_toml(repo_dir: &Path) { + let cargo_toml_path = repo_dir.join("Cargo.toml"); + let mut cargo_toml = LocalManifest::try_new(&cargo_toml_path).unwrap(); + let mut registry_array = toml_edit::Array::new(); + registry_array.push(TEST_REGISTRY); + cargo_toml.data["package"]["publish"] = + toml_edit::Item::Value(toml_edit::Value::Array(registry_array)); + cargo_toml.write().unwrap(); +} -[net] -git-fetch-with-cli = true - "#; +fn create_cargo_config(repo_dir: &Path, username: &str) { let config_dir = repo_dir.join(".cargo"); fs::create_dir(&config_dir).unwrap(); let config_file = config_dir.join("config.toml"); + let cargo_config = cargo_config(username); fs::write(config_file, cargo_config).unwrap(); } +fn cargo_config(username: &str) -> String { + // matches the docker compose file + let cargo_registries = format!( + "[registry]\ndefault = \"{TEST_REGISTRY}\"\n\n[registries.{TEST_REGISTRY}]\nindex = " + ); + // we use gitea as a cargo registry: + // https://docs.gitea.com/usage/packages/cargo + let gitea_index = format!( + "\"http://{}/{}/{CARGO_INDEX_REPO}.git\"", + gitea_address(), + username + ); + + let config_end = r#" +[net] +git-fetch-with-cli = true + "#; + format!("{}{}{}", cargo_registries, gitea_index, config_end) +} + fn git_client(repo_url: &str, token: &str) -> GitClient { let git_backend = GitBackend::Gitea( Gitea::new( diff --git a/crates/release_plz_core/src/cargo.rs b/crates/release_plz_core/src/cargo.rs index 3e22aaffc7..33a3682fa6 100644 --- a/crates/release_plz_core/src/cargo.rs +++ b/crates/release_plz_core/src/cargo.rs @@ -73,7 +73,7 @@ pub fn is_published_git(index: &mut GitIndex, package: &Package) -> anyhow::Resu } // The package is not in the cache, so we update the cache. - index.update()?; + index.update().context("failed to update git index")?; // Try again with updated index. Ok(is_in_cache_git(index, package)) @@ -86,7 +86,9 @@ fn is_in_cache_git(index: &GitIndex, package: &Package) -> bool { } async fn is_in_cache_sparse(index: &SparseIndex, package: &Package) -> anyhow::Result { - let crate_data = fetch_sparse_metadata(index, &package.name).await?; + let crate_data = fetch_sparse_metadata(index, &package.name) + .await + .context("failed fetching sparse metadata")?; let version = &package.version.to_string(); Ok(is_in_cache(crate_data.as_ref(), version)) } @@ -139,7 +141,7 @@ async fn fetch_sparse_metadata( pub async fn wait_until_published(index: &mut CargoIndex, package: &Package) -> anyhow::Result<()> { let now = Instant::now(); let sleep_time = Duration::from_secs(2); - let timeout = Duration::from_secs(300); + let timeout = Duration::from_secs(60); let mut logged = false; loop { diff --git a/crates/release_plz_core/src/clone/cloner_builder.rs b/crates/release_plz_core/src/clone/cloner_builder.rs index 0d269de84c..c74fae85d5 100644 --- a/crates/release_plz_core/src/clone/cloner_builder.rs +++ b/crates/release_plz_core/src/clone/cloner_builder.rs @@ -3,7 +3,7 @@ use std::{env, path::PathBuf}; use anyhow::Context; -use cargo::{CargoResult, Config}; +use cargo::{core::Shell, util::homedir, CargoResult, Config}; use super::{Cloner, ClonerSource}; @@ -13,6 +13,8 @@ pub struct ClonerBuilder { config: Option, directory: Option, source: ClonerSource, + /// Cargo current working directory. You can use it to point to the right `.cargo/config.toml`. + cargo_cwd: Option, use_git: bool, } @@ -37,11 +39,19 @@ impl ClonerBuilder { Self { source, ..self } } + /// Set cargo working directory. + pub fn with_cargo_cwd(self, path: PathBuf) -> Self { + Self { + cargo_cwd: Some(path), + ..self + } + } + /// Build the [`Cloner`]. pub fn build(self) -> CargoResult { let config = match self.config { Some(config) => config, - None => Config::default().context("Unable to get cargo config.")?, + None => new_cargo_config(self.cargo_cwd).context("Unable to get cargo config.")?, }; let directory = match self.directory { @@ -63,3 +73,17 @@ impl ClonerBuilder { }) } } + +fn new_cargo_config(cwd: Option) -> anyhow::Result { + match cwd { + Some(cwd) => { + let shell = Shell::new(); + let homedir = homedir(&cwd).context( + "Cargo couldn't find your home directory. \ + This probably means that $HOME was not set.", + )?; + Ok(Config::new(shell, cwd, homedir)) + } + None => Config::default(), + } +} diff --git a/crates/release_plz_core/src/command/release.rs b/crates/release_plz_core/src/command/release.rs index 95c4e4429c..02c4a6bbc3 100644 --- a/crates/release_plz_core/src/command/release.rs +++ b/crates/release_plz_core/src/command/release.rs @@ -284,13 +284,19 @@ pub async fn release(input: &ReleaseRequest) -> anyhow::Result<()> { ); continue; } - let registry_indexes = registry_indexes(package, input.registry.clone())?; + let registry_indexes = registry_indexes(package, input.registry.clone()) + .context("can't determine registry indexes")?; for mut index in registry_indexes { - if is_published(&mut index, package).await? { + if is_published(&mut index, package) + .await + .context("can't determine if package is published")? + { info!("{} {}: already published", package.name, package.version); continue; } - release_package(&mut index, package, input, git_tag.clone()).await?; + release_package(&mut index, package, input, git_tag.clone()) + .await + .context("failed to release package")?; } } Ok(()) diff --git a/crates/release_plz_core/src/copy_dir.rs b/crates/release_plz_core/src/copy_dir.rs index 32b089601c..2836b2ca4a 100644 --- a/crates/release_plz_core/src/copy_dir.rs +++ b/crates/release_plz_core/src/copy_dir.rs @@ -44,6 +44,7 @@ pub fn copy_dir(from: impl AsRef, to: impl AsRef) -> anyhow::Result< /// `to` must exist. #[tracing::instrument] +#[allow(clippy::filetype_is_file)] // we want to distinguish between files and symlinks fn copy_directory(from: &Path, to: std::path::PathBuf) -> Result<(), anyhow::Error> { for entry in WalkDir::new(from) { let entry = entry.context("invalid entry")?; diff --git a/crates/release_plz_core/src/download.rs b/crates/release_plz_core/src/download.rs index cbda165b8e..21917cc1e5 100644 --- a/crates/release_plz_core/src/download.rs +++ b/crates/release_plz_core/src/download.rs @@ -1,6 +1,6 @@ //! Download packages from cargo registry, similar to the `git clone` behavior. -use std::{fmt, path::Path}; +use std::path::{Path, PathBuf}; use anyhow::{anyhow, Context}; use cargo_metadata::Package; @@ -11,34 +11,70 @@ use crate::{ CARGO_TOML, }; -#[instrument] -pub fn download_packages( - packages: &[&str], - directory: impl AsRef + fmt::Debug, - registry: Option<&str>, -) -> anyhow::Result> { - let directory = directory.as_ref(); - info!("downloading packages from cargo registry"); - let source: ClonerSource = match registry { - Some(registry) => ClonerSource::registry(registry), - None => ClonerSource::crates_io(), - }; - let crates: Vec = packages - .iter() - .map(|&package_name| Crate::new(package_name.to_string(), None)) - .collect(); - let downloaded_packages = Cloner::builder() - .with_directory(directory) - .with_source(source) - .build() - .context("can't build cloner")? - .clone(&crates) - .context("error while downloading packages")?; +#[derive(Debug)] +pub struct PackageDownloader { + packages: Vec, + directory: String, + registry: Option, + cargo_cwd: Option, +} + +impl PackageDownloader { + pub fn new( + packages: impl IntoIterator>, + directory: impl Into, + ) -> Self { + Self { + packages: packages.into_iter().map(Into::into).collect(), + directory: directory.into(), + registry: None, + cargo_cwd: None, + } + } + + pub fn with_registry(self, registry: String) -> Self { + Self { + registry: Some(registry), + ..self + } + } - downloaded_packages - .iter() - .map(|(_package, path)| read_package(path)) - .collect() + pub fn with_cargo_cwd(self, cargo_cwd: PathBuf) -> Self { + Self { + cargo_cwd: Some(cargo_cwd), + ..self + } + } + + #[instrument] + pub fn download(&self) -> anyhow::Result> { + info!("downloading packages from cargo registry"); + let source: ClonerSource = match &self.registry { + Some(registry) => ClonerSource::registry(registry), + None => ClonerSource::crates_io(), + }; + let crates: Vec = self + .packages + .iter() + .map(|package_name| Crate::new(package_name.to_string(), None)) + .collect(); + let mut cloner_builder = Cloner::builder() + .with_directory(&self.directory) + .with_source(source); + if let Some(cwd) = &self.cargo_cwd { + cloner_builder = cloner_builder.with_cargo_cwd(cwd.clone()); + } + let downloaded_packages = cloner_builder + .build() + .context("can't build cloner")? + .clone(&crates) + .context("error while downloading packages")?; + + downloaded_packages + .iter() + .map(|(_package, path)| read_package(path)) + .collect() + } } /// Read a package from file system @@ -69,7 +105,9 @@ mod tests { let package_name = "rand"; let temp_dir = tempdir().unwrap(); let directory = temp_dir.as_ref().to_str().expect("invalid tempdir path"); - let packages = download_packages(&[package_name], directory, None).unwrap(); + let packages = PackageDownloader::new([package_name], directory) + .download() + .unwrap(); let rand = &packages[0]; assert_eq!(rand.name, package_name); } @@ -81,8 +119,9 @@ mod tests { let second_package = "rust-gh-example"; let temp_dir = tempdir().unwrap(); let directory = temp_dir.as_ref().to_str().expect("invalid tempdir path"); - let packages = - download_packages(&[first_package, second_package], directory, None).unwrap(); + let packages = PackageDownloader::new([first_package, second_package], directory) + .download() + .unwrap(); assert_eq!(&packages[0].name, first_package); assert_eq!(&packages[1].name, second_package); } @@ -94,6 +133,8 @@ mod tests { let package: String = 15.fake(); let temp_dir = tempdir().unwrap(); let directory = temp_dir.as_ref().to_str().expect("invalid tempdir path"); - download_packages(&[&package], directory, None).unwrap(); + PackageDownloader::new([&package], directory) + .download() + .unwrap(); } } diff --git a/crates/release_plz_core/src/lib.rs b/crates/release_plz_core/src/lib.rs index a30f4487f8..945d0e312c 100644 --- a/crates/release_plz_core/src/lib.rs +++ b/crates/release_plz_core/src/lib.rs @@ -22,7 +22,7 @@ mod version; pub use changelog::*; pub use command::*; -pub use download::read_package; +pub use download::{read_package, PackageDownloader}; pub use git::backend::{GitBackend, GitClient, GitPr}; pub use git::gitea_client::Gitea; pub use git::github_client::GitHub; diff --git a/crates/release_plz_core/src/registry_packages.rs b/crates/release_plz_core/src/registry_packages.rs index 4f9eea2fc6..9e60e7b71a 100644 --- a/crates/release_plz_core/src/registry_packages.rs +++ b/crates/release_plz_core/src/registry_packages.rs @@ -27,12 +27,18 @@ pub fn get_registry_packages( let (temp_dir, registry_packages) = match registry_manifest { Some(manifest) => (None, next_ver::publishable_packages(manifest)?), None => { - let temp_dir = tempdir()?; + let temp_dir = tempdir().context("failed to get a temporary directory")?; let local_packages_names: Vec<&str> = local_packages.iter().map(|c| c.name.as_str()).collect(); let directory = temp_dir.as_ref().to_str().context("invalid tempdir path")?; - let registry_packages = - download::download_packages(&local_packages_names, directory, registry)?; + + let mut downloader = download::PackageDownloader::new(local_packages_names, directory); + if let Some(registry) = registry { + downloader = downloader.with_registry(registry.to_string()); + } + let registry_packages = downloader + .download() + .context("failed to download packages")?; (Some(temp_dir), registry_packages) } }; diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index 105364db3a..ddab8ab24f 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -38,13 +38,3 @@ services: interval: 5s timeout: 5s retries: 10 - # With Cargo-http-registry we mock crates.io. - registry: - image: ghcr.io/d-e-s-o/cargo-http-registry:sha-7556ed9 - container_name: cargo-registry - restart: always - # Directory where the registry will store its data. - # Cargo-http-registry creates the directory if it does not exist. - command: /tmp/test-registry -a 0.0.0.0:35504 - ports: - - "35504:35504"