@@ -337,3 +337,157 @@ func TestMutateModuleConfig(t *testing.T) {
337337 test .That (t , modules [0 ]["version" ], test .ShouldEqual , expectedVersion )
338338 })
339339}
340+
341+ func TestReloadWithMissingBuildSection (t * testing.T ) {
342+ logger := logging .NewTestLogger (t )
343+
344+ t .Run ("reload-local with missing build section" , func (t * testing.T ) {
345+ // Create manifest without build section (nil value deletes the key)
346+ manifestPath := createTestManifest (t , "" , map [string ]any {
347+ "build" : nil ,
348+ })
349+
350+ confStruct , err := structpb .NewStruct (map [string ]any {
351+ "modules" : []any {},
352+ })
353+ test .That (t , err , test .ShouldBeNil )
354+
355+ userInfo , err := structpb .NewStruct (map [string ]any {
356+ "version" : "0.90.0" ,
357+ "platform" : "linux/amd64" ,
358+ })
359+ test .That (t , err , test .ShouldBeNil )
360+
361+ cCtx , vc , _ , _ := setup (
362+ mockFullAppServiceClient (confStruct , userInfo , nil ),
363+ nil ,
364+ & inject.BuildServiceClient {},
365+ map [string ]any {
366+ moduleFlagPath : manifestPath ,
367+ generalFlagPartID : "part-123" ,
368+ moduleFlagLocal : true ,
369+ generalFlagNoProgress : true ,
370+ },
371+ "token" ,
372+ )
373+
374+ // Test reload-local (cloudBuild=false)
375+ err = reloadModuleActionInner (cCtx , vc , parseStructFromCtx [reloadModuleArgs ](cCtx ), logger , false )
376+ test .That (t , err , test .ShouldNotBeNil )
377+ test .That (t , err .Error (), test .ShouldContainSubstring , "cannot have an empty build step" )
378+ test .That (t , err .Error (), test .ShouldContainSubstring , "required for 'reload' and 'reload-local' commands" )
379+ })
380+
381+ t .Run ("reload (cloud) with missing build section" , func (t * testing.T ) {
382+ // Create manifest without build section (nil value deletes the key)
383+ manifestPath := createTestManifest (t , "" , map [string ]any {
384+ "build" : nil ,
385+ })
386+
387+ confStruct , err := structpb .NewStruct (map [string ]any {
388+ "modules" : []any {},
389+ })
390+ test .That (t , err , test .ShouldBeNil )
391+
392+ userInfo , err := structpb .NewStruct (map [string ]any {
393+ "version" : "0.90.0" ,
394+ "platform" : "linux/amd64" ,
395+ })
396+ test .That (t , err , test .ShouldBeNil )
397+
398+ cCtx , vc , _ , _ := setup (
399+ mockFullAppServiceClient (confStruct , userInfo , nil ),
400+ nil ,
401+ & inject.BuildServiceClient {},
402+ map [string ]any {
403+ moduleFlagPath : manifestPath ,
404+ generalFlagPartID : "part-123" ,
405+ generalFlagNoProgress : true ,
406+ },
407+ "token" ,
408+ )
409+
410+ // Test reload with cloud build (cloudBuild=true)
411+ err = reloadModuleActionInner (cCtx , vc , parseStructFromCtx [reloadModuleArgs ](cCtx ), logger , true )
412+ test .That (t , err , test .ShouldNotBeNil )
413+ test .That (t , err .Error (), test .ShouldContainSubstring , "cannot have an empty build step" )
414+ test .That (t , err .Error (), test .ShouldContainSubstring , "required for 'reload' and 'reload-local' commands" )
415+ })
416+
417+ t .Run ("reload-local with empty build command" , func (t * testing.T ) {
418+ // Create manifest with build section but empty build command
419+ manifestPath := createTestManifest (t , "" , map [string ]any {
420+ "build" : map [string ]any {
421+ "path" : "module" ,
422+ "arch" : []any {"linux/amd64" },
423+ // "build" field is missing or empty
424+ },
425+ })
426+
427+ confStruct , err := structpb .NewStruct (map [string ]any {
428+ "modules" : []any {},
429+ })
430+ test .That (t , err , test .ShouldBeNil )
431+
432+ userInfo , err := structpb .NewStruct (map [string ]any {
433+ "version" : "0.90.0" ,
434+ "platform" : "linux/amd64" ,
435+ })
436+ test .That (t , err , test .ShouldBeNil )
437+
438+ cCtx , vc , _ , _ := setup (
439+ mockFullAppServiceClient (confStruct , userInfo , nil ),
440+ nil ,
441+ & inject.BuildServiceClient {},
442+ map [string ]any {
443+ moduleFlagPath : manifestPath ,
444+ generalFlagPartID : "part-123" ,
445+ moduleFlagLocal : true ,
446+ generalFlagNoProgress : true ,
447+ },
448+ "token" ,
449+ )
450+
451+ err = reloadModuleActionInner (cCtx , vc , parseStructFromCtx [reloadModuleArgs ](cCtx ), logger , false )
452+ test .That (t , err , test .ShouldNotBeNil )
453+ test .That (t , err .Error (), test .ShouldContainSubstring , "cannot have an empty build step" )
454+ })
455+
456+ t .Run ("reload-local with --no-build flag still requires manifest" , func (t * testing.T ) {
457+ // Create manifest without build section (nil value deletes the key)
458+ manifestPath := createTestManifest (t , "" , map [string ]any {
459+ "build" : nil ,
460+ })
461+
462+ confStruct , err := structpb .NewStruct (map [string ]any {
463+ "modules" : []any {},
464+ })
465+ test .That (t , err , test .ShouldBeNil )
466+
467+ userInfo , err := structpb .NewStruct (map [string ]any {
468+ "version" : "0.90.0" ,
469+ "platform" : "linux/amd64" ,
470+ })
471+ test .That (t , err , test .ShouldBeNil )
472+
473+ cCtx , vc , _ , _ := setup (
474+ mockFullAppServiceClient (confStruct , userInfo , nil ),
475+ nil ,
476+ & inject.BuildServiceClient {},
477+ map [string ]any {
478+ moduleFlagPath : manifestPath ,
479+ generalFlagPartID : "part-123" ,
480+ moduleBuildFlagNoBuild : true , // --no-build flag
481+ moduleFlagLocal : true ,
482+ generalFlagNoProgress : true ,
483+ },
484+ "token" ,
485+ )
486+
487+ // Even with --no-build flag, manifest with build section is still required
488+ // because it needs to know where to find the already-built artifact
489+ err = reloadModuleActionInner (cCtx , vc , parseStructFromCtx [reloadModuleArgs ](cCtx ), logger , false )
490+ test .That (t , err , test .ShouldNotBeNil )
491+ test .That (t , err .Error (), test .ShouldContainSubstring , "manifest required for reload" )
492+ })
493+ }
0 commit comments