Skip to content

Link automation.action.* events to automation.triggered event#143

Open
tomerqodo wants to merge 7 commits intoqodo_combined_20260121_qodo_grep_cursor_copilot_1_base_link_automationaction_events_to_automationtriggered_event_pr553from
qodo_combined_20260121_qodo_grep_cursor_copilot_1_head_link_automationaction_events_to_automationtriggered_event_pr553
Open

Link automation.action.* events to automation.triggered event#143
tomerqodo wants to merge 7 commits intoqodo_combined_20260121_qodo_grep_cursor_copilot_1_base_link_automationaction_events_to_automationtriggered_event_pr553from
qodo_combined_20260121_qodo_grep_cursor_copilot_1_head_link_automationaction_events_to_automationtriggered_event_pr553

Conversation

@tomerqodo
Copy link
Copy Markdown

Benchmark PR from qodo-benchmark#553

chrisguidry and others added 7 commits January 21, 2026 15:45
When debugging automation failures at high volumes, it's difficult to trace
from an `automation.action.failed` event back to the `automation.triggered`
event that spawned it. This adds an `automation_triggered_event_id` field to
`TriggeredAction` and includes it as a related resource with role
`automation-triggered-event` on all action events (`.triggered`, `.executed`,
and `.failed`).

Port of https://github.com/PrefectHQ/nebula/pull/10911

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The triggering-event related resource should appear on all three action
event types (.triggered, .executed, .failed) to enable full traceability.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Now that automation.action.executed and automation.action.failed events include
a triggering-event related resource, update the tests to expect it in their
assertions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Build related_resources once at the start of fail() and succeed() methods and
reuse it for both the .triggered and .failed/.executed events, rather than
building separate lists with identical logic.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add a brief section to the automations docs explaining the events emitted during
automation execution and the related resources (triggering-event and
automation-triggered-event) available for tracing action failures back to their
source.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the docs label Jan 21, 2026
@qodo-code-review
Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (2) 📎 Requirement gaps (0)

Grey Divider


Action required

1. triggers.py missing future annotations 📘 Rule violation ✓ Correctness
Description
src/prefect/server/events/triggers.py contains type annotations but does not include `from
  __future__ import annotations` as the first import statement.
• This violates the required typing pattern for files in src/ and can lead to inconsistent
  forward-reference behavior and slower type checking.
• The new UUID | None annotation added in this PR increases the file’s reliance on consistent
  annotation handling.
Code

src/prefect/server/events/triggers.py[R451-453]

+    source_actions: List[
+        Tuple[Optional[ReceivedEvent], ServerActionTypes, UUID | None]
+    ] = [
Evidence
Compliance ID 7 requires every src/ Python file with type annotations to include `from __future__
import annotations` as the first import. The file header shows no such import, while the modified
code introduces/uses type annotations (UUID | None).

AGENTS.md
src/prefect/server/events/triggers.py[1-18]
src/prefect/server/events/triggers.py[449-453]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`src/prefect/server/events/triggers.py` uses type annotations but does not include `from __future__ import annotations` as the first import statement, violating the required typing standard.

## Issue Context
The file contains annotations (including the newly added `UUID | None` type usage) and must opt into future annotations per the compliance requirement.

## Fix Focus Areas
- src/prefect/server/events/triggers.py[1-18]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Cross-field check uses field_validator 📘 Rule violation ✓ Correctness
Description
TriggeredAction.validate_automation_triggered_event_id validates automation_triggered_event_id
  based on another field (triggering_event).
• This is cross-field validation but is implemented with @field_validator, which violates the
  requirement to use @model_validator for multi-field dependent validation.
• Keeping it as a field validator can create order/availability issues (relying on info.data) and
  makes validation sequencing less reliable.
Code

src/prefect/server/events/schemas/automations.py[R772-780]

+    @field_validator("automation_triggered_event_id")
+    @classmethod
+    def validate_automation_triggered_event_id(cls, v, info):
+        """Ensure automation_triggered_event_id is only set when triggering_event exists."""
+        if v is not None and info.data.get("triggering_event") is None:
+            raise ValueError(
+                "automation_triggered_event_id can only be set when triggering_event is provided"
+            )
+        return v
Evidence
Compliance ID 14 requires cross-field validation to use @model_validator. The added validator
checks automation_triggered_event_id and reads triggering_event from info.data, making it
cross-field validation implemented via @field_validator.

AGENTS.md
src/prefect/server/events/schemas/automations.py[772-780]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`TriggeredAction` performs cross-field validation (it checks `automation_triggered_event_id` based on `triggering_event`) using `@field_validator`, but cross-field validation must use `@model_validator`.

## Issue Context
The current implementation relies on `info.data.get(&quot;triggering_event&quot;)`, which is order-dependent and does not follow the required validation pattern.

## Fix Focus Areas
- src/prefect/server/events/schemas/automations.py[763-780]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Fail drops related links 🐞 Bug ✓ Correctness
Description
• In the failure path, the code builds related_resources with the new automation-triggered-event
  and existing triggering-event, but the emitted prefect.automation.action.triggered event does
  not use it.
• This makes the most important trace links missing exactly when actions fail, and contradicts the
  updated tests/expectations for action.triggered.
• Result: users cannot reliably trace failures back to the automation state change/original
  triggering event, and tests should fail.
Code

src/prefect/server/events/actions.py[R199-205]

                    occurred=triggered_action.triggered,
                    event="prefect.automation.action.triggered",
                    resource=resource,
-                    related=related_resources,
+                    related=self._resulting_related_resources,
                    payload=action_details,
                    id=triggered_event_id,
                    follows=follows_id,
Evidence
Action.fail() constructs related_resources with both the automation-triggered-event and
triggering-event, but then emits the action.triggered event with
related=self._resulting_related_resources instead of related_resources. Tests explicitly assert
the triggering-event related resource exists on the triggered event even in failure cases.

src/prefect/server/events/actions.py[177-206]
tests/events/server/actions/test_actions_service.py[153-191]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
In the failure path, `Action.fail()` builds an enriched `related_resources` list but does not attach it to the emitted `prefect.automation.action.triggered` event, dropping trace links.

### Issue Context
This breaks the intended tracing behavior (and updated tests) for action-triggered events when the action fails.

### Fix Focus Areas
- src/prefect/server/events/actions.py[197-206]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



ⓘ The new review experience is currently in Beta. Learn more

Qodo Logo

Comment on lines +451 to +453
source_actions: List[
Tuple[Optional[ReceivedEvent], ServerActionTypes, UUID | None]
] = [
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. triggers.py missing future annotations 📘 Rule violation ✓ Correctness

src/prefect/server/events/triggers.py contains type annotations but does not include `from
  __future__ import annotations` as the first import statement.
• This violates the required typing pattern for files in src/ and can lead to inconsistent
  forward-reference behavior and slower type checking.
• The new UUID | None annotation added in this PR increases the file’s reliance on consistent
  annotation handling.
Agent prompt
## Issue description
`src/prefect/server/events/triggers.py` uses type annotations but does not include `from __future__ import annotations` as the first import statement, violating the required typing standard.

## Issue Context
The file contains annotations (including the newly added `UUID | None` type usage) and must opt into future annotations per the compliance requirement.

## Fix Focus Areas
- src/prefect/server/events/triggers.py[1-18]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +772 to +780
@field_validator("automation_triggered_event_id")
@classmethod
def validate_automation_triggered_event_id(cls, v, info):
"""Ensure automation_triggered_event_id is only set when triggering_event exists."""
if v is not None and info.data.get("triggering_event") is None:
raise ValueError(
"automation_triggered_event_id can only be set when triggering_event is provided"
)
return v
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Cross-field check uses field_validator 📘 Rule violation ✓ Correctness

TriggeredAction.validate_automation_triggered_event_id validates automation_triggered_event_id
  based on another field (triggering_event).
• This is cross-field validation but is implemented with @field_validator, which violates the
  requirement to use @model_validator for multi-field dependent validation.
• Keeping it as a field validator can create order/availability issues (relying on info.data) and
  makes validation sequencing less reliable.
Agent prompt
## Issue description
`TriggeredAction` performs cross-field validation (it checks `automation_triggered_event_id` based on `triggering_event`) using `@field_validator`, but cross-field validation must use `@model_validator`.

## Issue Context
The current implementation relies on `info.data.get("triggering_event")`, which is order-dependent and does not follow the required validation pattern.

## Fix Focus Areas
- src/prefect/server/events/schemas/automations.py[763-780]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines 199 to 205
occurred=triggered_action.triggered,
event="prefect.automation.action.triggered",
resource=resource,
related=related_resources,
related=self._resulting_related_resources,
payload=action_details,
id=triggered_event_id,
follows=follows_id,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

3. Fail drops related links 🐞 Bug ✓ Correctness

• In the failure path, the code builds related_resources with the new automation-triggered-event
  and existing triggering-event, but the emitted prefect.automation.action.triggered event does
  not use it.
• This makes the most important trace links missing exactly when actions fail, and contradicts the
  updated tests/expectations for action.triggered.
• Result: users cannot reliably trace failures back to the automation state change/original
  triggering event, and tests should fail.
Agent prompt
### Issue description
In the failure path, `Action.fail()` builds an enriched `related_resources` list but does not attach it to the emitted `prefect.automation.action.triggered` event, dropping trace links.

### Issue Context
This breaks the intended tracing behavior (and updated tests) for action-triggered events when the action fails.

### Fix Focus Areas
- src/prefect/server/events/actions.py[197-206]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants