-
Notifications
You must be signed in to change notification settings - Fork 6
Add support for 'continue-on-error' in scenario steps and UI compon… #112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0ad395a
bd2a8dd
ff51208
5fca634
c94a2c1
1cc1abf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,3 +14,4 @@ steps: | |
| arguments: | ||
| state: ENDED | ||
| - step: Teardown Flight Declaration | ||
| if: always() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,3 +14,4 @@ steps: | |
| arguments: | ||
| state: ENDED | ||
| - step: Teardown Flight Declaration | ||
| if: always() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,3 +29,4 @@ steps: | |
| arguments: | ||
| action: STOP | ||
| surveillance_session_id: ${{ steps.Generate UUID.result }} | ||
| if: always() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,3 +33,4 @@ steps: | |
| action: STOP | ||
| needs: | ||
| - stream_air_traffic | ||
| if: always() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,3 +16,4 @@ steps: | |
| arguments: | ||
| state: ENDED | ||
| - step: Teardown Flight Declaration | ||
| if: always() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,3 +18,4 @@ steps: | |
| arguments: | ||
| state: ENDED | ||
| - step: Teardown Flight Declaration | ||
| if: always() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,4 +29,5 @@ steps: | |
| arguments: | ||
| state: ENDED | ||
| - step: Teardown Flight Declaration | ||
| if: always() | ||
| description: Cleanup. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,3 +21,4 @@ steps: | |
| arguments: | ||
| state: ENDED | ||
| - step: Teardown Flight Declaration | ||
| if: always() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -626,10 +626,17 @@ async def _execute_group( | |
|
|
||
| # If step failed and it's not allowed to fail, break the group | ||
| if result.status == Status.FAIL: | ||
| logger.error(f"Group step '{group_step.id}' failed, stopping group execution") | ||
| # Mark remaining steps as SKIP | ||
| self._mark_remaining_group_steps_skipped(group, group_name, loop_context, executed_step_indices) | ||
| break | ||
| if group_step.continue_on_error: | ||
| logger.warning(f"Group step '{group_step.id}' failed, but continue-on-error=true — continuing group") | ||
| result.continue_on_error = True | ||
| if self.session_context: | ||
| with self.session_context: | ||
| self.session_context.update_result(result) | ||
| else: | ||
| logger.error(f"Group step '{group_step.id}' failed, stopping group execution") | ||
| # Mark remaining steps as SKIP | ||
| self._mark_remaining_group_steps_skipped(group, group_name, loop_context, executed_step_indices) | ||
| break | ||
|
|
||
| return results | ||
|
|
||
|
|
@@ -663,6 +670,15 @@ def _mark_remaining_group_steps_skipped( | |
| with self.session_context: | ||
| self.session_context.update_result(skipped_result) | ||
|
|
||
| def _mark_results_continue_on_error(self, results: List[StepResult]) -> None: | ||
| """Mark failed results as continue_on_error and update them in session context.""" | ||
| for result in results: | ||
| if result.status == Status.FAIL: | ||
| result.continue_on_error = True | ||
| if self.session_context: | ||
| with self.session_context: | ||
| self.session_context.update_result(result) | ||
|
|
||
| async def _wait_for_dependencies(self, step: StepDefinition) -> None: | ||
| """Wait for any declared dependencies (by step ID) before executing a step.""" | ||
| if not step.needs: | ||
|
|
@@ -779,30 +795,50 @@ async def run_scenario(self, scenario: ScenarioDefinition) -> List[StepResult]: | |
| # Wait for declared dependencies (useful for background steps) | ||
| await self._wait_for_dependencies(step) | ||
|
|
||
| should_continue_on_error = step.continue_on_error | ||
|
|
||
| # Check if this step references a group | ||
| if self._is_group_reference(step.step, scenario): | ||
| # Handle loop execution for groups | ||
| if step.loop: | ||
| loop_results = await self._execute_loop_for_group(step, scenario) | ||
| if loop_results and any(r.status == Status.FAIL for r in loop_results): | ||
| logger.error(f"Loop for group '{step.id}' failed, breaking scenario") | ||
| break | ||
| if should_continue_on_error: | ||
| logger.warning(f"Loop for group '{step.id}' failed, but continue-on-error=true — continuing") | ||
| self._mark_results_continue_on_error(loop_results) | ||
| else: | ||
| logger.error(f"Loop for group '{step.id}' failed, breaking scenario") | ||
| break | ||
|
Comment on lines
803
to
+811
|
||
| else: | ||
| group_results = await self._execute_group(step, scenario) | ||
| if any(r.status == Status.FAIL for r in group_results): | ||
| logger.error(f"Group '{step.id}' failed, breaking scenario") | ||
| break | ||
| if should_continue_on_error: | ||
| logger.warning(f"Group '{step.id}' failed, but continue-on-error=true — continuing") | ||
| self._mark_results_continue_on_error(group_results) | ||
| else: | ||
| logger.error(f"Group '{step.id}' failed, breaking scenario") | ||
| break | ||
|
Comment on lines
812
to
+820
|
||
| else: | ||
| # Regular step execution | ||
| # Handle loop execution | ||
| if step.loop: | ||
| loop_results = await self._execute_loop(step) | ||
| # Check if any loop iteration failed | ||
| if loop_results and any(r.status == Status.FAIL for r in loop_results): | ||
| logger.error(f"Loop for step '{step.id}' failed, breaking scenario") | ||
| break | ||
| if should_continue_on_error: | ||
| logger.warning(f"Loop for step '{step.id}' failed, but continue-on-error=true — continuing") | ||
| self._mark_results_continue_on_error(loop_results) | ||
| else: | ||
| logger.error(f"Loop for step '{step.id}' failed, breaking scenario") | ||
| break | ||
| else: | ||
| await self.execute_single_step(step) | ||
| result = await self.execute_single_step(step) | ||
| if result.status == Status.FAIL and should_continue_on_error: | ||
| logger.warning(f"Step '{step.id}' failed, but continue-on-error=true — continuing") | ||
| result.continue_on_error = True | ||
| if self.session_context: | ||
| with self.session_context: | ||
| self.session_context.update_result(result) | ||
|
atti92 marked this conversation as resolved.
|
||
| # An empty scenario (or one whose every step was skipped before any | ||
| # `with self.session_context:` block ran) leaves session_context.state | ||
| # unset; return an empty list rather than crashing. | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.