@@ -16,7 +16,7 @@ use symbolic::common::ByteView;
16
16
use zip:: write:: SimpleFileOptions ;
17
17
use zip:: { DateTime , ZipWriter } ;
18
18
19
- use crate :: api:: { Api , AuthenticatedApi , ChunkUploadCapability } ;
19
+ use crate :: api:: { Api , AssembleMobileAppResponse , AuthenticatedApi , ChunkUploadCapability } ;
20
20
use crate :: config:: Config ;
21
21
use crate :: utils:: args:: ArgExt as _;
22
22
use crate :: utils:: chunks:: { upload_chunks, Chunk , ASSEMBLE_POLL_INTERVAL } ;
@@ -129,9 +129,10 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
129
129
130
130
let config = Config :: current ( ) ;
131
131
let ( org, project) = config. get_org_and_project ( matches) ?;
132
+ let base_url = config. get_base_url ( ) ?;
132
133
133
- let mut uploaded_paths = vec ! [ ] ;
134
- let mut errored_paths = vec ! [ ] ;
134
+ let mut uploaded_paths_and_ids = vec ! [ ] ;
135
+ let mut errored_paths_and_reasons = vec ! [ ] ;
135
136
for ( path, zip) in normalized_zips {
136
137
info ! ( "Uploading file: {}" , path. display( ) ) ;
137
138
let bytes = ByteView :: open ( zip. path ( ) ) ?;
@@ -143,41 +144,50 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
143
144
sha. as_deref ( ) ,
144
145
build_configuration,
145
146
) {
146
- Ok ( _ ) => {
147
+ Ok ( artifact_id ) => {
147
148
info ! ( "Successfully uploaded file: {}" , path. display( ) ) ;
148
- uploaded_paths . push ( path. to_path_buf ( ) ) ;
149
+ uploaded_paths_and_ids . push ( ( path. to_path_buf ( ) , artifact_id ) ) ;
149
150
}
150
151
Err ( e) => {
151
152
debug ! ( "Failed to upload file at path {}: {}" , path. display( ) , e) ;
152
- errored_paths . push ( path. to_path_buf ( ) ) ;
153
+ errored_paths_and_reasons . push ( ( path. to_path_buf ( ) , e ) ) ;
153
154
}
154
155
}
155
156
}
156
157
157
- if !errored_paths . is_empty ( ) {
158
+ if !errored_paths_and_reasons . is_empty ( ) {
158
159
warn ! (
159
160
"Failed to upload {} file{}:" ,
160
- errored_paths. len( ) ,
161
- if errored_paths. len( ) == 1 { "" } else { "s" }
161
+ errored_paths_and_reasons. len( ) ,
162
+ if errored_paths_and_reasons. len( ) == 1 {
163
+ ""
164
+ } else {
165
+ "s"
166
+ }
162
167
) ;
163
- for path in errored_paths {
164
- warn ! ( " - {}" , path. display( ) ) ;
168
+ for ( path, reason ) in errored_paths_and_reasons {
169
+ warn ! ( " - {} ({}) " , path. display( ) , reason ) ;
165
170
}
166
171
}
167
172
168
- println ! (
169
- "Successfully uploaded {} file{} to Sentry" ,
170
- uploaded_paths. len( ) ,
171
- if uploaded_paths. len( ) == 1 { "" } else { "s" }
172
- ) ;
173
- if uploaded_paths. len ( ) < 3 {
174
- for path in & uploaded_paths {
175
- println ! ( " - {}" , path. display( ) ) ;
176
- }
177
- }
178
-
179
- if uploaded_paths. is_empty ( ) {
173
+ if uploaded_paths_and_ids. is_empty ( ) {
180
174
bail ! ( "Failed to upload any files" ) ;
175
+ } else {
176
+ println ! (
177
+ "Successfully uploaded {} file{} to Sentry" ,
178
+ uploaded_paths_and_ids. len( ) ,
179
+ if uploaded_paths_and_ids. len( ) == 1 {
180
+ ""
181
+ } else {
182
+ "s"
183
+ }
184
+ ) ;
185
+ if uploaded_paths_and_ids. len ( ) < 3 {
186
+ for ( path, artifact_id) in & uploaded_paths_and_ids {
187
+ let url = format ! ( "{base_url}/{org}/preprod/{project}/{artifact_id}" ) ;
188
+ println ! ( " - {} {url}" , path. display( ) ) ;
189
+ }
190
+ }
181
191
}
182
192
Ok ( ( ) )
183
193
}
@@ -337,14 +347,15 @@ fn normalize_directory(path: &Path) -> Result<TempFile> {
337
347
Ok ( temp_file)
338
348
}
339
349
350
+ /// Returns artifact id if upload was successful.
340
351
fn upload_file (
341
352
api : & AuthenticatedApi ,
342
353
bytes : & [ u8 ] ,
343
354
org : & str ,
344
355
project : & str ,
345
356
sha : Option < & str > ,
346
357
build_configuration : Option < & str > ,
347
- ) -> Result < ( ) > {
358
+ ) -> Result < String > {
348
359
const SELF_HOSTED_ERROR_HINT : & str = "If you are using a self-hosted Sentry server, \
349
360
update to the latest version of Sentry to use the mobile-app upload command.";
350
361
@@ -400,7 +411,7 @@ fn upload_file(
400
411
println ! ( "Nothing to upload, all files are on the server" ) ;
401
412
}
402
413
403
- poll_assemble (
414
+ let response = poll_assemble (
404
415
api,
405
416
checksum,
406
417
& checksums,
@@ -409,7 +420,10 @@ fn upload_file(
409
420
sha,
410
421
build_configuration,
411
422
) ?;
412
- Ok ( ( ) )
423
+
424
+ response
425
+ . artifact_id
426
+ . ok_or ( anyhow ! ( "Missing artifactId in response" ) )
413
427
}
414
428
415
429
fn poll_assemble (
@@ -420,7 +434,7 @@ fn poll_assemble(
420
434
project : & str ,
421
435
sha : Option < & str > ,
422
436
build_configuration : Option < & str > ,
423
- ) -> Result < ( ) > {
437
+ ) -> Result < AssembleMobileAppResponse > {
424
438
debug ! ( "Polling assemble for checksum: {}" , checksum) ;
425
439
426
440
let progress_style = ProgressStyle :: default_spinner ( ) . template ( "{spinner} Processing files..." ) ;
@@ -453,7 +467,7 @@ fn poll_assemble(
453
467
info ! ( "File processing complete" ) ;
454
468
}
455
469
456
- Ok ( ( ) )
470
+ Ok ( response )
457
471
}
458
472
459
473
#[ cfg( not( windows) ) ]
0 commit comments