This script demonstrates how to programmatically deploy an existing release with prompted variables.
Usage
Provide values for:
- Octopus URL
- Octopus API Key
- Space Name
- Project Name
- Environment Name
- Release Version
- Prompted Variables (the format is variable name::variable value, can be multi-line)
Script
PowerShell (REST API)
$ErrorActionPreference = "Stop";
# Define working variables
$OctopusURL = "https://your-octopus-url"
$apiKey = "API-YOUR-KEY"
$ProjectName = "Your Project Name"
$EnvironmentName = "Your Environment Name"
$ReleaseNumber = "Your Release Number"
$spaceName = "Your Space Name"
$promptedVariableValue = "VariableName::Variable Value"
$Header = @{ "X-Octopus-ApiKey" = $apiKey }
# Get space id
$spaceList = Invoke-RestMethod "$OctopusUrl/api/spaces?partialName=$([System.Web.HTTPUtility]::UrlEncode($spaceName))&skip=0&take=1" -Headers $Header
$spaceId = $spaceList.Items[0].Id
# Get project by name
$ProjectList = Invoke-RestMethod "$OctopusURL/api/$spaceId/projects?name=$([System.Web.HTTPUtility]::UrlEncode($projectName))&skip=0&take=1" -Headers $header
$ProjectId = $ProjectList.Items[0].Id
# Get environment by name
$EnvironmentList = Invoke-RestMethod -Uri "$OctopusURL/api/$spaceId/Environments?name=$([System.Web.HTTPUtility]::UrlEncode($EnvironmentName))&skip=0&take=1" -Headers $Header
$EnvironmentId = $EnvironmentList.Items[0].Id
# Get release by version
$ReleaseList = Invoke-RestMethod -Uri "$OctopusURL/api/$spaceId/projects/$ProjectId/releases?searchByVersion=$([System.Web.HTTPUtility]::UrlEncode($releaseNumber))&skip=0&take=1" -Headers $Header
$ReleaseId = $ReleaseList.Items[0].Id
# Get deployment preview for prompted variables
$deploymentPreview = Invoke-RestMethod "$OctopusUrl/api/$spaceId/releases/$releaseId/deployments/preview/$($EnvironmentId)?includeDisabledSteps=true" -Headers $Header
$deploymentFormValues = @{}
$promptedValueList = @(($promptedVariableValue -Split "`n").Trim())
foreach($element in $deploymentPreview.Form.Elements)
{
$nameToSearchFor = $element.Control.Name
$uniqueName = $element.Name
$isRequired = $element.Control.Required
$promptedVariableFound = $false
Write-Host "Looking for the prompted variable value for $nameToSearchFor"
foreach ($promptedValue in $promptedValueList)
{
$splitValue = $promptedValue -Split "::"
Write-Host "Comparing $nameToSearchFor with provided prompted variable $($promptedValue[$nameToSearchFor])"
if ($splitValue.Length -gt 1)
{
if ($nameToSearchFor -eq $splitValue[0])
{
Write-Host "Found the prompted variable value $nameToSearchFor"
$deploymentFormValues[$uniqueName] = $splitValue[1]
$promptedVariableFound = $true
break
}
}
}
if ($promptedVariableFound -eq $false -and $isRequired -eq $true)
{
Write-Highlight "Unable to find a value for the required prompted variable $nameToSearchFor, exiting"
Exit 1
}
}
# Create deployment
$DeploymentBody = @{
ReleaseID = $releaseId
EnvironmentID = $EnvironmentId
FormValues = $deploymentFormValues
ForcePackageDownload=$False
ForcePackageRedeployment=$False
UseGuidedFailure=$False
} | ConvertTo-Json
Write-Host "Creating deployment with these values: $deploymentBody"
Invoke-RestMethod -Uri "$OctopusURL/api/$spaceId/deployments" -Method Post -Headers $Header -Body $DeploymentBody
PowerShell (Octopus.Client)
# Load assembly
Add-Type -Path 'path:\to\Octopus.Client.dll'
$octopusURL = "https://your-octopus-url"
$octopusAPIKey = "API-YOUR-KEY"
$spaceName = "Default"
$projectName = "MyProject"
$releaseVersion = "0.0.1"
$environmentName = "Development"
$promptedVariable = "MyVariable::MyValue"
$endpoint = New-Object Octopus.Client.OctopusServerEndpoint($octopusURL, $octopusAPIKey)
$repository = New-Object Octopus.Client.OctopusRepository($endpoint)
$client = New-Object Octopus.Client.OctopusClient($endpoint)
# Get space
$space = $repository.Spaces.FindByName($spaceName)
$repositoryForSpace = $client.ForSpace($space)
# Get project by name
$project = $repositoryForSpace.Projects.FindByName($projectName)
Write-Host "Using Project named $($project.Name) with id $($project.Id)"
# Get project releases
$projectRelease = $repositoryForSpace.Projects.GetAllReleases($project) | Where-Object {$_.Version -eq $releaseVersion}
# Get environment
$environment = $repositoryForSpace.Environments.GetAll() | Where-Object {$_.Name -eq $environmentName}
# Get release template
$releaseTemplate = $repositoryForSpace.Releases.GetTemplate($projectRelease)
# Get promotion object
$promotion = $releaseTemplate.PromoteTo | Where-Object {$_.Name -eq $environment.Name}
# Get the preview of the deployment to grab prompted variables
$preview = $repositoryForSpace.Releases.GetPreview($promotion)
# Parse variable
$parsedPromptedVariable = $promptedVariable.Split("::", [System.StringSplitOptions]::RemoveEmptyEntries)
# Create deployment object
$deployment = New-Object Octopus.Client.Model.DeploymentResource -Property @{
ReleaseId = $projectRelease.Id
EnvironmentId = $environment.Id
}
# Loop through form values
foreach ($element in $preview.Form.Elements)
{
# Check to see if element matches variable name
if ($parsedPromptedVariable[0] -eq $element.Control.Name)
{
Write-Host "Adding $($element.Control.Name) to list with value $($parsedPromptedVariable[1])"
$deployment.FormValues.Add($element.Name, $parsedPromptedVariable[1])
}
}
# Execute deployment
$deployment = $repositoryForSpace.Deployments.Create($deployment)
C#
// If using .net Core, be sure to add the NuGet package of System.Security.Permissions
#r "path\to\Octopus.Client.dll"
using Octopus.Client;
using Octopus.Client.Model;
using System.Linq;
var octopusURL = "https://your-octopus-url";
var octopusAPIKey = "API-YOUR-KEY";
var spaceName = "Default";
var projectName = "MyProject";
var releaseVersion = "0.0.1";
var environmentName = "Development";
var promptedVariable = "MyVariable::MyValue";
// Create repository object
var endpoint = new OctopusServerEndpoint(octopusURL, octopusAPIKey);
var repository = new OctopusRepository(endpoint);
var client = new OctopusClient(endpoint);
// Get space
var space = repository.Spaces.FindByName(spaceName);
var spaceRepository = client.ForSpace(space);
// Get project by name
var project = repository.Projects.FindByName(projectName);
// Get project release
var projectRelease = spaceRepository.Projects.GetAllReleases(project).Where(x => x.Version == releaseVersion).FirstOrDefault();
// Get the environment
var environment = spaceRepository.Environments.FindByName(environmentName);
// Get project release template
var template = spaceRepository.Releases.GetTemplate(projectRelease);
// Get promotion object
var promotion = template.PromoteTo.FirstOrDefault(x => x.Name == environment.Name);
// Get preview object
var preview = spaceRepository.Releases.GetPreview(promotion);
// Parse parameter
var parsedParameter = promptedVariable.Split("::", StringSplitOptions.RemoveEmptyEntries);
// Create new deployment object
var deployment = new Octopus.Client.Model.DeploymentResource();
deployment.ReleaseId = projectRelease.Id;
deployment.EnvironmentId = environment.Id;
// Loop through form elements
foreach (var element in preview.Form.Elements)
{
// Check to see if the variable name matches
if (parsedParameter[0] == ((Octopus.Client.Model.Forms.VariableValue)element.Control).Name)
{
// Add to form values
deployment.FormValues.Add(element.Name, parsedParameter[1]);
}
}
// Execute deployment
spaceRepository.Deployments.Create(deployment);
Python3
import json
import requests
from requests.api import get, head
def get_octopus_resource(uri, headers, skip_count = 0):
items = []
skip_querystring = ""
if '?' in uri:
skip_querystring = '&skip='
else:
skip_querystring = '?skip='
response = requests.get((uri + skip_querystring + str(skip_count)), headers=headers)
response.raise_for_status()
# Get results of API call
results = json.loads(response.content.decode('utf-8'))
# Store results
if 'Items' in results.keys():
items += results['Items']
# Check to see if there are more results
if (len(results['Items']) > 0) and (len(results['Items']) == results['ItemsPerPage']):
skip_count += results['ItemsPerPage']
items += get_octopus_resource(uri, headers, skip_count)
else:
return results
# return results
return items
octopus_server_uri = 'https://your-octopus-url'
octopus_api_key = 'API-YOUR-KEY'
headers = {'X-Octopus-ApiKey': octopus_api_key}
space_name = "Default"
project_name = "MyProject"
release_version = "0.0.1"
environment_name = "Development"
prompted_variable = "MyVariable::MyValue"
# Get space
uri = '{0}/api/spaces'.format(octopus_server_uri)
spaces = get_octopus_resource(uri, headers)
space = next((x for x in spaces if x['Name'] == space_name), None)
# Get project
uri = '{0}/api/{1}/projects'.format(octopus_server_uri, space['Id'])
projects = get_octopus_resource(uri, headers)
project = next((x for x in projects if x['Name'] == project_name), None)
# Get project releases
uri = '{0}/api/{1}/projects/{2}/releases'.format(octopus_server_uri, space['Id'], project['Id'])
releases = get_octopus_resource(uri, headers)
release = next((x for x in releases if x['Version'] == release_version), None)
# Get environment
uri = '{0}/api/{1}/environments'.format(octopus_server_uri, space['Id'])
environments = get_octopus_resource(uri, headers)
environment = next((x for x in environments if x['Name'] == environment_name), None)
# Get deployment preview
uri = '{0}/api/{1}/releases/{2}/deployments/preview/{3}?includeDisabledSteps=true'.format(octopus_server_uri, space['Id'], release['Id'], environment['Id'])
preview = get_octopus_resource(uri, headers)
# Create variable for values
form_values = {}
parsedPromptedVariable = prompted_variable.split("::")
# Loop through prompted variables
for promptedVariable in preview['Form']['Elements']:
if promptedVariable['Control']['Name'] == parsedPromptedVariable[0]:
# Add to list
form_values[promptedVariable['Name']] = parsedPromptedVariable[1]
# Create deployment object
# Create deploymentJson
deploymentJson = {
'ReleaseId': release['Id'],
'EnvironmentId': environment['Id'],
'FormValues': form_values
}
# Deploy
uri = '{0}/api/{1}/deployments'.format(octopus_server_uri, space['Id'])
response = requests.post(uri, headers=headers, json=deploymentJson)
response.raise_for_status()
Go
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"strconv"
"strings"
"github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy"
)
func main() {
apiURL, err := url.Parse("https://your-octopus-url")
if err != nil {
log.Println(err)
}
APIKey := "API-YOUR-KEY"
spaceName := "Default"
projectName := "MyProject"
releaseVersion := "0.0.1"
environmentName := "Development"
promptedVariable := "MyVariable::MyValue"
// Get reference to space
space := GetSpace(apiURL, APIKey, spaceName)
// Create client object
client := octopusAuth(apiURL, APIKey, space.ID)
// Get project
project := GetProject(apiURL, APIKey, space, projectName)
// Get environment
environment := GetEnvironment(apiURL, APIKey, space, environmentName)
// Get project releases
projectReleases := GetProjectReleases(apiURL, APIKey, space, project)
// Split prompted variable
parsedPromptedVariable := strings.Split(promptedVariable, "::")
// Declare release
releaseId := ""
// Loop through releases
for i := 0; i < len(projectReleases); i++ {
projectRelease := projectReleases[i].(map[string]interface{})
// Delete release
if projectRelease["Version"].(string) == releaseVersion {
releaseId = projectRelease["Id"].(string)
break
}
}
// Get deployment preview
deploymentPreview := GetDeploymentPreview(apiURL, APIKey, releaseId, space, environment)
// Get form
form := deploymentPreview["Form"].(map[string]interface{})
// Get elements
elements := form["Elements"].([]interface{})
// Create variable for form elements
formElements := make(map[string]string)
// Loop through form elements
for i := 0; i < len(elements); i++ {
element := elements[i].(map[string]interface{})
// check to see if the element display name matches
if (element["Control"].(map[string]interface{}))["Name"] == parsedPromptedVariable[0] {
formElements[element["Name"].(string)] = parsedPromptedVariable[1]
}
}
// Create deployment object
deployment := octopusdeploy.NewDeployment(environment.ID, releaseId)
deployment.FormValues = formElements
// Issue deployment
deployment, err = client.Deployments.Add(deployment)
if err != nil {
log.Println(err)
}
}
func octopusAuth(octopusURL *url.URL, APIKey, space string) *octopusdeploy.Client {
client, err := octopusdeploy.NewClient(nil, octopusURL, APIKey, space)
if err != nil {
log.Println(err)
}
return client
}
func GetSpace(octopusURL *url.URL, APIKey string, spaceName string) *octopusdeploy.Space {
client := octopusAuth(octopusURL, APIKey, "")
spaceQuery := octopusdeploy.SpacesQuery{
Name: spaceName,
}
// Get specific space object
spaces, err := client.Spaces.Get(spaceQuery)
if err != nil {
log.Println(err)
}
for _, space := range spaces.Items {
if space.Name == spaceName {
return space
}
}
return nil
}
func GetProjectReleases(octopusURL *url.URL, APIKey string, space *octopusdeploy.Space, project *octopusdeploy.Project) []interface{} {
// Define api endpoint
projectReleasesEndpoint := octopusURL.String() + "/api/" + space.ID + "/projects/" + project.ID + "/releases"
// Create http client
httpClient := &http.Client{}
skipAmount := 0
// Make request
request, _ := http.NewRequest("GET", projectReleasesEndpoint, nil)
request.Header.Set("X-Octopus-ApiKey", APIKey)
response, err := httpClient.Do(request)
if err != nil {
log.Println(err)
}
// Get response
responseData, err := ioutil.ReadAll(response.Body)
var releasesJson interface{}
err = json.Unmarshal(responseData, &releasesJson)
// Map the returned data
returnedReleases := releasesJson.(map[string]interface{})
// Returns the list of items, translate it to a map
returnedItems := returnedReleases["Items"].([]interface{})
for true {
// check to see if there's more to get
fltItemsPerPage := returnedReleases["ItemsPerPage"].(float64)
itemsPerPage := int(fltItemsPerPage)
if len(returnedReleases["Items"].([]interface{})) == itemsPerPage {
// Increment skip amount
skipAmount += len(returnedReleases["Items"].([]interface{}))
// Make request
queryString := request.URL.Query()
queryString.Set("skip", strconv.Itoa(skipAmount))
request.URL.RawQuery = queryString.Encode()
response, err := httpClient.Do(request)
if err != nil {
log.Println(err)
}
responseData, err := ioutil.ReadAll(response.Body)
var releasesJson interface{}
err = json.Unmarshal(responseData, &releasesJson)
returnedReleases = releasesJson.(map[string]interface{})
returnedItems = append(returnedItems, returnedReleases["Items"].([]interface{})...)
} else {
break
}
}
return returnedItems
}
func GetProject(octopusURL *url.URL, APIKey string, space *octopusdeploy.Space, projectName string) *octopusdeploy.Project {
// Create client
client := octopusAuth(octopusURL, APIKey, space.ID)
projectsQuery := octopusdeploy.ProjectsQuery {
Name: projectName,
}
// Get specific project object
projects, err := client.Projects.Get(projectsQuery)
if err != nil {
log.Println(err)
}
for _, project := range projects.Items {
if project.Name == projectName {
return project
}
}
return nil
}
func GetEnvironment(octopusURL *url.URL, APIKey string, space *octopusdeploy.Space, environmentName string) *octopusdeploy.Environment {
// Get client for space
client := octopusAuth(octopusURL, APIKey, space.ID)
// Get environment
environmentsQuery := octopusdeploy.EnvironmentsQuery {
Name: environmentName,
}
environments, err := client.Environments.Get(environmentsQuery)
if err != nil {
log.Println(err)
}
// Loop through results
for _, environment := range environments.Items {
if environment.Name == environmentName {
return environment
}
}
return nil
}
func GetDeploymentPreview(octopusURL *url.URL, APIKey string, ReleaseId string, space *octopusdeploy.Space, environment *octopusdeploy.Environment) map[string]interface{} {
// Define api endpoint
deploymentPreviewEndpoint := octopusURL.String() + "/api/" + space.ID + "/releases/" + ReleaseId + "/deployments/preview/" + environment.ID + "?includeDisabledSteps=true"
// Create http client
httpClient := &http.Client{}
// Make request
request, _ := http.NewRequest("GET", deploymentPreviewEndpoint, nil)
request.Header.Set("X-Octopus-ApiKey", APIKey)
response, err := httpClient.Do(request)
if err != nil {
log.Println(err)
}
// Get response
responseData, err := ioutil.ReadAll(response.Body)
var releasesJson interface{}
err = json.Unmarshal(responseData, &releasesJson)
// Map the returned data
returnedPreview := releasesJson.(map[string]interface{})
return returnedPreview
}
Help us continuously improve
Please let us know if you have any feedback about this page.
Page updated on Sunday, January 1, 2023