Adding and then sorting steps via Octoposh / aPI

Hi.

I’m currently able to add a step to a project’s deployment process using Octoposh. Using code something like the below.

$Project = Get-OctopusProject -ProjectName $ProjectName -ResourceOnly -Verbose
$process = $con.Repository.DeploymentProcesses.get($Project.DeploymentProcessId)

$newStep = [Octopus.Client.Model.DeploymentStepResource]::new()
$actionTemplate = $con.Repository.ActionTemplates.FindByName("My Template")

$stepAction = [Octopus.Client.Model.DeploymentActionResource]::new()  
$stepAction.Name = $actionTemplate.Name
$stepAction.ActionType = $actionTemplate.ActionType

foreach ($property in $actionTemplate.Properties.Keys)
{
    $stepAction.properties.$property = $actionTemplate.Properties.$property
    $stepAction.properties."Octopus.Action.Template.Version" = $actionTemplate.Version
    $stepAction.properties."Octopus.Action.Template.Id" = $actionTemplate.Id
}
$newStep.Actions.Add($stepAction)

$process.Steps.Add($newStep)
$con.Repository.DeploymentProcesses.Modify($process)

Of course this deployment process will currently have existing steps in it already. I’m wondering what the best way to sort the steps so that I have the new step in the position that I want could be. In fact, let’s say that I have three new steps that I’ll be adding in a similar way. One needs to be the first, another the second, and another the last step in the process.

Anyone tried this before? I’m thinking maybe clear the steps in the object. Then add them back in one at a time in the order I prefer. E.g. do I have a new one for the current position? if yes, then add it, otherwise add the next one from the old steps.

Any alternative suggestions? I’m hoping there’s a baked in sort of some kind as it seems an integral part of the UI.

Cheers.

Hi Daniel,

Thanks for getting in touch. Octoposh currently doesn’t support modifying the deployment process.

Your best course of action will be to use the Octopus.Client/API to do this. You’ll need to write yourself, We have a large set of script examples here you can use for inspiration and ideas:

Here’s an example of creating a script step:

Here’s how to remove all steps:

If you use your browsers network tab, you’ll see the API calls being made when you do things through the Octopus web app (user interface), that may help you work out / find the best way to call the API and what data to provide.

Regards,
Nick

Hmm… Thanks. Well I’ve managed to do with Octoposh. Admittedly, it’s mostly access the resources and not using the cmdlets for the most part. But in case anyone would like to see it or suggest improvements, I’ll add it here.

function Add-OctopusSteps
{
    param
    (
        [parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [Octopus.Client.Model.ProjectResource]
        $Project,

        [parameter(Mandatory=$true)]
        [Array]
        $stepsToAdd
    )

    process {
        $con = New-OctopusConnection

        $process = $con.Repository.DeploymentProcesses.get($Project.DeploymentProcessId)
        $processOld = $con.Repository.DeploymentProcesses.get($Project.DeploymentProcessId)

        $stepsToAdd | Where-Object {$_.Position -lt 0} | ForEach-Object{
            $_.Position = $_.Position + ($TargetStepCount + 1)
        }

        $process.Steps.Clear()

        $i = 1
        $oldStepKey = 0
        Do {
            $stepToAdd = $stepsToAdd | Where-Object {$_.Position -eq $i}
            if ($stepToAdd){
                Write-Output "Adding step: $($stepToAdd.StepName)"

                $newStep = [Octopus.Client.Model.DeploymentStepResource]::new()
                $newStep.Name = $stepToAdd.StepName
                $actionTemplate = $con.Repository.ActionTemplates.FindByName($stepToAdd.TemplateName)

                $stepAction = [Octopus.Client.Model.DeploymentActionResource]::new()
                $stepAction.Name = $actionTemplate.Name
                $stepAction.ActionType = $actionTemplate.ActionType

                foreach ($property in $actionTemplate.Properties.Keys)
                {
                    $stepAction.properties.$property = $actionTemplate.Properties.$property
                    $stepAction.properties."Octopus.Action.Template.Version" = $actionTemplate.Version
                    $stepAction.properties."Octopus.Action.Template.Id" = $actionTemplate.Id
                }

                if( $stepToAdd.ExtraProperties )
                {
                    foreach ( $prop in $stepToAdd.ExtraProperties.GetEnumerator() )
                    {
                        if( $stepAction.Properties.Remove($prop.Name) )
                        {
                            Write-Output "Action property '$($prop.Name)' removed. Will replace with provided value of '$($prop.Value.Value)'."
                        }
                        $stepAction.Properties.Add($prop.Name,$prop.Value)
                    }
                }

                $newStep.Actions.Add($stepAction)
                $process.Steps.Add($newStep)
            }
            else {
                Write-Output "Adding step: $($processOld.Steps[$oldStepKey].Name)"
                $process.Steps.Add($processOld.Steps[$oldStepKey])

                $oldStepKey++
            }
            $i++
        }
        until($i -gt $TargetStepCount)
        $con.Repository.DeploymentProcesses.Modify($process) | Out-Null
    }

    end{
        Write-Output "Steps added."
    }
}

$ProjectName = "MyProject"

$project = Get-OctopusProject -ProjectName $ProjectName -ResourceOnly -Verbose

#First map the step templates and provide additional properties
$stepsToAdd = @(
    [PSCustomObject]@{
        StepName = "Deployment Audit Checks"
        TemplateName = "Deployment Audit Checks"
        Position = 1
        ExtraProperties = @{
            "Octopus.Action.RunOnServer" = [Octopus.Client.Model.PropertyValueResource]::new("true")
            skipReqCheck = [Octopus.Client.Model.PropertyValueResource]::new('$false') #This is a parameter for the step template. Should always default to false.
        }
    }
    [PSCustomObject]@{
        StepName = "Comms - Commencing Deployment"
        TemplateName = "Comms - Commencing Deployment v2"
        Position = 2
    }    
    [PSCustomObject]@{
        StepName = "Comms - Change Complete" 
        TemplateName = "Comms - Change Complete v2"
        Position = -1
    }
)

#Now add the steps
$project | Add-OctopusSteps -stepsToAdd $stepsToAdd

This will create the steps in the positions provided in the “stepsToAdd” array. If a number is in the negative, it will mean reverse position. e.g. -1 means the last step. -2 means the second to last step. 1 means the very first step, etc.