(ctx context.Context, project *types.Project, services []string, options api.WatchOptions)
| 633 | } |
| 634 | |
| 635 | func (s *composeService) rebuild(ctx context.Context, project *types.Project, services []string, options api.WatchOptions) error { |
| 636 | options.LogTo.Log(api.WatchLogger, fmt.Sprintf("Rebuilding service(s) %q after changes were detected...", services)) |
| 637 | // Work on a copy so concurrent watch events don't race on the shared |
| 638 | // BuildOptions pointer carried by WatchOptions. |
| 639 | buildOpts := *options.Build |
| 640 | // Restrict the build to ONLY the watched services, not any of their |
| 641 | // dependencies. `up --build` sets Deps=true so initial startup builds |
| 642 | // images for depends_on services; here we must reset it, otherwise a |
| 643 | // rebuild for service A cascades to its upstream dependency B. |
| 644 | buildOpts.Services = services |
| 645 | buildOpts.Deps = false |
| 646 | buildOpts.Progress = string(progressui.PlainMode) |
| 647 | buildOpts.Out = cutils.GetWriter(func(line string) { |
| 648 | options.LogTo.Log(api.WatchLogger, line) |
| 649 | }) |
| 650 | |
| 651 | var ( |
| 652 | imageNameToIdMap map[string]string |
| 653 | err error |
| 654 | ) |
| 655 | err = tracing.SpanWrapFunc("project/build", tracing.ProjectOptions(ctx, project), |
| 656 | func(ctx context.Context) error { |
| 657 | imageNameToIdMap, err = s.build(ctx, project, buildOpts, nil) |
| 658 | return err |
| 659 | })(ctx) |
| 660 | if err != nil { |
| 661 | options.LogTo.Log(api.WatchLogger, fmt.Sprintf("Build failed. Error: %v", err)) |
| 662 | return err |
| 663 | } |
| 664 | |
| 665 | if options.Prune { |
| 666 | s.pruneDanglingImagesOnRebuild(ctx, project.Name, imageNameToIdMap) |
| 667 | } |
| 668 | |
| 669 | options.LogTo.Log(api.WatchLogger, fmt.Sprintf("service(s) %q successfully built", services)) |
| 670 | |
| 671 | err = s.create(ctx, project, api.CreateOptions{ |
| 672 | Services: services, |
| 673 | Inherit: true, |
| 674 | Recreate: api.RecreateForce, |
| 675 | SkipProviders: true, |
| 676 | }) |
| 677 | if err != nil { |
| 678 | options.LogTo.Log(api.WatchLogger, fmt.Sprintf("Failed to recreate services after update. Error: %v", err)) |
| 679 | return err |
| 680 | } |
| 681 | |
| 682 | p, err := project.WithSelectedServices(services, types.IncludeDependents) |
| 683 | if err != nil { |
| 684 | return err |
| 685 | } |
| 686 | err = s.start(ctx, project.Name, api.StartOptions{ |
| 687 | Project: p, |
| 688 | Services: services, |
| 689 | AttachTo: services, |
| 690 | }, nil) |
| 691 | if err != nil { |
| 692 | options.LogTo.Log(api.WatchLogger, fmt.Sprintf("Application failed to start after update. Error: %v", err)) |
no test coverage detected