@@ -47,13 +47,20 @@ type batchExecuteFlags struct {
4747 workspace string
4848 cleanArchives bool
4949 skipErrors bool
50+
51+ // EXPERIMENTAL
52+ textOnly bool
5053}
5154
5255func newBatchExecuteFlags (flagSet * flag.FlagSet , cacheDir , tempDir string ) * batchExecuteFlags {
5356 caf := & batchExecuteFlags {
5457 api : api .NewFlags (flagSet ),
5558 }
5659
60+ flagSet .BoolVar (
61+ & caf .textOnly , "text-only" , false ,
62+ "INTERNAL USE ONLY. EXPERIMENTAL. Switches off the TUI to only print JSON lines." ,
63+ )
5764 flagSet .BoolVar (
5865 & caf .allowUnsupported , "allow-unsupported" , false ,
5966 "Allow unsupported code hosts." ,
@@ -415,6 +422,219 @@ func executeBatchSpec(ctx context.Context, opts executeBatchSpecOpts) error {
415422 return nil
416423}
417424
425+ // TODO: This is a straight up copy of the other function
426+ func textOnlyExecuteBatchSpec (ctx context.Context , opts executeBatchSpecOpts ) error {
427+ svc := service .New (& service.Opts {
428+ AllowUnsupported : opts .flags .allowUnsupported ,
429+ AllowIgnored : opts .flags .allowIgnored ,
430+ Client : opts .client ,
431+ })
432+
433+ if err := svc .DetermineFeatureFlags (ctx ); err != nil {
434+ return err
435+ }
436+
437+ if err := checkExecutable ("git" , "version" ); err != nil {
438+ return err
439+ }
440+
441+ if err := checkExecutable ("docker" , "version" ); err != nil {
442+ return err
443+ }
444+
445+ // Parse flags and build up our service and executor options.
446+ logOperationStart ("PARSING_BATCH_SPEC" , "" )
447+ batchSpec , rawSpec , err := batchParseSpec (opts .out , & opts .flags .file , svc )
448+ if err != nil {
449+ return err
450+ }
451+ logOperationSuccess ("PARSING_BATCH_SPEC" , "" )
452+
453+ logOperationStart ("RESOLVING_NAMESPACE" , "" )
454+ namespace , err := svc .ResolveNamespace (ctx , opts .flags .namespace )
455+ if err != nil {
456+ return err
457+ }
458+ logOperationSuccess ("RESOLVING_NAMESPACE" , fmt .Sprintf ("Namespace: %s" , namespace ))
459+
460+ logOperationStart ("PREPARING_DOCKER_IMAGES" , "" )
461+ err = svc .SetDockerImages (ctx , batchSpec , func (perc float64 ) {
462+ logOperationProgress ("PREPARING_DOCKER_IMAGES" , fmt .Sprintf ("%d%% done" , int (perc * 100 )))
463+ })
464+ if err != nil {
465+ return err
466+ }
467+ logOperationSuccess ("PREPARING_DOCKER_IMAGES" , "" )
468+
469+ logOperationStart ("DETERMINING_WORKSPACE_TYPE" , "" )
470+ workspaceCreator := workspace .NewCreator (ctx , opts .flags .workspace , opts .flags .cacheDir , opts .flags .tempDir , batchSpec .Steps )
471+ if workspaceCreator .Type () == workspace .CreatorTypeVolume {
472+ _ , err = svc .EnsureImage (ctx , workspace .DockerVolumeWorkspaceImage )
473+ if err != nil {
474+ return err
475+ }
476+ }
477+ switch workspaceCreator .Type () {
478+ case workspace .CreatorTypeVolume :
479+ logOperationSuccess ("DETERMINING_WORKSPACE_TYPE" , "VOLUME" )
480+ case workspace .CreatorTypeBind :
481+ logOperationSuccess ("DETERMINING_WORKSPACE_TYPE" , "BIND" )
482+ }
483+
484+ logOperationStart ("RESOLVING_REPOSITORIES" , "" )
485+ repos , err := svc .ResolveRepositories (ctx , batchSpec )
486+ if err != nil {
487+ if repoSet , ok := err .(batches.UnsupportedRepoSet ); ok {
488+ logOperationSuccess ("RESOLVING_REPOSITORIES" , fmt .Sprintf ("%d unsupported repositories" , len (repoSet )))
489+ } else if repoSet , ok := err .(batches.IgnoredRepoSet ); ok {
490+ logOperationSuccess ("RESOLVING_REPOSITORIES" , fmt .Sprintf ("%d ignored repositories" , len (repoSet )))
491+ } else {
492+ return errors .Wrap (err , "resolving repositories" )
493+ }
494+ } else {
495+ logOperationSuccess ("RESOLVING_REPOSITORIES" , fmt .Sprintf ("Resolved %d repositories" , len (repos )))
496+ }
497+
498+ logOperationStart ("DETERMINING_WORKSPACES" , "" )
499+ tasks , err := svc .BuildTasks (ctx , repos , batchSpec )
500+ if err != nil {
501+ return err
502+ }
503+ logOperationSuccess ("DETERMINING_WORKSPACES" , fmt .Sprintf ("Found %d workspaces with steps to execute" , len (tasks )))
504+
505+ // EXECUTION OF TASKS
506+ coord := svc .NewCoordinator (executor.NewCoordinatorOpts {
507+ Creator : workspaceCreator ,
508+ CacheDir : opts .flags .cacheDir ,
509+ ClearCache : opts .flags .clearCache ,
510+ SkipErrors : opts .flags .skipErrors ,
511+ CleanArchives : opts .flags .cleanArchives ,
512+ Parallelism : opts .flags .parallelism ,
513+ Timeout : opts .flags .timeout ,
514+ KeepLogs : opts .flags .keepLogs ,
515+ TempDir : opts .flags .tempDir ,
516+ })
517+
518+ logOperationStart ("CHECKING_CACHE" , "" )
519+ uncachedTasks , cachedSpecs , err := coord .CheckCache (ctx , tasks )
520+ if err != nil {
521+ return err
522+ }
523+ var specsFoundMessage string
524+ if len (cachedSpecs ) == 1 {
525+ specsFoundMessage = "Found 1 cached changeset spec"
526+ } else {
527+ specsFoundMessage = fmt .Sprintf ("Found %d cached changeset specs" , len (cachedSpecs ))
528+ }
529+ switch len (uncachedTasks ) {
530+ case 0 :
531+ logOperationSuccess ("CHECKING_CACHE" , fmt .Sprintf ("%s; no tasks need to be executed" , specsFoundMessage ))
532+ case 1 :
533+ logOperationSuccess ("CHECKING_CACHE" , fmt .Sprintf ("%s; %d task needs to be executed" , specsFoundMessage , len (uncachedTasks )))
534+ default :
535+ logOperationSuccess ("CHECKING_CACHE" , fmt .Sprintf ("%s; %d tasks need to be executed" , specsFoundMessage , len (uncachedTasks )))
536+ }
537+
538+ logOperationStart ("EXECUTING_TASKS" , "" )
539+ freshSpecs , logFiles , err := coord .Execute (ctx , uncachedTasks , batchSpec , func (statuses []* executor.TaskStatus ) {
540+
541+ finishedExecution := 0
542+ finishedBuilding := 0
543+ currentlyRunning := 0
544+ errored := 0
545+
546+ for _ , ts := range statuses {
547+ if ts .FinishedExecution () {
548+ if ts .Err != nil {
549+ errored += 1
550+ }
551+
552+ finishedExecution += 1
553+ }
554+
555+ if ts .FinishedBuildingSpecs () {
556+ finishedBuilding += 1
557+ }
558+
559+ if ts .IsRunning () {
560+ currentlyRunning += 1
561+ }
562+ }
563+
564+ logOperationProgress ("EXECUTING_TASKS" , fmt .Sprintf ("running: %d, executed: %d, built: %d, errored: %d" , currentlyRunning , finishedExecution , finishedBuilding , errored ))
565+ })
566+
567+ if err != nil && ! opts .flags .skipErrors {
568+ return err
569+ }
570+ if err != nil && opts .flags .skipErrors {
571+ logOperationFailure ("EXECUTING_TASKS" , fmt .Sprintf ("Error: %s. Skipping errors because -skip-errors was used." , err ))
572+ } else {
573+ logOperationSuccess ("EXECUTING_TASKS" , "" )
574+ }
575+
576+ if len (logFiles ) > 0 && opts .flags .keepLogs {
577+ for _ , file := range logFiles {
578+ logOperationSuccess ("LOG_FILE_KEPT" , file )
579+ }
580+ }
581+
582+ specs := append (cachedSpecs , freshSpecs ... )
583+
584+ err = svc .ValidateChangesetSpecs (repos , specs )
585+ if err != nil {
586+ return err
587+ }
588+
589+ ids := make ([]graphql.ChangesetSpecID , len (specs ))
590+
591+ if len (specs ) > 0 {
592+ var label string
593+ if len (specs ) == 1 {
594+ label = "Sending changeset spec"
595+ } else {
596+ label = fmt .Sprintf ("Sending %d changeset specs" , len (specs ))
597+ }
598+
599+ logOperationStart ("UPLOADING_CHANGESET_SPECS" , label )
600+
601+ for i , spec := range specs {
602+ id , err := svc .CreateChangesetSpec (ctx , spec )
603+ if err != nil {
604+ return err
605+ }
606+ ids [i ] = id
607+ logOperationProgress ("UPLOADING_CHANGESET_SPECS" , fmt .Sprintf ("Uploaded %d out of %d" , i + 1 , len (specs )))
608+
609+ }
610+ logOperationSuccess ("UPLOADING_CHANGESET_SPECS" , "" )
611+ } else {
612+ if len (repos ) == 0 {
613+ fmt .Println ("No changeset specs created" )
614+ }
615+ }
616+
617+ logOperationStart ("CREATING_BATCH_SPEC" , "" )
618+ id , url , err := svc .CreateBatchSpec (ctx , namespace , rawSpec , ids )
619+ if err != nil {
620+ return prettyPrintBatchUnlicensedError (opts .out , err )
621+ } else {
622+ logOperationSuccess ("CREATING_BATCH_SPEC" , fmt .Sprintf ("%s%s" , cfg .Endpoint , url ))
623+ }
624+
625+ if opts .applyBatchSpec {
626+ logOperationStart ("APPLYING_BATCH_SPEC" , "" )
627+ batch , err := svc .ApplyBatchChange (ctx , id )
628+ if err != nil {
629+ return err
630+ }
631+
632+ logOperationSuccess ("APPLYING_BATCH_SPEC" , fmt .Sprintf ("%s%s" , cfg .Endpoint , batch .URL ))
633+ }
634+
635+ return nil
636+ }
637+
418638// batchParseSpec parses and validates the given batch spec. If the spec has
419639// validation errors, the errors are output in a human readable form and an
420640// exitCodeError is returned.
0 commit comments