Skip to content

Commit f99509f

Browse files
fix(build): Allow clearing string arguments to build upload (#2946)
### Description Don't serialize empty-string values for `--vcs-provider`, `--head-repo-name`, `--head-ref`, `--base-ref`, and `--base-repo-name` into HTTP requests to the assemble build artifact endpoint. This allows users to set these values to empty strings to override any default values. ### Issues - Resolves #2941 - Resolves [CLI-224](https://linear.app/getsentry/issue/CLI-224/skip-serializing-certain-fields-for-build-upload)
1 parent a2cef20 commit f99509f

File tree

4 files changed

+84
-21
lines changed

4 files changed

+84
-21
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
- Added validation for the `sentry-cli build upload` command's `--head-sha` and `--base-sha` arguments ([#2945](https://github.com/getsentry/sentry-cli/pull/2945)). The CLI now validates that these are valid SHA1 sums. Passing an empty string is also allowed; this prevents the default values from being used, causing the values to instead be unset.
88

9+
### Fixes
10+
11+
- Fixed a bug where providing empty-string values for the `sentry-cli build upload` command's `--vcs-provider`, `--head-repo-name`, `--head-ref`, `--base-ref`, and `--base-repo-name` arguments resulted in 400 errors ([#2946](https://github.com/getsentry/sentry-cli/pull/2946)). Now, setting these to empty strings instead explicitly clears the default value we would set otherwise, as expected.
12+
913
## 2.58.1
1014

1115
### Deprecations

src/api/data_types/chunking/build.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,16 @@ pub struct VcsInfo<'a> {
3131
pub head_sha: Option<Digest>,
3232
#[serde(skip_serializing_if = "Option::is_none")]
3333
pub base_sha: Option<Digest>,
34-
#[serde(skip_serializing_if = "Option::is_none", rename = "provider")]
35-
pub vcs_provider: Option<&'a str>,
36-
#[serde(skip_serializing_if = "Option::is_none")]
37-
pub head_repo_name: Option<&'a str>,
38-
#[serde(skip_serializing_if = "Option::is_none")]
39-
pub base_repo_name: Option<&'a str>,
40-
#[serde(skip_serializing_if = "Option::is_none")]
41-
pub head_ref: Option<&'a str>,
42-
#[serde(skip_serializing_if = "Option::is_none")]
43-
pub base_ref: Option<&'a str>,
34+
#[serde(skip_serializing_if = "str::is_empty", rename = "provider")]
35+
pub vcs_provider: &'a str,
36+
#[serde(skip_serializing_if = "str::is_empty")]
37+
pub head_repo_name: &'a str,
38+
#[serde(skip_serializing_if = "str::is_empty")]
39+
pub base_repo_name: &'a str,
40+
#[serde(skip_serializing_if = "str::is_empty")]
41+
pub head_ref: &'a str,
42+
#[serde(skip_serializing_if = "str::is_empty")]
43+
pub base_ref: &'a str,
4444
#[serde(skip_serializing_if = "Option::is_none")]
4545
pub pr_number: Option<&'a u32>,
4646
}

src/commands/build/upload.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
137137
.as_ref()
138138
.map(|url| get_provider_from_remote(url))
139139
.map(Cow::Owned)
140-
});
140+
})
141+
.unwrap_or_default();
141142

142143
let head_repo_name = matches
143144
.get_one("head_repo_name")
@@ -148,7 +149,8 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
148149
.as_ref()
149150
.map(|url| get_repo_from_remote_preserve_case(url))
150151
.map(Cow::Owned)
151-
});
152+
})
153+
.unwrap_or_default();
152154

153155
let head_ref = matches
154156
.get_one("head_ref")
@@ -175,7 +177,8 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
175177
}
176178
})
177179
.map(Cow::Owned)
178-
});
180+
})
181+
.unwrap_or_default();
179182

180183
let base_ref = matches
181184
.get_one("base_ref")
@@ -199,7 +202,8 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
199202
}
200203
})
201204
.map(Cow::Owned)
202-
});
205+
})
206+
.unwrap_or_default();
203207

204208
let base_repo_name = matches
205209
.get_one("base_repo_name")
@@ -223,7 +227,8 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
223227
}
224228
})
225229
.map(Cow::Owned)
226-
});
230+
})
231+
.unwrap_or_default();
227232

228233
(
229234
vcs_provider,
@@ -266,7 +271,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
266271
base_sha.expect("base_sha is Some at this point")
267272
);
268273
base_sha = None;
269-
base_ref = None;
274+
base_ref = "".into();
270275
}
271276
let pr_number = matches
272277
.get_one("pr_number")
@@ -331,11 +336,11 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
331336
let vcs_info = VcsInfo {
332337
head_sha,
333338
base_sha,
334-
vcs_provider: vcs_provider.as_deref(),
335-
head_repo_name: head_repo_name.as_deref(),
336-
base_repo_name: base_repo_name.as_deref(),
337-
head_ref: head_ref.as_deref(),
338-
base_ref: base_ref.as_deref(),
339+
vcs_provider: &vcs_provider,
340+
head_repo_name: &head_repo_name,
341+
base_repo_name: &base_repo_name,
342+
head_ref: &head_ref,
343+
base_ref: &base_ref,
339344
pr_number: pr_number.as_ref(),
340345
};
341346
match upload_file(

tests/integration/build/upload.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,3 +278,57 @@ fn command_build_upload_empty_shas() {
278278
.register_trycmd_test("build/build-upload-empty-shas.trycmd")
279279
.with_default_token();
280280
}
281+
282+
/// Verify that all string-based arguments to `build upload` can be set to an empty string,
283+
/// and that setting to empty string results in the corresponding fields being omitted from
284+
/// the request body.
285+
#[test]
286+
fn command_build_upload_empty_refs() {
287+
TestManager::new()
288+
.mock_endpoint(
289+
MockEndpointBuilder::new("GET", "/api/0/organizations/wat-org/chunk-upload/")
290+
.with_response_file("build/get-chunk-upload.json"),
291+
)
292+
.mock_endpoint(
293+
MockEndpointBuilder::new(
294+
"POST",
295+
"/api/0/projects/wat-org/wat-project/files/preprodartifacts/assemble/",
296+
)
297+
.with_response_fn(move |req| {
298+
let body = req.body().expect("body should be readable");
299+
let json: serde_json::Value =
300+
serde_json::from_slice(body).expect("body should be valid JSON");
301+
302+
assert!(json.get("provider").is_none());
303+
assert!(json.get("head_repo_name").is_none());
304+
assert!(json.get("base_repo_name").is_none());
305+
assert!(json.get("head_ref").is_none());
306+
assert!(json.get("base_ref").is_none());
307+
308+
serde_json::json!({
309+
"state": "created",
310+
"missingChunks": [],
311+
"artifactUrl": "http://sentry.io/wat-org/preprod/wat-project/42"
312+
})
313+
.to_string()
314+
.into()
315+
}),
316+
)
317+
.assert_cmd([
318+
"build",
319+
"upload",
320+
"tests/integration/_fixtures/build/apk.apk",
321+
"--vcs-provider",
322+
"",
323+
"--head-repo-name",
324+
"",
325+
"--base-repo-name",
326+
"",
327+
"--head-ref",
328+
"",
329+
"--base-ref",
330+
"",
331+
])
332+
.with_default_token()
333+
.run_and_assert(AssertCommand::Success);
334+
}

0 commit comments

Comments
 (0)