Skip to content

fix(deploy): don't let a failed docker ps pass for 'no containers' - #105

Merged
owine merged 1 commit into
mainfrom
fix/compose-project-ps-failure
Oct 10, 2026
Merged

owine merged 1 commit into
mainfrom
fix/compose-project-ps-failure

Conversation

@owine

@owine owine commented Oct 10, 2026 •

Copy link
Copy Markdown
Owner

Follow-up to Sourcery's review of #103 (the one finding worth fixing).

Problem

compose_projects turned a failed docker ps into an empty result (|| p=""). With the daemon unreachable, compose_p <stack> down ran nothing and returned 0. Teardowns and failure cleanups then looked successful while the containers kept running. This dates from #101.

Fix

  • Both lookups capture docker's output and exit status before sort (so it doesn't depend on the caller's pipefail), print ::warning::<stack>: docker ps failed… and return 1. docker's own stderr is no longer thrown away.
  • compose_p stores the lookup result instead of reading < <(compose_projects …), because a process substitution loses its exit status. On a failed lookup it returns 1 without calling compose.

Every call site already handles a non-zero return:

  • removed-stack and rollback teardowns log ::warning::down failed
  • the health check reports docker compose ps failed (it runs under pipefail)
  • diagnostics and new-stack cleanups use || true, and the helper's own warning still shows

Verification

  • test-compose-project.sh: 20/20. The 3 new cases (either lookup fails; compose_p makes no call and returns non-zero) all fail against the previous helper.
  • shellcheck is clean.

Independent of #104 (no overlapping files).

Summary by Sourcery

Prevent failed Docker project discovery from being mistaken for an empty deployment during teardown and cleanup.

Bug Fixes:

  • Fail safely when Docker project discovery cannot run instead of treating the failure as an empty container set and reporting teardown success.
  • Propagate project lookup failures through compose operations without invoking Docker Compose.

Enhancements:

  • Preserve Docker diagnostics and emit actionable warnings when project resolution fails.

Tests:

  • Add coverage for failures during both Docker project lookups and verify that compose operations are skipped and return non-zero on lookup failure.

Sourcery review of #103. compose_projects swallowed docker ps failures
(|| p=""), so a broken daemon made compose_p return 0 without running
down: teardowns and failure cleanups looked successful while the containers
kept running. Both lookups now capture docker's status before sorting (no
reliance on the caller's pipefail), warn and return 1; compose_p captures
the lookup result instead of reading a process substitution (whose exit
status is lost) and returns 1 without calling compose. docker's own stderr
is no longer discarded.

Every call site already handles non-zero: teardowns log 'down failed', the
health check reports 'docker compose ps failed', diagnostics use || true.
Tests: 3 new cases (20/20); all 3 fail against the previous helper.
@sourcery-ai

sourcery-ai Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

The PR makes Docker Compose project discovery fail closed: docker ps errors now produce warnings and non-zero status, and compose_p propagates that failure without invoking compose. Tests add coverage for both lookup paths and confirm failed discovery cannot result in a successful no-op teardown.

Sequence diagram for fail-closed Compose project discovery

sequenceDiagram
    participant Caller
    participant compose_p
    participant compose_projects
    participant Docker
    participant Compose

    Caller->>compose_p: compose_p(stack, args)
    compose_p->>compose_projects: compose_projects(stack)
    compose_projects->>Docker: docker ps
    alt docker ps succeeds
        Docker-->>compose_projects: project output
        compose_projects-->>compose_p: project names
        loop each project
            compose_p->>Compose: docker compose -p project args
            Compose-->>compose_p: exit status
        end
        compose_p-->>Caller: compose result
    else docker ps fails
        Docker-->>compose_projects: non-zero status and stderr
        compose_projects-->>Caller: warning and status 1
        compose_projects-->>compose_p: lookup failure
        compose_p-->>Caller: status 1
    end
Loading

File-Level Changes

Change Details Files
Propagate Docker lookup failures instead of treating them as an empty project list.
  • Capture each docker ps result and status before sorting, independent of pipefail.
  • Emit a GitHub warning and preserve Docker stderr when either lookup fails.
  • Return non-zero so teardown and cleanup callers cannot silently succeed.
scripts/deployment/lib/compose-project.sh
Prevent compose execution when project discovery fails.
  • Store compose_projects output directly rather than using process substitution.
  • Return immediately on lookup failure; otherwise iterate discovered projects and preserve compose command status.
scripts/deployment/lib/compose-project.sh
Add regression coverage for Docker lookup failures and skipped compose calls.
  • Extend the fake Docker executable with nth-call failure injection.
  • Test both lookup paths, warning and status propagation, and verify compose is not invoked after discovery failure.
scripts/testing/test-compose-project.sh

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot 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.

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Needs a human reviewer. If the new error propagation mishandles a transient or unexpected docker ps failure, deployment teardown aborts before running Compose, leaving containers or other runtime resources behind and potentially failing the deployment. Reverting restores the previous behavior, but any already-created resource buildup or failed deployment would require manual cleanup or rerunning the operation.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

@owine
owine merged commit ab78ef8 into main Oct 10, 2026
3 checks passed
@owine
owine deleted the fix/compose-project-ps-failure branch October 10, 2026 13:30
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.

1 participant