From 65abab8b9d2657d5456192e5e871cde7d4570d7b Mon Sep 17 00:00:00 2001 From: Emrys MacInally Date: Thu, 22 Jan 2026 16:38:09 +0100 Subject: [PATCH] Enhanced Stop-Task with progress bar and array support --- CHANGELOG.md | 14 +++++ OctopusDeploy/Classes/TransformerClasses.psm1 | 25 +++++++-- OctopusDeploy/Public/Stop-Task.ps1 | 54 +++++++++++++------ 3 files changed, 73 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfdb998..6b65844 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [Unreleased] + +### Added + +- **Stop-Task**: Added progress bar when cancelling multiple tasks, showing current progress and task descriptions for better user feedback. + +### Changed + +- **Stop-Task**: Enhanced `Task` parameter to accept arrays of tasks using the new `TaskTransformation` class, allowing multiple tasks to be cancelled in a single call or via pipeline. + +### Fixed + +- **Stop-Task**: Removed `ValueFromPipeline` from the `Regarding` parameter to resolve parameter set ambiguity when piping task objects. Tasks can now be piped directly to the function without conflicts. + ## [2.2.1] - 2026-01-14 ### Fixed diff --git a/OctopusDeploy/Classes/TransformerClasses.psm1 b/OctopusDeploy/Classes/TransformerClasses.psm1 index 865bea7..61db130 100644 --- a/OctopusDeploy/Classes/TransformerClasses.psm1 +++ b/OctopusDeploy/Classes/TransformerClasses.psm1 @@ -266,10 +266,29 @@ class TaskSingleTransformation : System.Management.Automation.ArgumentTransforma if ($item -is [string] -and $item -like "ServerTasks-*") { $item = Get-Task -TaskID "$item" } - elseif ($item -is [string]) { - $item = $null + elseif ($item -is [Octopus.Client.Model.TaskResource]) { + return $item } - return ($item) + throw "Invalid Task input: $($item.toString())" + } +} + +class TaskTransformation : System.Management.Automation.ArgumentTransformationAttribute { + [object] Transform([System.Management.Automation.EngineIntrinsics]$EngineIntrinsics, [object] $InputData) { + $result = @() + foreach ($item in $InputData) { + if ($item -is [string] -and $item -like "ServerTasks-*") { + $item = Get-Task -TaskID "$item" + } + elseif ($item -is [Octopus.Client.Model.TaskResource]) { + # Already a TaskResource, keep it + } + else { + throw "Invalid Task input: $($item.toString())" + } + $result += ($item) + } + return ($result) } } diff --git a/OctopusDeploy/Public/Stop-Task.ps1 b/OctopusDeploy/Public/Stop-Task.ps1 index d3d89f8..f33ab1c 100644 --- a/OctopusDeploy/Public/Stop-Task.ps1 +++ b/OctopusDeploy/Public/Stop-Task.ps1 @@ -32,10 +32,10 @@ function Stop-Task { [CmdletBinding()] param ( [Parameter(Mandatory = $false, - ValueFromPipelineByPropertyName = $true, + ValueFromPipeline = $true, ParameterSetName = 'byTask')] - [TaskSingleTransformation()] - [Octopus.Client.Model.TaskResource] + [TaskTransformation()] + [Octopus.Client.Model.TaskResource[]] $Task, [Parameter(Mandatory = $false, @@ -57,7 +57,6 @@ function Stop-Task { $Environment, [Parameter(Mandatory = $false, - ValueFromPipeline = $true, ParameterSetName = 'byRegarding')] [ValidateNotNullOrEmpty()] [Octopus.Client.Model.Resource] @@ -77,23 +76,27 @@ function Stop-Task { $PSCmdlet.ThrowTerminatingError($_) } + # Initialize counter for progress + $taskCounter = 0 + $allTasks = @() + } + + process { # Initialize an empty array to store tasks to cancel $tasksToCancel = @() - + # Combine states into a regex pattern $stateRegex = ($State -join '|') -replace ' ', '' - } - - process { + # Check the parameter set name to determine how to retrieve tasks if ($PSCmdlet.ParameterSetName -eq 'byTask') { # Cancel a specific task - $tasksToCancel += $Task + $tasksToCancel = $Task } elseif ($PSCmdlet.ParameterSetName -eq 'byRegarding') { # Cancel tasks regarding a specific object foreach ($r in $Regarding) { - $tasksToCancel += Get-Task -Regarding $r | Where-Object { $_.State -match $stateRegex } + $tasksToCancel = Get-Task -Regarding $r | Where-Object { $_.State -match $stateRegex } } } else { @@ -101,11 +104,27 @@ function Stop-Task { $tasksToCancel = Get-Task -TaskType $TaskType -Tenant $Tenant -Environment $Environment | Where-Object { $_.State -match $stateRegex } } - Write-Verbose "Found $($tasksToCancel.Count) tasks to cancel." + # Add to collection + $allTasks += $tasksToCancel + } - # Cancel each task - # Todo [DNA-327]: Add progress bar for large number of tasks to give user feedback - foreach ($_task in $tasksToCancel) { + end { + Write-Verbose "Found $($allTasks.Count) tasks to cancel." + + # Cancel each task with progress bar + $totalTasks = $allTasks.Count + foreach ($_task in $allTasks) { + $taskCounter++ + + # Show progress bar + if ($totalTasks -gt 0) { + $percentComplete = ($taskCounter / $totalTasks) * 100 + Write-Progress -Activity "Cancelling Tasks" ` + -Status "Processing task $taskCounter of $totalTasks" ` + -CurrentOperation "Cancelling: $($_task.Description)" ` + -PercentComplete $percentComplete + } + try { Write-Verbose "Cancelling task: $($_task.Id) - $($_task.Description)" $repo._repository.Tasks.Cancel($_task) @@ -114,9 +133,10 @@ function Stop-Task { Write-Warning "Failed to cancel task $($_task.Id): $_" } } - } - - end { + # Clear the progress bar + if ($totalTasks -gt 0) { + Write-Progress -Activity "Cancelling Tasks" -Completed + } } } \ No newline at end of file