@@ -93,11 +93,25 @@ export function createUploader(
9393 onProgress ( { phase : 'processing' , current, total : files . length } )
9494 ) ;
9595
96- // Check which files need uploading
97- const { toUpload, existing } = await checkExistingFiles (
96+ // Create build first to get buildId for SHA checking
97+ const buildInfo = {
98+ name : buildName || `Upload ${ new Date ( ) . toISOString ( ) } ` ,
99+ branch : branch || ( await getDefaultBranch ( ) ) || 'main' ,
100+ commitSha : commit ,
101+ commitMessage : message ,
102+ environment,
103+ threshold,
104+ } ;
105+
106+ const build = await api . createBuild ( buildInfo ) ;
107+ const buildId = build . id ;
108+
109+ // Check which files need uploading (now with buildId)
110+ const { toUpload, existing, screenshots } = await checkExistingFiles (
98111 fileMetadata ,
99112 api ,
100- signal
113+ signal ,
114+ buildId
101115 ) ;
102116
103117 onProgress ( {
@@ -107,18 +121,13 @@ export function createUploader(
107121 total : files . length ,
108122 } ) ;
109123
110- // Create build and upload files
124+ // Upload remaining files
111125 const result = await uploadFiles ( {
112126 toUpload,
113127 existing,
114- buildInfo : {
115- name : buildName || `Upload ${ new Date ( ) . toISOString ( ) } ` ,
116- branch : branch || ( await getDefaultBranch ( ) ) || 'main' ,
117- commitSha : commit ,
118- commitMessage : message ,
119- environment,
120- threshold,
121- } ,
128+ screenshots,
129+ buildId,
130+ buildInfo,
122131 api,
123132 signal,
124133 batchSize : batchSize ,
@@ -277,9 +286,10 @@ async function processFiles(files, signal, onProgress) {
277286/**
278287 * Check which files already exist on the server
279288 */
280- async function checkExistingFiles ( fileMetadata , api , signal ) {
289+ async function checkExistingFiles ( fileMetadata , api , signal , buildId ) {
281290 const allShas = fileMetadata . map ( f => f . sha256 ) ;
282291 const existingShas = new Set ( ) ;
292+ const allScreenshots = [ ] ;
283293
284294 // Check in batches
285295 for ( let i = 0 ; i < allShas . length ; i += DEFAULT_SHA_CHECK_BATCH_SIZE ) {
@@ -291,11 +301,12 @@ async function checkExistingFiles(fileMetadata, api, signal) {
291301 const res = await api . request ( '/api/sdk/check-shas' , {
292302 method : 'POST' ,
293303 headers : { 'Content-Type' : 'application/json' } ,
294- body : JSON . stringify ( { shas : batch } ) ,
304+ body : JSON . stringify ( { shas : batch , buildId } ) ,
295305 signal,
296306 } ) ;
297- const { existing = [ ] } = res || { } ;
307+ const { existing = [ ] , screenshots = [ ] } = res || { } ;
298308 existing . forEach ( sha => existingShas . add ( sha ) ) ;
309+ allScreenshots . push ( ...screenshots ) ;
299310 } catch ( error ) {
300311 // Continue without deduplication on error
301312 console . debug (
@@ -308,6 +319,7 @@ async function checkExistingFiles(fileMetadata, api, signal) {
308319 return {
309320 toUpload : fileMetadata . filter ( f => ! existingShas . has ( f . sha256 ) ) ,
310321 existing : fileMetadata . filter ( f => existingShas . has ( f . sha256 ) ) ,
322+ screenshots : allScreenshots ,
311323 } ;
312324}
313325
@@ -316,53 +328,29 @@ async function checkExistingFiles(fileMetadata, api, signal) {
316328 */
317329async function uploadFiles ( {
318330 toUpload,
319- existing,
320- buildInfo,
331+ buildId,
321332 api,
322333 signal,
323334 batchSize,
324335 onProgress,
325336} ) {
326- let buildId = null ;
327337 let result = null ;
328338
329- // If all files exist, just create a build
339+ // If all files exist, screenshot records were already created during SHA check
330340 if ( toUpload . length === 0 ) {
331- return createBuildWithExisting ( { existing , buildInfo , api , signal } ) ;
341+ return { buildId , url : null } ; // Build was already created
332342 }
333343
334344 // Upload in batches
335345 for ( let i = 0 ; i < toUpload . length ; i += batchSize ) {
336346 if ( signal . aborted ) throw new UploadError ( 'Operation cancelled' ) ;
337347
338348 const batch = toUpload . slice ( i , i + batchSize ) ;
339- const isFirstBatch = i === 0 ;
340349
341350 const form = new FormData ( ) ;
342351
343- if ( isFirstBatch ) {
344- // First batch creates the build
345- form . append ( 'build_name' , buildInfo . name ) ;
346- form . append ( 'branch' , buildInfo . branch ) ;
347- form . append ( 'environment' , buildInfo . environment ) ;
348-
349- if ( buildInfo . commitSha ) form . append ( 'commit_sha' , buildInfo . commitSha ) ;
350- if ( buildInfo . commitMessage )
351- form . append ( 'commit_message' , buildInfo . commitMessage ) ;
352- if ( buildInfo . threshold !== undefined )
353- form . append ( 'threshold' , buildInfo . threshold . toString ( ) ) ;
354-
355- // Include existing SHAs
356- if ( existing . length > 0 ) {
357- form . append (
358- 'existing_shas' ,
359- JSON . stringify ( existing . map ( f => f . sha256 ) )
360- ) ;
361- }
362- } else {
363- // Subsequent batches add to existing build
364- form . append ( 'build_id' , buildId ) ;
365- }
352+ // All batches add to existing build (build was created earlier)
353+ form . append ( 'build_id' , buildId ) ;
366354
367355 // Add files
368356 for ( const file of batch ) {
@@ -383,52 +371,17 @@ async function uploadFiles({
383371 } ) ;
384372 }
385373
386- if ( isFirstBatch && result . build ?. id ) {
387- buildId = result . build . id ;
388- }
389-
390374 onProgress ( i + batch . length ) ;
391375 }
392376
393377 return {
394- buildId : result . build ?. id || buildId ,
395- url : result . build ?. url || result . url ,
378+ buildId,
379+ url : result ? .build ?. url || result ? .url ,
396380 } ;
397381}
398382
399- /**
400- * Create a build with only existing files
401- */
402- async function createBuildWithExisting ( { existing, buildInfo, api, signal } ) {
403- const form = new FormData ( ) ;
404-
405- form . append ( 'build_name' , buildInfo . name ) ;
406- form . append ( 'branch' , buildInfo . branch ) ;
407- form . append ( 'environment' , buildInfo . environment ) ;
408- form . append ( 'existing_shas' , JSON . stringify ( existing . map ( f => f . sha256 ) ) ) ;
409-
410- if ( buildInfo . commitSha ) form . append ( 'commit_sha' , buildInfo . commitSha ) ;
411- if ( buildInfo . commitMessage )
412- form . append ( 'commit_message' , buildInfo . commitMessage ) ;
413- if ( buildInfo . threshold !== undefined )
414- form . append ( 'threshold' , buildInfo . threshold . toString ( ) ) ;
415-
416- let result ;
417- try {
418- result = await api . request ( '/api/sdk/upload' , {
419- method : 'POST' ,
420- body : form ,
421- signal,
422- headers : { } ,
423- } ) ;
424- } catch ( err ) {
425- throw new UploadError ( `Failed to create build: ${ err . message } ` ) ;
426- }
427- return {
428- buildId : result . build ?. id ,
429- url : result . build ?. url || result . url ,
430- } ;
431- }
383+ // createBuildWithExisting function removed - no longer needed since
384+ // builds are created first and /check-shas automatically creates screenshot records
432385
433386/**
434387 * Uploader class for handling screenshot uploads
0 commit comments