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.
nick
(Nick Josevski)
July 13, 2017, 6:19am
2
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:
# You can this dll from your Octopus Server/Tentacle installation directory or from
# https://www.nuget.org/packages/Octopus.Client/
Add-Type -Path 'Octopus.Client.dll'
$apikey = 'API-MCPLE1AQM2VKTRFDLIBMORQHBXA' # Get this from your profile
$octopusURI = 'http://localhost' # Your server address
$projectId = "Projects-100" # Get this from /api/projects
$stepName = "Run a script" # The name of the step
$role = "demo-role" # The machine role to run this step on
$scriptBody = "Write-Host 'Hello world'" # The script to run
$endpoint = New-Object Octopus.Client.OctopusServerEndpoint $octopusURI,$apikey
$repository = New-Object Octopus.Client.OctopusRepository $endpoint
$project = $repository.Projects.Get($projectId)
$process = $repository.DeploymentProcesses.Get($project.DeploymentProcessId)
$step = New-Object Octopus.Client.Model.DeploymentStepResource
$step.Name = $stepName
This file has been truncated. show original
Here’s how to remove all steps:
# You can this dll from your Octopus Server/Tentacle installation directory or from
# https://www.nuget.org/packages/Octopus.Client/
Add-Type -Path 'Octopus.Client.dll'
$apikey = 'API-MCPLE1AQM2VKTRFDLIBMORQHBXA' # Get this from your profile
$octopusURI = 'http://localhost' # Your server address
$projectName = "Demo Project" # Name of your project
$roleToRemove = "Demo-role" # Role to remove (case sensitive)
$endpoint = new-object Octopus.Client.OctopusServerEndpoint $octopusURI,$apikey
$repository = new-object Octopus.Client.OctopusRepository $endpoint
$project = $repository.Projects.FindByName($projectName)
$deploymentProcess = $repository.DeploymentProcesses.Get($project.DeploymentProcessId)
foreach ($step in $deploymentProcess.Steps)
{
[System.Collections.ArrayList]$roles = $step.Properties.'Octopus.Action.TargetRoles'.Split(",")
This file has been truncated. show original
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.