Skip to content

Commit 75920e8

Browse files
authored
feat(mobile-app): Add new VCS params to mobile-app command (#2682)
Adds new VCS params as args to the `mobile-app` command and passes them to the API (pending getsentry/sentry#97332). Notably removes `sha` in favor of `head_sha`. Given this command is still unreleased and marked experimental, this would usually be a breaking change but I don't believe we need any backwards compatibility here. We'll implement default value providing for most of these as well in follow ups, as I'd prefer to silo those implementations for easier review && testing.
1 parent 17d95d4 commit 75920e8

File tree

8 files changed

+168
-31
lines changed

8 files changed

+168
-31
lines changed

src/api/data_types/chunking/mobile_app.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,24 @@ pub struct ChunkedMobileAppRequest<'a> {
99
pub checksum: Digest,
1010
pub chunks: &'a [Digest],
1111
#[serde(skip_serializing_if = "Option::is_none")]
12+
pub build_configuration: Option<&'a str>,
13+
// VCS fields
14+
#[serde(skip_serializing_if = "Option::is_none")]
1215
pub head_sha: Option<&'a str>,
1316
#[serde(skip_serializing_if = "Option::is_none")]
14-
pub build_configuration: Option<&'a str>,
17+
pub base_sha: Option<&'a str>,
18+
#[serde(skip_serializing_if = "Option::is_none")]
19+
pub provider: Option<&'a str>,
20+
#[serde(skip_serializing_if = "Option::is_none")]
21+
pub head_repo_name: Option<&'a str>,
22+
#[serde(skip_serializing_if = "Option::is_none")]
23+
pub base_repo_name: Option<&'a str>,
24+
#[serde(skip_serializing_if = "Option::is_none")]
25+
pub head_ref: Option<&'a str>,
26+
#[serde(skip_serializing_if = "Option::is_none")]
27+
pub base_ref: Option<&'a str>,
28+
#[serde(skip_serializing_if = "Option::is_none")]
29+
pub pr_number: Option<&'a u32>,
1530
}
1631

1732
#[derive(Debug, Deserialize)]

src/api/mod.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,8 +1036,8 @@ impl<'a> AuthenticatedApi<'a> {
10361036
project: &str,
10371037
checksum: Digest,
10381038
chunks: &[Digest],
1039-
head_sha: Option<&str>,
10401039
build_configuration: Option<&str>,
1040+
vcs_info: &VcsInfo<'_>,
10411041
) -> ApiResult<AssembleMobileAppResponse> {
10421042
let url = format!(
10431043
"/projects/{}/{}/files/preprodartifacts/assemble/",
@@ -1049,8 +1049,15 @@ impl<'a> AuthenticatedApi<'a> {
10491049
.with_json_body(&ChunkedMobileAppRequest {
10501050
checksum,
10511051
chunks,
1052-
head_sha,
10531052
build_configuration,
1053+
head_sha: vcs_info.head_sha,
1054+
base_sha: vcs_info.base_sha,
1055+
provider: vcs_info.vcs_provider,
1056+
head_repo_name: vcs_info.head_repo_name,
1057+
base_repo_name: vcs_info.base_repo_name,
1058+
head_ref: vcs_info.head_ref,
1059+
base_ref: vcs_info.base_ref,
1060+
pr_number: vcs_info.pr_number,
10541061
})?
10551062
.send()?
10561063
.convert_rnf(ApiErrorKind::ProjectNotFound)
@@ -2518,6 +2525,20 @@ struct LogsResponse {
25182525
data: Vec<LogEntry>,
25192526
}
25202527

2528+
/// VCS information for mobile app uploads
2529+
#[cfg(feature = "unstable-mobile-app")]
2530+
#[derive(Debug)]
2531+
pub struct VcsInfo<'a> {
2532+
pub head_sha: Option<&'a str>,
2533+
pub base_sha: Option<&'a str>,
2534+
pub vcs_provider: Option<&'a str>,
2535+
pub head_repo_name: Option<&'a str>,
2536+
pub base_repo_name: Option<&'a str>,
2537+
pub head_ref: Option<&'a str>,
2538+
pub base_ref: Option<&'a str>,
2539+
pub pr_number: Option<&'a u32>,
2540+
}
2541+
25212542
/// Log entry structure from the logs API
25222543
#[derive(Debug, Deserialize)]
25232544
pub struct LogEntry {

src/commands/mobile_app/upload.rs

Lines changed: 73 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use symbolic::common::ByteView;
1010
use zip::write::SimpleFileOptions;
1111
use zip::{DateTime, ZipWriter};
1212

13-
use crate::api::{Api, AuthenticatedApi, ChunkUploadCapability, ChunkedFileState};
13+
use crate::api::{Api, AuthenticatedApi, ChunkUploadCapability, ChunkedFileState, VcsInfo};
1414
use crate::config::Config;
1515
use crate::utils::args::ArgExt as _;
1616
use crate::utils::chunks::{upload_chunks, Chunk};
@@ -44,9 +44,45 @@ pub fn make_command(command: Command) -> Command {
4444
.required(true),
4545
)
4646
.arg(
47-
Arg::new("sha")
48-
.long("sha")
49-
.help("The git commit sha to use for the upload. If not provided, the current commit sha will be used.")
47+
Arg::new("head_sha")
48+
.long("head-sha")
49+
.help("The VCS commit sha to use for the upload. If not provided, the current commit sha will be used.")
50+
)
51+
.arg(
52+
Arg::new("base_sha")
53+
.long("base-sha")
54+
.help("The VCS commit's base sha to use for the upload. If not provided, the merge-base of the current and remote branch will be used.")
55+
)
56+
.arg(
57+
Arg::new("vcs_provider")
58+
.long("vcs-provider")
59+
.help("The VCS provider to use for the upload. If not provided, the current provider will be used.")
60+
)
61+
.arg(
62+
Arg::new("head_repo_name")
63+
.long("head-repo-name")
64+
.help("The name of the git repository to use for the upload (e.g. organization/repository). If not provided, the current repository will be used.")
65+
)
66+
.arg(
67+
Arg::new("base_repo_name")
68+
.long("base-repo-name")
69+
.help("The name of the git repository to use for the upload (e.g. organization/repository). If not provided, the current repository will be used.")
70+
)
71+
.arg(
72+
Arg::new("head_ref")
73+
.long("head-ref")
74+
.help("The reference (branch) to use for the upload. If not provided, the current reference will be used.")
75+
)
76+
.arg(
77+
Arg::new("base_ref")
78+
.long("base-ref")
79+
.help("The reference (branch) to use for the upload. If not provided, the current reference will be used.")
80+
)
81+
.arg(
82+
Arg::new("pr_number")
83+
.long("pr-number")
84+
.value_parser(clap::value_parser!(u32))
85+
.help("The pull request number to use for the upload. If not provided, the current pull request number will be used.")
5086
)
5187
.arg(
5288
Arg::new("build_configuration")
@@ -60,12 +96,20 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
6096
.get_many::<String>("paths")
6197
.expect("paths argument is required");
6298

63-
let sha = matches
64-
.get_one("sha")
99+
let head_sha = matches
100+
.get_one("head_sha")
65101
.map(String::as_str)
66102
.map(Cow::Borrowed)
67103
.or_else(|| vcs::find_head().ok().map(Cow::Owned));
68104

105+
let base_sha = matches.get_one("base_sha").map(String::as_str);
106+
let vcs_provider = matches.get_one("vcs_provider").map(String::as_str);
107+
let head_repo_name = matches.get_one("head_repo_name").map(String::as_str);
108+
let base_repo_name = matches.get_one("base_repo_name").map(String::as_str);
109+
let head_ref = matches.get_one("head_ref").map(String::as_str);
110+
let base_ref = matches.get_one("base_ref").map(String::as_str);
111+
let pr_number = matches.get_one::<u32>("pr_number");
112+
69113
let build_configuration = matches.get_one("build_configuration").map(String::as_str);
70114

71115
let api = Api::current();
@@ -124,13 +168,23 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
124168
for (path, zip) in normalized_zips {
125169
info!("Uploading file: {}", path.display());
126170
let bytes = ByteView::open(zip.path())?;
171+
let vcs_info = VcsInfo {
172+
head_sha: head_sha.as_deref(),
173+
base_sha,
174+
vcs_provider,
175+
head_repo_name,
176+
base_repo_name,
177+
head_ref,
178+
base_ref,
179+
pr_number,
180+
};
127181
match upload_file(
128182
&authenticated_api,
129183
&bytes,
130184
&org,
131185
&project,
132-
sha.as_deref(),
133186
build_configuration,
187+
&vcs_info,
134188
) {
135189
Ok(artifact_id) => {
136190
info!("Successfully uploaded file: {}", path.display());
@@ -289,18 +343,18 @@ fn upload_file(
289343
bytes: &[u8],
290344
org: &str,
291345
project: &str,
292-
sha: Option<&str>,
293346
build_configuration: Option<&str>,
347+
vcs_info: &VcsInfo<'_>,
294348
) -> Result<String> {
295349
const SELF_HOSTED_ERROR_HINT: &str = "If you are using a self-hosted Sentry server, \
296350
update to the latest version of Sentry to use the mobile-app upload command.";
297351

298352
debug!(
299-
"Uploading file to organization: {}, project: {}, sha: {}, build_configuration: {}",
353+
"Uploading file to organization: {}, project: {}, build_configuration: {}, vcs_info: {:?}",
300354
org,
301355
project,
302-
sha.unwrap_or("unknown"),
303-
build_configuration.unwrap_or("unknown")
356+
build_configuration.unwrap_or("unknown"),
357+
vcs_info,
304358
);
305359

306360
let chunk_upload_options = api.get_chunk_upload_options(org)?.ok_or_else(|| {
@@ -346,8 +400,14 @@ fn upload_file(
346400
// iteration of the loop) we get:
347401
// n. state=err, artifact_id unset
348402
let result = loop {
349-
let response =
350-
api.assemble_mobile_app(org, project, checksum, &checksums, sha, build_configuration)?;
403+
let response = api.assemble_mobile_app(
404+
org,
405+
project,
406+
checksum,
407+
&checksums,
408+
build_configuration,
409+
vcs_info,
410+
)?;
351411
chunks.retain(|Chunk((digest, _))| response.missing_chunks.contains(digest));
352412

353413
if !chunks.is_empty() {

tests/integration/_cases/mobile_app/mobile_app-upload-apk.trycmd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
```
2-
$ sentry-cli mobile-app upload tests/integration/_fixtures/mobile_app/apk.apk --sha test_sha
2+
$ sentry-cli mobile-app upload tests/integration/_fixtures/mobile_app/apk.apk --head-sha test_head_sha
33
? success
44
[..]WARN[..]EXPERIMENTAL: The mobile-app subcommand is experimental. The command is subject to breaking changes and may be removed without notice in any release.
55
Successfully uploaded 1 file to Sentry

tests/integration/_cases/mobile_app/mobile_app-upload-help-macos.trycmd

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,38 @@ Options:
1919
The project ID or slug.
2020
--auth-token <AUTH_TOKEN>
2121
Use the given Sentry auth token.
22-
--sha <sha>
23-
The git commit sha to use for the upload. If not provided, the current commit sha will be
22+
--head-sha <head_sha>
23+
The VCS commit sha to use for the upload. If not provided, the current commit sha will be
2424
used.
25-
--build-configuration <build_configuration>
26-
The build configuration to use for the upload. If not provided, the current version will
27-
be used.
25+
--base-sha <base_sha>
26+
The VCS commit's base sha to use for the upload. If not provided, the merge-base of the
27+
current and remote branch will be used.
2828
--log-level <LOG_LEVEL>
2929
Set the log output verbosity. [possible values: trace, debug, info, warn, error]
30+
--vcs-provider <vcs_provider>
31+
The VCS provider to use for the upload. If not provided, the current provider will be
32+
used.
33+
--head-repo-name <head_repo_name>
34+
The name of the git repository to use for the upload (e.g. organization/repository). If
35+
not provided, the current repository will be used.
3036
--quiet
3137
Do not print any output while preserving correct exit code. This flag is currently
3238
implemented only for selected subcommands. [aliases: silent]
39+
--base-repo-name <base_repo_name>
40+
The name of the git repository to use for the upload (e.g. organization/repository). If
41+
not provided, the current repository will be used.
42+
--head-ref <head_ref>
43+
The reference (branch) to use for the upload. If not provided, the current reference will
44+
be used.
45+
--base-ref <base_ref>
46+
The reference (branch) to use for the upload. If not provided, the current reference will
47+
be used.
48+
--pr-number <pr_number>
49+
The pull request number to use for the upload. If not provided, the current pull request
50+
number will be used.
51+
--build-configuration <build_configuration>
52+
The build configuration to use for the upload. If not provided, the current version will
53+
be used.
3354
-h, --help
3455
Print help
3556

tests/integration/_cases/mobile_app/mobile_app-upload-help-not-macos.trycmd

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
```
22
$ sentry-cli mobile-app upload --help
3-
? success
43
[EXPERIMENTAL] Upload mobile app files to a project.
54

65
Usage: sentry-cli[EXE] mobile-app upload [OPTIONS] <PATH>...
@@ -18,17 +17,38 @@ Options:
1817
The project ID or slug.
1918
--auth-token <AUTH_TOKEN>
2019
Use the given Sentry auth token.
21-
--sha <sha>
22-
The git commit sha to use for the upload. If not provided, the current commit sha will be
20+
--head-sha <head_sha>
21+
The VCS commit sha to use for the upload. If not provided, the current commit sha will be
2322
used.
24-
--build-configuration <build_configuration>
25-
The build configuration to use for the upload. If not provided, the current version will
26-
be used.
23+
--base-sha <base_sha>
24+
The VCS commit's base sha to use for the upload. If not provided, the merge-base of the
25+
current and remote branch will be used.
2726
--log-level <LOG_LEVEL>
2827
Set the log output verbosity. [possible values: trace, debug, info, warn, error]
28+
--vcs-provider <vcs_provider>
29+
The VCS provider to use for the upload. If not provided, the current provider will be
30+
used.
31+
--head-repo-name <head_repo_name>
32+
The name of the git repository to use for the upload (e.g. organization/repository). If
33+
not provided, the current repository will be used.
2934
--quiet
3035
Do not print any output while preserving correct exit code. This flag is currently
3136
implemented only for selected subcommands. [aliases: silent]
37+
--base-repo-name <base_repo_name>
38+
The name of the git repository to use for the upload (e.g. organization/repository). If
39+
not provided, the current repository will be used.
40+
--head-ref <head_ref>
41+
The reference (branch) to use for the upload. If not provided, the current reference will
42+
be used.
43+
--base-ref <base_ref>
44+
The reference (branch) to use for the upload. If not provided, the current reference will
45+
be used.
46+
--pr-number <pr_number>
47+
The pull request number to use for the upload. If not provided, the current pull request
48+
number will be used.
49+
--build-configuration <build_configuration>
50+
The build configuration to use for the upload. If not provided, the current version will
51+
be used.
3252
-h, --help
3353
Print help
3454

tests/integration/_cases/mobile_app/mobile_app-upload-ipa.trycmd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
```
2-
$ sentry-cli mobile-app upload tests/integration/_fixtures/mobile_app/ipa.ipa --sha test_sha
2+
$ sentry-cli mobile-app upload tests/integration/_fixtures/mobile_app/ipa.ipa --head-sha test_head_sha
33
? success
44
[..]WARN[..]EXPERIMENTAL: The mobile-app subcommand is experimental. The command is subject to breaking changes and may be removed without notice in any release.
55
Successfully uploaded 1 file to Sentry

tests/integration/mobile_app/upload.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ fn command_mobile_app_upload_apk_chunked() {
159159
"/api/0/projects/wat-org/wat-project/files/preprodartifacts/assemble/",
160160
)
161161
.with_header_matcher("content-type", "application/json")
162-
.with_matcher(r#"{"checksum":"18e40e6e932d0b622d631e887be454cc2003dbb5","chunks":["18e40e6e932d0b622d631e887be454cc2003dbb5"],"head_sha":"test_sha"}"#)
162+
.with_matcher(r#"{"checksum":"18e40e6e932d0b622d631e887be454cc2003dbb5","chunks":["18e40e6e932d0b622d631e887be454cc2003dbb5"],"head_sha":"test_head_sha"}"#)
163163
.with_response_fn(move |_| {
164164
if is_first_assemble_call.swap(false, Ordering::Relaxed) {
165165
r#"{
@@ -214,7 +214,7 @@ fn command_mobile_app_upload_ipa_chunked() {
214214
"/api/0/projects/wat-org/wat-project/files/preprodartifacts/assemble/",
215215
)
216216
.with_header_matcher("content-type", "application/json")
217-
.with_matcher(r#"{"checksum":"ed9da71e3688261875db21b266da84ffe004a8a4","chunks":["ed9da71e3688261875db21b266da84ffe004a8a4"],"head_sha":"test_sha"}"#)
217+
.with_matcher(r#"{"checksum":"ed9da71e3688261875db21b266da84ffe004a8a4","chunks":["ed9da71e3688261875db21b266da84ffe004a8a4"],"head_sha":"test_head_sha"}"#)
218218
.with_response_fn(move |_| {
219219
if is_first_assemble_call.swap(false, Ordering::Relaxed) {
220220
r#"{

0 commit comments

Comments
 (0)