-
Notifications
You must be signed in to change notification settings - Fork 5.8k
fix(watch): don't rebuild dependencies when a service changes #13854
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -138,6 +138,10 @@ func (s *composeService) Watch(ctx context.Context, project *types.Project, opti | |
| return wait() | ||
| } | ||
|
|
||
| func selectWatchServices(project *types.Project, services []string) (*types.Project, error) { | ||
| return project.WithSelectedServices(services, types.IgnoreDependencies) | ||
| } | ||
|
|
||
| type watchRule struct { | ||
| types.Trigger | ||
| include watch.PathMatcher | ||
|
|
@@ -188,7 +192,7 @@ func (r watchRule) Matches(event watch.FileEvent) *sync.PathMapping { | |
|
|
||
| func (s *composeService) watch(ctx context.Context, project *types.Project, options api.WatchOptions) (func() error, error) { //nolint: gocyclo | ||
| var err error | ||
| if project, err = project.WithSelectedServices(options.Services); err != nil { | ||
| if project, err = selectWatchServices(project, options.Services); err != nil { | ||
| return nil, err | ||
| } | ||
| syncer, err := s.getSyncImplementation(project) | ||
|
|
@@ -636,6 +640,7 @@ func (s *composeService) rebuild(ctx context.Context, project *types.Project, se | |
| options.LogTo.Log(api.WatchLogger, fmt.Sprintf("Rebuilding service(s) %q after changes were detected...", services)) | ||
| // restrict the build to ONLY this service, not any of its dependencies | ||
| options.Build.Services = services | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [MEDIUM] Data race and shared-state mutation via
options.Build.Services = services
options.Build.Deps = false
options.Build.Progress = string(progressui.PlainMode)
options.Build.Out = cutils.GetWriter(...)…all write directly through the shared pointer to the original
Suggested fix — make a local copy of bo := *options.Build // shallow copy of the value struct
bo.Services = services
bo.Deps = false
bo.Progress = string(progressui.PlainMode)
bo.Out = cutils.GetWriter(...)
options.Build = &bo // point to local copy, not the shared one |
||
| options.Build.Deps = false | ||
| options.Build.Progress = string(progressui.PlainMode) | ||
| options.Build.Out = cutils.GetWriter(func(line string) { | ||
| options.LogTo.Log(api.WatchLogger, line) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| services: | ||
| backend: | ||
| build: | ||
| dockerfile_inline: | | ||
| FROM nginx | ||
| RUN mkdir /data | ||
| COPY backend /data/backend | ||
| frontend: | ||
| build: | ||
| dockerfile_inline: | | ||
| FROM nginx | ||
| RUN mkdir /data | ||
| COPY frontend /data/frontend | ||
| depends_on: | ||
| - backend | ||
| develop: | ||
| watch: | ||
| - path: frontend | ||
| action: rebuild |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[MEDIUM — LIKELY]
selectWatchServiceswithIgnoreDependenciesmay strip dependency metadata needed bycreate/startselectWatchServicesnow callsproject.WithSelectedServices(services, types.IgnoreDependencies), which removes all dependency services from the in-memory project object used throughout the entire watch session.Previously the default mode (
IncludeDependencies) kept dependency service configs in scope. WithIgnoreDependencies, if a user watches onlyfrontend(whichdepends_on: backend),backend's service config is stripped from theprojectvariable early on (line 195). Later inrebuild(), thecreateandstartcalls operate on this stripped project:If
s.create()(line 669) ors.start()needs to resolve network membership, shared volumes, or environment interpolation from a dependency service's config, it will find it absent from the project. This is a broader change than the targetedBuild.Deps = falsefix and may introduce regressions for setups where the dependency service config is needed during container re-creation.The
Build.Deps = falsefix on lines 643 is sufficient to prevent unnecessary dependency rebuilds. It's worth verifying thatIgnoreDependencieshere is intentional and thatcreate/startdo not rely on the full project graph.