Skip to content

Commit 60ac9f4

Browse files
authored
smoke_test: Check failed publish with large payload (#10106)
The "invalid authentication" check was actually resulting in a false-positive, since the request payload was small enough to not trigger the Cloudfront bug. This commit adjusts the smoke test to generate a 15 MB dummy file which we then try to publish instead.
1 parent e6ec730 commit 60ac9f4

File tree

3 files changed

+74
-37
lines changed

3 files changed

+74
-37
lines changed

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.

crates/crates_io_smoke_test/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ anyhow = "=1.0.93"
1212
bytes = "=1.9.0"
1313
clap = { version = "=4.5.21", features = ["derive", "env", "unicode", "wrap_help"] }
1414
crates_io_index = { path = "../crates_io_index" }
15+
rand = "=0.8.5"
1516
reqwest = { version = "=0.12.9", features = ["gzip", "json"] }
1617
secrecy = "=0.10.3"
1718
semver = { version = "=1.0.23", features = ["serde"] }

crates/crates_io_smoke_test/src/main.rs

Lines changed: 72 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use secrecy::SecretString;
1313
use std::path::{Path, PathBuf};
1414
use tempfile::tempdir;
1515
use tokio::fs;
16+
use tokio::io::AsyncWriteExt;
1617
use tracing_subscriber::filter::LevelFilter;
1718
use tracing_subscriber::layer::SubscriberExt;
1819
use tracing_subscriber::util::SubscriberInitExt;
@@ -53,8 +54,12 @@ async fn main() -> anyhow::Result<()> {
5354
let old_version = krate.max_version;
5455
let mut new_version = old_version.clone();
5556

56-
new_version.patch += 1;
57-
info!(%old_version, %new_version, "Calculated new version number");
57+
if !options.skip_publish {
58+
new_version.patch += 1;
59+
info!(%old_version, %new_version, "Calculated new version number");
60+
} else {
61+
info!(%old_version, %new_version, "Using old version number since `--skip-publish` is set");
62+
}
5863

5964
info!("Creating temporary working folder…");
6065
let tempdir = tempdir().context("Failed to create temporary working folder")?;
@@ -65,37 +70,20 @@ async fn main() -> anyhow::Result<()> {
6570
.await
6671
.context("Failed to create project")?;
6772

68-
info!("Checking publish with invalid authentication…");
69-
let invalid_token = "invalid-token".into();
70-
let output = cargo::publish_with_output(&project_path, &invalid_token).await?;
71-
if output.status.success() {
72-
bail!("Expected `cargo publish` to fail with invalid token");
73-
} else {
74-
let stderr = String::from_utf8_lossy(&output.stderr);
75-
if !stderr.contains("401 Unauthorized")
76-
|| !stderr.contains("The given API token does not match the format used by crates.io")
77-
{
78-
bail!("Expected `cargo publish` to fail with an `401 Unauthorized` error, but got: {stderr}");
79-
}
80-
}
81-
8273
if options.skip_publish {
8374
info!("Packaging crate file…");
8475
cargo::package(&project_path)
8576
.await
8677
.context("Failed to run `cargo package`")?;
8778

8879
info!("Skipping publish step");
89-
new_version = old_version;
9080
} else {
9181
info!("Publishing to staging.crates.io…");
9282
cargo::publish(&project_path, &options.token)
9383
.await
9484
.context("Failed to run `cargo publish`")?;
9585
}
9686

97-
drop(tempdir);
98-
9987
let version = new_version;
10088
info!(%version, "Checking staging.crates.io API for the new version…");
10189

@@ -176,6 +164,22 @@ async fn main() -> anyhow::Result<()> {
176164
return Err(anyhow!("Failed to find published version on the git index"));
177165
}
178166

167+
if !options.skip_publish {
168+
info!("Checking failed publish with large payload…");
169+
create_dummy_content(&project_path).await?;
170+
171+
info!("Sending publish request…");
172+
let output = cargo::publish_with_output(&project_path, &options.token).await?;
173+
if output.status.success() {
174+
bail!("Expected `cargo publish` to fail with invalid token");
175+
} else {
176+
let stderr = String::from_utf8_lossy(&output.stderr);
177+
if !stderr.contains("413 Payload Too Large") {
178+
bail!("Expected `cargo publish` to fail with an `413 Payload Too Large` error, but got:\n{stderr}");
179+
}
180+
}
181+
}
182+
179183
info!(
180184
"All automated smoke tests have passed.\n\nPlease visit https://staging.crates.io/crates/{}/{} for further manual testing.",
181185
&options.crate_name, &version
@@ -201,31 +205,16 @@ async fn create_project(
201205
name: &str,
202206
version: &semver::Version,
203207
) -> anyhow::Result<PathBuf> {
208+
let version = version.to_string();
209+
204210
cargo::new_lib(parent_path, name)
205211
.await
206212
.context("Failed to run `cargo new`")?;
207213

208214
let project_path = parent_path.join(name);
209215
debug!(project_path = %project_path.display());
210216

211-
{
212-
let manifest_path = project_path.join("Cargo.toml");
213-
info!(manifest_path = %manifest_path.display(), "Overriding `Cargo.toml` file…");
214-
215-
let new_content = format!(
216-
r#"[package]
217-
name = "{name}"
218-
version = "{version}"
219-
edition = "2018"
220-
license = "MIT"
221-
description = "test crate"
222-
"#,
223-
);
224-
225-
fs::write(&manifest_path, new_content)
226-
.await
227-
.context("Failed to write `Cargo.toml` file content")?;
228-
}
217+
write_manifest(&project_path, name, &version).await?;
229218

230219
{
231220
let readme_path = project_path.join("README.md");
@@ -259,3 +248,49 @@ description = "test crate"
259248

260249
Ok(project_path)
261250
}
251+
252+
async fn write_manifest(project_path: &Path, name: &str, version: &str) -> anyhow::Result<()> {
253+
let manifest_path = project_path.join("Cargo.toml");
254+
info!(manifest_path = %manifest_path.display(), "Overriding `Cargo.toml` file…");
255+
256+
let new_content = format!(
257+
r#"[package]
258+
name = "{name}"
259+
version = "{version}"
260+
edition = "2018"
261+
license = "MIT"
262+
description = "test crate"
263+
"#,
264+
);
265+
266+
fs::write(&manifest_path, new_content)
267+
.await
268+
.context("Failed to write `Cargo.toml` file content")?;
269+
270+
Ok(())
271+
}
272+
273+
async fn create_dummy_content(project_path: &Path) -> anyhow::Result<()> {
274+
const FILE_SIZE: u32 = 15 * 1024 * 1024;
275+
276+
debug!("Creating `dummy.txt` file…");
277+
let f = fs::File::create(project_path.join("dummy.txt")).await?;
278+
let mut writer = tokio::io::BufWriter::new(f);
279+
for _ in 0..(FILE_SIZE / 16) {
280+
writer.write_u128(rand::random()).await?;
281+
}
282+
drop(writer);
283+
284+
write_manifest(project_path, "dummy", "0.0.0-dummy").await?;
285+
286+
debug!("Creating additional git commit…");
287+
git::add_all(project_path)
288+
.await
289+
.context("Failed to add changes to git")?;
290+
291+
git::commit(project_path, "add dummy content")
292+
.await
293+
.context("Failed to commit changes")?;
294+
295+
Ok(())
296+
}

0 commit comments

Comments
 (0)