Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Oct 23, 2025

Summary

This PR implements thread-safe status tracking for pipeline steps, allowing the pipeline execution engine to track whether steps are pending, running, succeeded, failed, canceled, or skipped. This provides better visibility into pipeline execution state and enables improved error reporting and diagnostics.

Changes

New PipelineStepStatus Enum

Added a new enum with six status values representing the lifecycle of a pipeline step:

public enum PipelineStepStatus
{
    Pending,    // Step is waiting to start
    Running,    // Step is currently executing
    Succeeded,  // Step completed successfully
    Failed,     // Step failed during execution
    Canceled,   // Step was canceled before completion
    Skipped     // Step was skipped and not executed
}

Updated PipelineStep Class

Modified the PipelineStep class to support thread-safe status management:

  • Changed Status to a read-only property backed by a private field with lock-based synchronization
  • Added internal TryTransitionStatus() method for validated, thread-safe state transitions
  • Implemented state transition validation to prevent invalid transitions:
    • PendingRunning, Failed (dependency failure), or Skipped (filtered out)
    • RunningSucceeded, Failed, or Canceled
    • Terminal states (Succeeded, Failed, Canceled, Skipped) cannot transition to other states
    • Same-state transitions are idempotent
public PipelineStepStatus Status { get; } // Read-only, thread-safe
internal bool TryTransitionStatus(PipelineStepStatus newStatus) // Validated transitions

Automatic Status Management

Modified the DistributedApplicationPipeline execution engine to automatically update step status throughout the execution lifecycle using the thread-safe transition method:

  • PendingRunning: Status is set when step execution begins
  • RunningSucceeded: Status is set when step completes successfully
  • RunningFailed: Status is set when step throws an exception
  • RunningCanceled: Status is set when step is canceled via OperationCanceledException
  • PendingFailed: Dependent steps are marked as failed when their dependencies fail
  • PendingSkipped: Steps that are filtered out (not in the execution path) are marked as skipped

The implementation ensures that OperationCanceledException is properly preserved (not wrapped) to enable correct cancellation detection, and eliminates duplicate status assignments in exception handling paths.

Testing

Added comprehensive test coverage with 12 new tests covering:

  • Default status initialization
  • Successful execution status transitions
  • Failed execution status transitions
  • Canceled execution status transitions
  • Multiple independent steps tracking status
  • Dependent steps with proper status transitions
  • Failed dependencies marking dependent steps as failed
  • Invalid state transition validation
  • Valid state transition validation
  • Same-state transition handling
  • Filtered steps being marked as skipped
  • Skipped status transition validation

All 76 pipeline tests pass (64 existing + 12 new) with no regressions.

Benefits

  • 📊 Track execution progress of individual pipeline steps
  • 🔍 Identify which steps succeeded, failed, were canceled, or were skipped at a glance
  • 🎯 Monitor overall pipeline execution state
  • 🐛 Enable better error reporting and diagnostics
  • 🖥️ Support status-based UI updates for deployment dashboards
  • 🔒 Thread-safe status management prevents race conditions
  • ✅ State validation ensures status integrity
  • ⏭️ Clear indication of skipped steps in filtered executions

Breaking Changes

None. This is a purely additive feature. The status property remains publicly readable, and the internal transition method is only used by the pipeline execution engine. The status property is automatically managed by the pipeline execution engine and requires no changes from consumers.

Fixes #12282

Original prompt

This section details on the original issue you should resolve

<issue_title>Support modeling status on pipeline steps</issue_title>
<issue_description>Pipeline steps don't currently support modeling their status. We should add this so we can track if steps are waiting, running, or completed. The status should also capture completion state.

  • Introduce a new PipelineStepStatus enum.
enum PipelineStepStatus {
    Pending,
    Running,
    Succeeded,
    Failed,
    Canceled
}
  • Add a Status property to a PipelineStep
  • Update the DistributedApplicationPipeline to set the status on each of those steps</issue_description>

Comments on the Issue (you are @copilot in this section)

Fixes #12282


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: captainsafia <1857993+captainsafia@users.noreply.github.com>
Copilot AI changed the title [WIP] Support modeling status on pipeline steps Add status tracking to pipeline steps Oct 23, 2025
Copilot AI requested a review from captainsafia October 23, 2025 15:55
Copilot finished work on behalf of captainsafia October 23, 2025 15:55
@github-actions
Copy link
Contributor

github-actions bot commented Oct 23, 2025

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 12312

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 12312"

@captainsafia captainsafia marked this pull request as ready for review October 23, 2025 18:27
@Copilot Copilot AI review requested due to automatic review settings October 23, 2025 18:27
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds status tracking capabilities to pipeline steps, enabling the pipeline execution engine to monitor the lifecycle state of each step through five distinct statuses: Pending, Running, Succeeded, Failed, and Canceled. This enhances visibility into pipeline execution and supports better diagnostics.

Key Changes:

  • Introduced PipelineStepStatus enum with five lifecycle states
  • Added automatic status management in DistributedApplicationPipeline that updates step status throughout execution
  • Included comprehensive test coverage with 7 new tests validating all status transitions

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
src/Aspire.Hosting/Pipelines/PipelineStepStatus.cs New enum defining the five possible execution states for pipeline steps
src/Aspire.Hosting/Pipelines/PipelineStep.cs Added Status property with default value of Pending
src/Aspire.Hosting/Pipelines/DistributedApplicationPipeline.cs Implemented automatic status tracking logic throughout step execution lifecycle
tests/Aspire.Hosting.Tests/Pipelines/DistributedApplicationPipelineTests.cs Added 7 new tests covering all status transition scenarios

catch (OperationCanceledException)
{
// Cancellation - mark as canceled and re-throw
step.Status = PipelineStepStatus.Canceled;
Copy link

Copilot AI Oct 23, 2025

Choose a reason for hiding this comment

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

Duplicate status assignment for Canceled state. The status is already set to Canceled in the inner catch block (lines 386-390). This outer catch will only execute if the inner try-catch is bypassed, but the inner catch already handles OperationCanceledException and re-throws it. Consider removing this outer catch block to eliminate the redundancy.

Suggested change
step.Status = PipelineStepStatus.Canceled;

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in commit 526ca72. Removed the duplicate outer catch block for OperationCanceledException - status is now only set once in the inner catch block.

catch (Exception ex)
{
// Execution failure - mark as failed, cancel all other work, and re-throw
step.Status = PipelineStepStatus.Failed;
Copy link

Copilot AI Oct 23, 2025

Choose a reason for hiding this comment

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

Duplicate status assignment for Failed state. The status is already set to Failed in the inner catch block (line 393). This outer catch will receive the re-thrown exception from the inner catch, causing the Failed status to be set twice. The outer assignment on line 416 is redundant.

Suggested change
step.Status = PipelineStepStatus.Failed;

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in commit 526ca72. Removed the duplicate outer catch block for Failed status - status is now only set once in the inner catch block.

using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, publisher: "default", isDeploy: true);
var pipeline = new DistributedApplicationPipeline();

var statusTransitions = new Dictionary<string, List<PipelineStepStatus>>();
Copy link

Copilot AI Oct 23, 2025

Choose a reason for hiding this comment

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

The variable 'statusTransitions' is declared but never used in this test. Consider removing this unused variable declaration.

Suggested change
var statusTransitions = new Dictionary<string, List<PipelineStepStatus>>();

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in commit 526ca72. Removed the unused statusTransitions variable declaration.

@captainsafia captainsafia requested review from Erarndt, davidfowl and eerhardt and removed request for Erarndt October 23, 2025 18:30

// Wrap the dependency failure with context about this step
var wrappedException = new InvalidOperationException(message, ex);
step.Status = PipelineStepStatus.Failed;
Copy link
Member

Choose a reason for hiding this comment

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

Do we need to worry about concurrency at all? Is it possible for 2 threads to try to update the status at the same time?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, all state changes need to be guarded and thread safe. We need to make sure that transitions are valid (you can't flip between arbitrary states).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in commit 526ca72. Made status changes thread-safe by:

  1. Changed Status to a read-only property backed by a private field
  2. Added TryTransitionStatus() internal method that uses a lock for thread-safe updates
  3. Implemented state transition validation to ensure only valid transitions are allowed (e.g., Pending→Running, Running→Succeeded/Failed/Canceled, but no transitions from terminal states)
  4. Added 3 new tests to validate the state transition logic

@davidfowl
Copy link
Member

@copilot implement the review feedback. Make the state change a method instead of a property and guard against invalid state transitions.

Co-authored-by: davidfowl <95136+davidfowl@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Oct 23, 2025

@copilot implement the review feedback. Make the state change a method instead of a property and guard against invalid state transitions.

Implemented in commit 526ca72. Changes made:

  1. Changed to method-based approach: Replaced the Status property setter with an internal TryTransitionStatus() method
  2. Thread-safe implementation: Used lock mechanism to ensure thread-safe status updates
  3. State transition validation: Added IsValidTransition() method that enforces valid state transitions:
    • Pending can transition to Running or Failed (dependency failure)
    • Running can transition to Succeeded, Failed, or Canceled
    • Terminal states (Succeeded, Failed, Canceled) cannot transition to other states
    • Same-state transitions are allowed (idempotent)
  4. Updated pipeline execution: All status assignments now use TryTransitionStatus()
  5. Removed duplicate assignments: Fixed the duplicate status assignments in outer catch blocks
  6. Added tests: 3 new tests validate state transition logic

All 74 tests pass.

Copilot AI changed the title Add status tracking to pipeline steps Add thread-safe status tracking to pipeline steps Oct 23, 2025
Copilot finished work on behalf of davidfowl October 23, 2025 20:33
@davidfowl
Copy link
Member

@copilot We should be setting the state to Canceled for OperationCancelledException. We should add a Skipped status if a task was not run.

Co-authored-by: davidfowl <95136+davidfowl@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Oct 23, 2025

@copilot We should be setting the state to Canceled for OperationCancelledException. We should add a Skipped status if a task was not run.

Implemented in commit 966cece. Changes made:

  1. Added Skipped status: Added a new PipelineStepStatus.Skipped enum value for steps that are not executed
  2. Status already set to Canceled: Confirmed OperationCanceledException correctly sets status to Canceled (lines 386-390 in DistributedApplicationPipeline.cs)
  3. Mark filtered steps as Skipped: Updated FilterStepsForExecution to mark steps that are filtered out (not in the execution path) as Skipped
  4. State transition validation: Updated IsValidTransition to allow PendingSkipped transitions
  5. Added tests: 2 new tests validate the Skipped status behavior

All 76 tests pass.

Copilot finished work on behalf of davidfowl October 23, 2025 20:43
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.

Support modeling status on pipeline steps

4 participants