Skip to content

fix: COMPOSE_REMOVE_ORPHANS resolves identically for every command carrying the flag - #14139

Open
ndeloof wants to merge 1 commit into
docker:mainfrom
ndeloof:d1-remove-orphans-resolution
Open

fix: COMPOSE_REMOVE_ORPHANS resolves identically for every command carrying the flag#14139
ndeloof wants to merge 1 commit into
docker:mainfrom
ndeloof:d1-remove-orphans-resolution

Conversation

@ndeloof

@ndeloof ndeloof commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Epic #14074, D.1 (and G.3). COMPOSE_REMOVE_ORPHANS had three resolution mechanisms: up read it after the project's .env was injected into the process environment; down/kill read it at cobra-tree construction time — before that injection, so a value in the project's .env worked for up but not for them; create/run never read it.

All five commands now resolve it identically from PreRunE through one helper: explicit flag > process env > local .env. create also gains COMPOSE_IGNORE_ORPHANS handling (its ignoreOrphans field was sent to the API without ever being assigned), with up's conflict guard.

Behavioral notes:

  • down/kill now honor the variable from the project's .env; the shell-exported case behaves as before (the --help output no longer reflects it as the flag default, since resolution moved out of the flag definition).
  • the remote-config (OCI/Git) exclusion is kept and now documented as a product decision on setEnvWithDotEnv: COMPOSE_* variables are the local user's choice; a remote model must not steer the CLI consuming it.
  • unit tests pin the .env → process env → flag resolution order and the remote exclusion.

🤖 Generated with Claude Code

…rrying the flag

The variable had three resolution mechanisms: up read it in PreRunE
after the project's .env was injected into the process environment;
down and kill read it at cobra-tree construction time — before that
injection, so a value declared in the project's .env worked for up but
not for them; create and run never read it at all.

All five commands now resolve it through one helper, from PreRunE:
explicit flag wins, then the process environment as completed by
setEnvWithDotEnv from the local .env. create also gains the
COMPOSE_IGNORE_ORPHANS handling (its ignoreOrphans field was sent to
the API without ever being assigned) with the same conflict guard as
up.

setEnvWithDotEnv's remote-config exclusion is now documented as a
product decision, not a technical constraint: COMPOSE_* variables
exist so a local user doesn't repeat flags — they are the local user's
choice, and a remote model must not steer the CLI consuming it.

Unit tests pin the .env → process env → flag resolution order and the
remote exclusion (epic docker#14074, D.1 and G.3).

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>

@docker-agent docker-agent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Assessment: 🟡 NEEDS ATTENTION

Lower-confidence findings (not posted inline)

  • [medium→low] cmd/compose/compose.go:757 — Remote-config exclusion guard in setEnvWithDotEnv only works when ConfigPaths is pre-populated; silently skipped when paths are discovered dynamically (confidence: weak 52/100)
  • [medium→low] cmd/compose/create.go:100 — Asymmetric env sources: removeOrphans reads from os.Getenv (process env) while ignoreOrphans reads from project.Environment (loader-resolved); conflict guard may behave differently for remote configs (confidence: weak 52/100)

Comment thread cmd/compose/run.go
display.Mode = display.ModeQuiet
backendOptions.Add(compose.WithEventProcessor(display.Quiet()))
}
options.removeOrphans = removeOrphansFromEnv(cmd.Flags(), options.removeOrphans)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[medium] Missing ignoreOrphans vs removeOrphans conflict guard in run subcommand

This PR correctly adds removeOrphansFromEnv to run's PreRunE so COMPOSE_REMOVE_ORPHANS is now resolved for run — but the corresponding conflict guard that both up and create have was not added to run's RunE.

In up.go (line 129) and create.go (line 103):

if create.ignoreOrphans && create.removeOrphans {
    return fmt.Errorf("cannot combine %s and --remove-orphans", ComposeIgnoreOrphans)
}

In run.go's RunE, after options.ignoreOrphans = utils.StringToBool(project.Environment[ComposeIgnoreOrphans]) (line 217), there is no equivalent check. Now that removeOrphans is properly resolved for run, a user with both COMPOSE_IGNORE_ORPHANS=true in their project .env and COMPOSE_REMOVE_ORPHANS=true (or --remove-orphans) will get conflicting options silently accepted for run, while up and create would return an error.

Fix: Add the same guard in run.go's RunE after options.ignoreOrphans is assigned:

options.ignoreOrphans = utils.StringToBool(project.Environment[ComposeIgnoreOrphans])
if options.ignoreOrphans && options.removeOrphans {
    return fmt.Errorf("cannot combine %s and --remove-orphans", ComposeIgnoreOrphans)
}
Confidence Score
🟢 strong 97/100

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Agreed and confirmed: run is the only command missing this guard; the fix above resolves it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thank you for confirming! Adding the conflict guard to run will ensure consistent validation across all commands that support orphan handling.

@codecov

codecov Bot commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.23529% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
cmd/compose/create.go 50.00% 1 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants