Skip to content

fix(compose): keep build-only services when Up starts a subset#3732

Open
davireis wants to merge 1 commit into
testcontainers:mainfrom
davireis:fix/compose-runservices-service-build-context
Open

fix(compose): keep build-only services when Up starts a subset#3732
davireis wants to merge 1 commit into
testcontainers:mainfrom
davireis:fix/compose-runservices-service-build-context

Conversation

@davireis

Copy link
Copy Markdown

Problem

Up(RunServices(...)) (any partial-service Up) rebuilt project.Services down to just the selected services before calling the compose service. When a selected service builds from a service: additional build context (build.additional_contexts.<name>: service:<dep>), the referenced build-only service was dropped too, so the build failed with:

service "X" declares unknown service "Y" as additional contexts

…even though docker compose up X on the same project builds the context and starts only X.

Repro

A compose project where a runtime service builds from a service: additional context:

services:
  build-dep:                      # build-only, never started
    build: { dockerfile: dep.Dockerfile }
    image: example/build-dep:latest
  app:
    build:
      dockerfile: app.Dockerfile
      additional_contexts:
        build-dep: service:build-dep   # COPY --from=build-dep ...
    image: example/app:latest

compose.Up(ctx, RunServices("app"))compose up: no such service: build-dep.

Fix

Use project.WithSelectedServices(services, types.IgnoreDependencies) instead of rebuilding project.Services. It disables (not deletes) the non-selected services, keeping them in the project's disabled set, so compose can re-enable build dependencies for the build phase (addBuildDependencies + WithServicesEnabled) while still only creating/starting the selected services. IgnoreDependencies preserves the existing behavior of starting only the explicitly requested services (not their runtime depends_on). The returned (new) project is reassigned to the up options so create and start operate on the same scoped project.

Test

Adds TestDockerComposeAPIWithRunServicesAndServiceBuildContext with a runtime service that builds from a service: additional context. It fails on the previous code (no such service) and passes with the fix. The existing TestDockerComposeAPIWithRunServices still passes, and the up-all path is unchanged.

@davireis davireis requested a review from a team as a code owner June 19, 2026 18:19
@netlify

netlify Bot commented Jun 19, 2026

Copy link
Copy Markdown

Deploy Preview for testcontainers-go ready!

Name Link
🔨 Latest commit ba4213b
🔍 Latest deploy log https://app.netlify.com/projects/testcontainers-go/deploys/6a35893daee88f0008959e69
😎 Deploy Preview https://deploy-preview-3732--testcontainers-go.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d016932e-3d3f-4e92-aa0b-fc2ff589323b

📥 Commits

Reviewing files that changed from the base of the PR and between ce84aa5 and ba4213b.

📒 Files selected for processing (5)
  • modules/compose/compose_api.go
  • modules/compose/compose_api_test.go
  • modules/compose/testdata/docker-compose-service-build-context.yml
  • modules/compose/testdata/service-build-context-app.Dockerfile
  • modules/compose/testdata/service-build-context-dep.Dockerfile
🚧 Files skipped from review as they are similar to previous changes (3)
  • modules/compose/testdata/docker-compose-service-build-context.yml
  • modules/compose/compose_api_test.go
  • modules/compose/compose_api.go

Summary by CodeRabbit

  • Bug Fixes

    • Improved Docker Compose service selection so only requested runtime services are started, without breaking build-only dependencies or additional build contexts.
  • Tests

    • Added a regression test covering RunServices("app") with build-time additional contexts.
    • Introduced new Docker Compose and Dockerfile test fixtures to validate build-only providers are not started while being available during image builds.

Walkthrough

The DockerCompose.Up service-scoping logic is changed from a sort-and-delete filter on d.project.Services to d.project.WithSelectedServices(..., types.IgnoreDependencies), which marks non-selected services as disabled rather than removing them. A regression test and accompanying Compose YAML and Dockerfiles are added to verify that build-only additional_contexts services are not erroneously started.

Changes

RunServices build context scoping fix

Layer / File(s) Summary
Service scoping logic in DockerCompose.Up
modules/compose/compose_api.go
Removes the sort import and replaces the sort-and-delete filter on d.project.Services with d.project.WithSelectedServices(upOptions.Services, types.IgnoreDependencies). The returned scoped project is stored back into d.project and assigned to upOptions.Project so that non-selected services remain in the project as disabled rather than being deleted.
Regression test and build fixtures
modules/compose/compose_api_test.go, modules/compose/testdata/docker-compose-service-build-context.yml, modules/compose/testdata/service-build-context-dep.Dockerfile, modules/compose/testdata/service-build-context-app.Dockerfile
TestDockerComposeAPIWithRunServicesAndServiceBuildContext starts only the app service and asserts it is running while build-dep is not. The compose YAML wires build-dep as an additional_contexts provider; service-build-context-dep.Dockerfile writes an artifact, and service-build-context-app.Dockerfile copies it via the named build context.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

compose, bug

Poem

🐇 Hop, hop — no sorting today,
WithSelectedServices saves the day!
Build-dep stays disabled, not erased,
Its artifact safely interlaced.
The rabbit cheers: contexts in place! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and concisely summarizes the main fix: keeping build-only services when Up starts a subset of services, which is the core issue addressed in the PR.
Description check ✅ Passed The description comprehensively explains the problem, root cause, fix, and testing approach, all directly related to the changeset's purpose and implementation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

`Up(RunServices(...))` (any partial-service Up) rebuilt `project.Services` down
to just the selected services before calling the compose service. When a
selected service builds from a `service:` additional build context
(`build.additional_contexts.<name>: service:<dep>`), the referenced build-only
service was dropped too, so the build failed with:

    service "X" declares unknown service "Y" as additional contexts

even though `docker compose up X` on the same project builds the context and
starts only X.

Use `project.WithSelectedServices(services, IgnoreDependencies)` instead: it
disables (not deletes) the non-selected services, keeping them in the project's
disabled set so compose can re-enable build dependencies for the build phase
while still only creating/starting the selected ones. `IgnoreDependencies`
preserves the existing behavior of starting only the explicitly requested
services. The returned project is reassigned to the up options so create and
start operate on the same scoped project.

Adds a regression test with a runtime service that builds from a `service:`
additional context: it fails on the previous code ("no such service") and
passes now.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@davireis davireis force-pushed the fix/compose-runservices-service-build-context branch from ce84aa5 to ba4213b Compare June 19, 2026 18:23
@mdelapenya mdelapenya requested a review from Copilot June 22, 2026 07:44

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes partial-service compose.Up(..., RunServices(...)) so that build-only services referenced via build.additional_contexts: service:<dep> remain resolvable during the build phase, matching docker compose up <service> behavior.

Changes:

  • Replace manual project.Services filtering with project.WithSelectedServices(..., types.IgnoreDependencies) and ensure the returned project is used consistently for create/start.
  • Add a regression test and new compose/Dockerfile testdata covering service: additional build contexts in a partial-service Up.
  • Add new test compose project assets (compose YAML + two Dockerfiles) to exercise the build-context scenario.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
modules/compose/compose_api.go Switches partial-service scoping to WithSelectedServices and updates up options to use the new project.
modules/compose/compose_api_test.go Adds regression test ensuring build-only service: build context works while only the selected runtime service is started.
modules/compose/testdata/docker-compose-service-build-context.yml New compose fixture defining a runtime service that builds from a build-only service context.
modules/compose/testdata/service-build-context-app.Dockerfile New app Dockerfile consuming the service: additional build context.
modules/compose/testdata/service-build-context-dep.Dockerfile New build-only dependency Dockerfile producing an artifact consumed by the app build.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -321,17 +320,16 @@ func (d *DockerCompose) Up(ctx context.Context, opts ...StackUpOption) (err erro
}

if len(upOptions.Services) != len(d.project.Services) {
Comment on lines +3 to +7
build-dep:
build:
context: .
dockerfile: service-build-context-dep.Dockerfile
image: testcontainers/compose-service-build-dep:latest
Comment on lines +8 to +14
app:
build:
context: .
dockerfile: service-build-context-app.Dockerfile
additional_contexts:
build-dep: service:build-dep
image: testcontainers/compose-service-build-app:latest
@mdelapenya mdelapenya self-assigned this Jun 22, 2026
@mdelapenya mdelapenya added the compose Docker Compose. label Jun 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

compose Docker Compose.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants