@@ -34,6 +34,31 @@ export interface PushOptions {
3434
3535const DESTRUCTIVE_CHANGE_PROMPT_THRESHOLD = 25 ;
3636
37+ /** Firestore/YAML artifact changes only (not asset uploads via studio function). */
38+ function yamlArtifactChangeTotal ( summary : PushSummary ) : number {
39+ const k = summary . byKind ;
40+ return (
41+ k . screens . created +
42+ k . screens . updated +
43+ k . screens . deleted +
44+ k . widgets . created +
45+ k . widgets . updated +
46+ k . widgets . deleted +
47+ k . scripts . created +
48+ k . scripts . updated +
49+ k . scripts . deleted +
50+ k . actions . created +
51+ k . actions . updated +
52+ k . actions . deleted +
53+ k . translations . created +
54+ k . translations . updated +
55+ k . translations . deleted +
56+ k . theme . created +
57+ k . theme . updated +
58+ k . theme . deleted
59+ ) ;
60+ }
61+
3762function printPushSummary ( summary : PushSummary , options : { verbose ?: boolean ; isNoop ?: boolean } ) {
3863 const { appName, environment, counts } = summary ;
3964 const totalChanges = counts . created + counts . updated + counts . deleted ;
@@ -60,6 +85,7 @@ function printPushSummary(summary: PushSummary, options: { verbose?: boolean; is
6085 [ 'actions' , summary . byKind . actions ] ,
6186 [ 'translations' , summary . byKind . translations ] ,
6287 [ 'theme' , summary . byKind . theme ] ,
88+ [ 'assets' , summary . byKind . assets ] ,
6389 ] ;
6490
6591 for ( const [ kind , c ] of entries ) {
@@ -307,9 +333,12 @@ export async function pushCommand(options: PushOptions = {}): Promise<void> {
307333 } ) ;
308334
309335 const summary = plan . summary ;
310- const changedCount = summary . counts . created + summary . counts . updated + summary . counts . deleted ;
336+ const yamlChangeTotal = yamlArtifactChangeTotal ( summary ) ;
337+ const assetsToUpload = plan . diff . assets . new
338+ . map ( ( item ) => ( item as { fileName ?: string } ) . fileName )
339+ . filter ( ( fn ) : fn is string => typeof fn === 'string' && fn . length > 0 ) ;
311340
312- if ( changedCount === 0 ) {
341+ if ( yamlChangeTotal === 0 && assetsToUpload . length === 0 ) {
313342 ui . info ( 'Up to date. Nothing to push.' ) ;
314343 return ;
315344 }
@@ -352,9 +381,7 @@ export async function pushCommand(options: PushOptions = {}): Promise<void> {
352381 let confirmed = options . yes ?? false ;
353382 const isInteractive = Boolean ( process . stdout . isTTY && process . stdin . isTTY ) ;
354383 const hasDeletes = summary . counts . deleted > 0 ;
355- const largeChangeSet =
356- summary . counts . created + summary . counts . updated + summary . counts . deleted >=
357- DESTRUCTIVE_CHANGE_PROMPT_THRESHOLD ;
384+ const largeChangeSet = yamlChangeTotal >= DESTRUCTIVE_CHANGE_PROMPT_THRESHOLD ;
358385
359386 if ( ! confirmed ) {
360387 if ( ! isInteractive ) {
@@ -365,12 +392,28 @@ export async function pushCommand(options: PushOptions = {}): Promise<void> {
365392 return ;
366393 }
367394
395+ const yamlCreatedOrUpdated =
396+ summary . byKind . screens . created +
397+ summary . byKind . screens . updated +
398+ summary . byKind . widgets . created +
399+ summary . byKind . widgets . updated +
400+ summary . byKind . scripts . created +
401+ summary . byKind . scripts . updated +
402+ summary . byKind . actions . created +
403+ summary . byKind . actions . updated +
404+ summary . byKind . translations . created +
405+ summary . byKind . translations . updated +
406+ summary . byKind . theme . created +
407+ summary . byKind . theme . updated ;
408+
368409 const headline =
369410 hasDeletes || largeChangeSet
370- ? `This will delete ${ summary . counts . deleted } item(s) and apply ${
371- summary . counts . created + summary . counts . updated
372- } other change(s). Continue? [y/N]`
373- : 'Proceed with push?' ;
411+ ? `This will delete ${ summary . counts . deleted } item(s) and apply ${ yamlCreatedOrUpdated } other change(s)${
412+ assetsToUpload . length > 0 ? `, and upload ${ assetsToUpload . length } asset(s)` : ''
413+ } . Continue? [y/N]`
414+ : `Proceed with push${
415+ assetsToUpload . length > 0 ? ` and upload ${ assetsToUpload . length } asset(s)` : ''
416+ } ?`;
374417
375418 const { proceed } = await prompts ( {
376419 type : 'confirm' ,
@@ -391,9 +434,17 @@ export async function pushCommand(options: PushOptions = {}): Promise<void> {
391434 }
392435
393436 try {
394- await withSpinner ( 'Pushing changes to cloud...' , ( ) =>
395- submitCliPush ( appId , idToken , pushPayload , firestoreOptions )
396- ) ;
437+ if ( yamlChangeTotal > 0 || assetsToUpload . length > 0 ) {
438+ const { assetsUploaded } = await withSpinner ( 'Pushing changes to cloud...' , ( ) =>
439+ submitCliPush ( appId , idToken , pushPayload , firestoreOptions , {
440+ projectRoot : root ,
441+ ...( assetsToUpload . length > 0 && { assetFileNames : assetsToUpload } ) ,
442+ } )
443+ ) ;
444+ if ( assetsUploaded > 0 ) {
445+ ui . success ( `Uploaded ${ assetsUploaded } asset(s) and updated .env.config.` ) ;
446+ }
447+ }
397448
398449 if ( manifestNeedsRefresh && bundle ) {
399450 // Only refresh manifest when artifact changes can affect its contents.
0 commit comments