fix(swarm): let the deploy wait for its own update instead of guessing after it

docker stack deploy defaults to --detach, so it returns before the daemon has
registered the rolling update. In that window a converged stack and one about to
be replaced look identical: UpdateStatus still reads completed from the previous
round, the outgoing task is still desired-state running and Running, and the
replica column still reads 1/1. The gate answers correctly and answers the wrong
question.

Moodle in run 33574056480 shows the whole shape. The stack deploy reported
changed at 02:26:30.797, the convergence gate went green 1.14s later, cfg.php
failed at 02:26:36 with

    Access denied for user 'moodle'@'192.168.201.4'

and the task carrying the new password did not start until 02:27:15, 38 seconds
after the failure. There was one task at the moment of the failure and it was the
old one, so this is not a resolver picking the wrong task of two.

--detach=false hands the waiting to the daemon, which is the only party that
knows an update has been created. The task after it starts once the update is
through, and the window is gone.

This sits next to 4b9e191200 rather than replacing it: that one stops an outgoing
task from satisfying the replica count while an update is in flight. This one
covers the moment before the update exists at all.

The deploy timeout derives from swarm_stack_converge_retries, the same knob the
gate polls on, so the two budgets cannot drift apart.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kevinveenbirkenbachandClaude Opus 5 committed 2026-09-02 20:26:08 +02:00
1 parent e6a76dbf72
commit 87e4313e11
1 file changed
+2
+2
View File
@@ -146,6 +146,7 @@
docker stack deploy \
{{ lookup('compose_file_args', application_id, flag='--compose-file') }} \
--resolve-image never \
--detach=false \
--prune \
--with-registry-auth \
"{{ application_id | get_entity_name }}"
@@ -154,6 +155,7 @@
executable: /bin/bash
register: swarm_deploy_result
changed_when: true
timeout: "{{ (swarm_stack_converge_retries | int) * 2 }}"
listen:
- compose-up
- swarm-deploy