MCPcopy
hub / github.com/docker/compose / TestWatchRebuildIgnoresDependencies

Function TestWatchRebuildIgnoresDependencies

pkg/e2e/watch_test.go:382–448  ·  pkg/e2e/watch_test.go::TestWatchRebuildIgnoresDependencies

TestWatchRebuildIgnoresDependencies verifies that when `compose up --watch` rebuilds a service after a file change, the rebuild does NOT cascade to its `depends_on` dependencies. Reproduces docker/compose#13853: `up --build` sets BuildOptions.Deps=true to build images for dependencies on initial st

(t *testing.T)

Source from the content-addressed store, hash-verified

380// The test scans build progress output between the "Rebuilding service(s)" and
381// "successfully built" markers and asserts only the watched service appears.
382func TestWatchRebuildIgnoresDependencies(t *testing.T) {
383 c := NewCLI(t)
384 const projectName = "test_watch_rebuild_deps"
385
386 defer c.cleanupWithDown(t, projectName)
387
388 tmpdir := t.TempDir()
389 composeFilePath := filepath.Join(tmpdir, "compose.yaml")
390 CopyFile(t, filepath.Join("fixtures", "watch", "rebuild-deps.yaml"), composeFilePath)
391
392 testFile := filepath.Join(tmpdir, "test")
393 assert.NilError(t, os.WriteFile(testFile, []byte("initial"), 0o600))
394
395 cmd := c.NewDockerComposeCmd(t, "-p", projectName, "-f", composeFilePath, "up", "--build", "--watch")
396 buffer := bytes.NewBuffer(nil)
397 cmd.Stdout = buffer
398 cmd.Stderr = buffer
399 watch := icmd.StartCmd(cmd)
400 assert.NilError(t, watch.Error)
401 t.Cleanup(func() {
402 if watch.Cmd.Process != nil {
403 _ = watch.Cmd.Process.Kill()
404 }
405 })
406
407 // Wait until the watcher is actually running. "Watch enabled" is logged
408 // AFTER the initial up (and its build output) is done, so anchoring the
409 // cutoff here keeps initial-build noise out of the rebuild assertions.
410 poll.WaitOn(t, func(l poll.LogT) poll.Result {
411 if strings.Contains(buffer.String(), "Watch enabled") {
412 return poll.Success()
413 }
414 return poll.Continue("waiting for watch to start: %v", buffer.String())
415 }, poll.WithTimeout(120*time.Second))
416
417 // Record the cutoff point in the log buffer so we only inspect output
418 // produced AFTER the file change triggers the rebuild.
419 logCutoff := buffer.Len()
420
421 // Trigger a rebuild of the frontend (only) by modifying the watched file.
422 assert.NilError(t, os.WriteFile(testFile, []byte("updated"), 0o600))
423
424 // Wait until the rebuild is reported as completed.
425 poll.WaitOn(t, func(l poll.LogT) poll.Result {
426 out := buffer.String()
427 if len(out) <= logCutoff {
428 return poll.Continue("no new output yet")
429 }
430 if strings.Contains(out[logCutoff:], `service(s) ["frontend"] successfully built`) {
431 return poll.Success()
432 }
433 return poll.Continue("waiting for rebuild to finish: %v", out[logCutoff:])
434 }, poll.WithTimeout(120*time.Second), poll.WithDelay(time.Second))
435
436 rebuildLog := buffer.String()[logCutoff:]
437
438 // The watch rebuild must only touch the frontend service. The backend is
439 // an upstream dependency and must not be rebuilt.

Callers

nothing calls this directly

Calls 10

cleanupWithDownMethod · 0.95
NewDockerComposeCmdMethod · 0.95
NewCLIFunction · 0.85
CopyFileFunction · 0.85
TempDirMethod · 0.80
WriteFileMethod · 0.80
LenMethod · 0.80
KillMethod · 0.65
StringMethod · 0.45

Tested by

no test coverage detected