@@ -16,7 +16,7 @@ use symbolic::common::ByteView;
1616use zip:: write:: SimpleFileOptions ;
1717use zip:: { DateTime , ZipWriter } ;
1818
19- use crate :: api:: { Api , AuthenticatedApi , ChunkUploadCapability } ;
19+ use crate :: api:: { Api , AssembleMobileAppResponse , AuthenticatedApi , ChunkUploadCapability } ;
2020use crate :: config:: Config ;
2121use crate :: utils:: args:: ArgExt as _;
2222use crate :: utils:: chunks:: { upload_chunks, Chunk , ASSEMBLE_POLL_INTERVAL } ;
@@ -130,8 +130,8 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
130130 let config = Config :: current ( ) ;
131131 let ( org, project) = config. get_org_and_project ( matches) ?;
132132
133- let mut uploaded_paths = vec ! [ ] ;
134- let mut errored_paths = vec ! [ ] ;
133+ let mut uploaded_paths_and_ids = vec ! [ ] ;
134+ let mut errored_paths_and_reasons = vec ! [ ] ;
135135 for ( path, zip) in normalized_zips {
136136 info ! ( "Uploading file: {}" , path. display( ) ) ;
137137 let bytes = ByteView :: open ( zip. path ( ) ) ?;
@@ -143,41 +143,55 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
143143 sha. as_deref ( ) ,
144144 build_configuration,
145145 ) {
146- Ok ( _ ) => {
146+ Ok ( artifact_id ) => {
147147 info ! ( "Successfully uploaded file: {}" , path. display( ) ) ;
148- uploaded_paths . push ( path. to_path_buf ( ) ) ;
148+ uploaded_paths_and_ids . push ( ( path. to_path_buf ( ) , artifact_id ) ) ;
149149 }
150150 Err ( e) => {
151151 debug ! ( "Failed to upload file at path {}: {}" , path. display( ) , e) ;
152- errored_paths . push ( path. to_path_buf ( ) ) ;
152+ errored_paths_and_reasons . push ( ( path. to_path_buf ( ) , e ) ) ;
153153 }
154154 }
155155 }
156156
157- if !errored_paths . is_empty ( ) {
157+ if !errored_paths_and_reasons . is_empty ( ) {
158158 warn ! (
159159 "Failed to upload {} file{}:" ,
160- errored_paths. len( ) ,
161- if errored_paths. len( ) == 1 { "" } else { "s" }
160+ errored_paths_and_reasons. len( ) ,
161+ if errored_paths_and_reasons. len( ) == 1 {
162+ ""
163+ } else {
164+ "s"
165+ }
162166 ) ;
163- for path in errored_paths {
164- warn ! ( " - {}" , path. display( ) ) ;
167+ for ( path, reason ) in errored_paths_and_reasons {
168+ warn ! ( " - {} ({}) " , path. display( ) , reason ) ;
165169 }
166170 }
167171
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 ( ) {
172+ if uploaded_paths_and_ids. is_empty ( ) {
180173 bail ! ( "Failed to upload any files" ) ;
174+ } else {
175+ println ! (
176+ "Successfully uploaded {} file{} to Sentry" ,
177+ uploaded_paths_and_ids. len( ) ,
178+ if uploaded_paths_and_ids. len( ) == 1 {
179+ ""
180+ } else {
181+ "s"
182+ }
183+ ) ;
184+ if uploaded_paths_and_ids. len ( ) < 3 {
185+ for ( path, artifact_id) in & uploaded_paths_and_ids {
186+ let url = format ! (
187+ "{}/preprod/{}/{}" ,
188+ config. get_base_url( ) . unwrap_or( "" ) ,
189+ project,
190+ artifact_id
191+ ) ;
192+ println ! ( " - {} {}" , path. display( ) , url) ;
193+ }
194+ }
181195 }
182196 Ok ( ( ) )
183197}
@@ -337,14 +351,15 @@ fn normalize_directory(path: &Path) -> Result<TempFile> {
337351 Ok ( temp_file)
338352}
339353
354+ /// Returns artifact id if upload was successful.
340355fn upload_file (
341356 api : & AuthenticatedApi ,
342357 bytes : & [ u8 ] ,
343358 org : & str ,
344359 project : & str ,
345360 sha : Option < & str > ,
346361 build_configuration : Option < & str > ,
347- ) -> Result < ( ) > {
362+ ) -> Result < String > {
348363 const SELF_HOSTED_ERROR_HINT : & str = "If you are using a self-hosted Sentry server, \
349364 update to the latest version of Sentry to use the mobile-app upload command.";
350365
@@ -400,7 +415,7 @@ fn upload_file(
400415 println ! ( "Nothing to upload, all files are on the server" ) ;
401416 }
402417
403- poll_assemble (
418+ let response = poll_assemble (
404419 api,
405420 checksum,
406421 & checksums,
@@ -409,7 +424,10 @@ fn upload_file(
409424 sha,
410425 build_configuration,
411426 ) ?;
412- Ok ( ( ) )
427+
428+ response
429+ . artifact_id
430+ . ok_or ( anyhow ! ( "Missing artifactId in response" ) )
413431}
414432
415433fn poll_assemble (
@@ -420,7 +438,7 @@ fn poll_assemble(
420438 project : & str ,
421439 sha : Option < & str > ,
422440 build_configuration : Option < & str > ,
423- ) -> Result < ( ) > {
441+ ) -> Result < AssembleMobileAppResponse > {
424442 debug ! ( "Polling assemble for checksum: {}" , checksum) ;
425443
426444 let progress_style = ProgressStyle :: default_spinner ( ) . template ( "{spinner} Processing files..." ) ;
@@ -453,7 +471,7 @@ fn poll_assemble(
453471 info ! ( "File processing complete" ) ;
454472 }
455473
456- Ok ( ( ) )
474+ Ok ( response )
457475}
458476
459477#[ cfg( not( windows) ) ]
0 commit comments