Skip to content

Commit 2afc7c6

Browse files
committed
ROB-1654 Leave the rollout revision unset until the controller syncs
On a Deployment update the controller hasn't processed yet (e.g. on_deployment_update right after `kubectl set image`), the revision annotation and the Progressing condition still describe the previous template while the images are already the new ones. event.rollout now reports revision and replicaset as null in that window instead of pairing them with the wrong images. The docs' example prompt also lets Holmes answer "unknown" when a superseded revision's pods are gone and what remains isn't enough to judge it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NBxJJXuSs1TpB2T7CixgLE
1 parent 1bd4a35 commit 2afc7c6

3 files changed

Lines changed: 21 additions & 9 deletions

File tree

‎docs/playbook-reference/actions/miscellaneous.rst‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ The workflow receives a payload like the one below. ``trigger`` and the ``subjec
7171
workflow filters (e.g. ``namespace`` = ``payments``). ``description`` says whether the rollout completed or
7272
failed, and ``resource`` is the Deployment's current manifest (Secret values are always redacted).
7373
``rollout`` names the revision that fired: its revision number, the ReplicaSet running it and the image of
74-
each container. With triggers that set ``change_filters`` (e.g. ``on_deployment_update``), the payload also
74+
each container. On a Deployment update the controller hasn't processed yet, ``revision`` and ``replicaset``
75+
are ``null``, because the new revision doesn't exist yet. With triggers that set ``change_filters`` (e.g. ``on_deployment_update``), the payload also
7576
carries a ``diff`` of the fields those filters kept.
7677

7778
.. code-block:: json
@@ -103,8 +104,10 @@ once it is scaled down. For example:
103104
A Deployment rollout just completed or failed; the trigger payload names it in `rollout`.
104105
Judge that revision: the pods of the ReplicaSet in `rollout.replicaset` running the images in
105106
`rollout.images`. Check that they are running and ready, and look for restarts, warning events
106-
and error logs. If the Deployment has since moved to another revision, say so, and still give
107-
the verdict for the revision in the payload. End with one line: healthy / degraded / failed.
107+
and error logs. If the Deployment has since moved to another revision, say so and judge the
108+
revision in the payload from what remains: the ReplicaSet's status and the events of it and
109+
its pods. End with one line: healthy / degraded / failed, or unknown if what remains is not
110+
enough to tell.
108111
109112
Each cluster's runner triggers the workflow for its own rollouts, so a release rolled out to five clusters
110113
runs the workflow five times, each against its own cluster. To run it once per release, add the playbook

‎src/robusta/core/triggers/deployment_rollout_trigger.py‎

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,22 @@ def get_rollout_revision(deployment: Deployment) -> Dict[str, Any]:
3131
Old ReplicaSets are kept (revisionHistoryLimit), so the ReplicaSet can still be inspected after the
3232
Deployment rolls out a newer revision.
3333
"""
34-
annotations = (deployment.metadata.annotations if deployment.metadata else None) or {}
35-
condition = get_progressing_condition(deployment)
36-
match = REPLICASET_IN_MESSAGE.search(condition.message or "") if condition else None
3734
pod_spec = deployment.spec.template.spec if deployment.spec and deployment.spec.template else None
38-
return {
39-
"revision": annotations.get(REVISION_ANNOTATION),
40-
"replicaset": match.group(1) if match else None,
35+
rollout = {
36+
"revision": None,
37+
"replicaset": None,
4138
"images": {c.name: c.image for c in pod_spec.containers} if pod_spec else {},
4239
}
40+
# Until the controller syncs a spec change, the revision and ReplicaSet still describe the previous template
41+
if not deployment.status or not _is_spec_observed(deployment):
42+
return rollout
43+
44+
annotations = (deployment.metadata.annotations if deployment.metadata else None) or {}
45+
condition = get_progressing_condition(deployment)
46+
match = REPLICASET_IN_MESSAGE.search(condition.message or "") if condition else None
47+
rollout["revision"] = annotations.get(REVISION_ANNOTATION)
48+
rollout["replicaset"] = match.group(1) if match else None
49+
return rollout
4350

4451

4552
def _is_spec_observed(deployment: Deployment) -> bool:

‎tests/test_workflow_trigger.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,8 @@ def test_event_payload_diff_follows_the_triggers_change_filters():
375375

376376
payload = build_event_workflow_payload(event)
377377
json.dumps(payload)
378+
# the controller hasn't synced the new template yet: its revision and ReplicaSet don't exist
379+
assert payload["event"]["rollout"] == {"revision": None, "replicaset": None, "images": {"app": "busybox:1.37.0"}}
378380
assert payload["event"]["diff"] == [
379381
{
380382
"path": "spec.template.spec.containers[0].image",

0 commit comments

Comments
 (0)