| name | managing-octopus-deploy |
| description | Use when working with Octopus Deploy — octopus Deploy management for
deployment automation. Covers deployment projects, environments, variable
sets, tenant configuration, release management, and runbook execution. Use
when checking deployment status, investigating release failures, managing
environments, or auditing Octopus Deploy configurations.
|
| connection_type | octopus-deploy |
| preload | false |
Octopus Deploy Management Skill
Manage and monitor Octopus Deploy projects, environments, releases, and tenants.
Core Helper Functions
#!/bin/bash
octopus_api() {
local method="${1:-GET}"
local endpoint="$2"
local data="${3:-}"
if [ -n "$data" ]; then
curl -s -X "$method" \
-H "X-Octopus-ApiKey: ${OCTOPUS_API_KEY}" \
-H "Content-Type: application/json" \
"${OCTOPUS_URL}/api/${OCTOPUS_SPACE_ID:-Spaces-1}/${endpoint}" \
-d "$data"
else
curl -s -X "$method" \
-H "X-Octopus-ApiKey: ${OCTOPUS_API_KEY}" \
"${OCTOPUS_URL}/api/${OCTOPUS_SPACE_ID:-Spaces-1}/${endpoint}"
fi
}
octopus_server_api() {
curl -s -X "${1:-GET}" \
-H "X-Octopus-ApiKey: ${OCTOPUS_API_KEY}" \
"${OCTOPUS_URL}/api/${2}"
}
MANDATORY: Discovery-First Pattern
Always discover spaces, projects, and environments before querying specifics.
Phase 1: Discovery
#!/bin/bash
echo "=== Server Info ==="
octopus_server_api GET "serverstatus" | jq '{version: .Version, isInMaintenanceMode: .IsInMaintenanceMode}'
echo ""
echo "=== Spaces ==="
octopus_server_api GET "spaces?take=20" | jq -r '
.Items[] | "\(.Id)\t\(.Name)\tdefault=\(.IsDefault)"
' | column -t
echo ""
echo "=== Projects ==="
octopus_api GET "projects?take=20" | jq -r '
.Items[] | "\(.Id)\t\(.Name)\tgroup=\(.ProjectGroupId)\tdisabled=\(.IsDisabled)"
' | column -t
echo ""
echo "=== Environments ==="
octopus_api GET "environments?take=20" | jq -r '
.Items[] | "\(.Id)\t\(.Name)\tsortOrder=\(.SortOrder)"
' | column -t
echo ""
echo "=== Recent Deployments ==="
octopus_api GET "deployments?take=10" | jq -r '
.Items[] | "\(.Id)\t\(.ProjectId)\t\(.EnvironmentId)\t\(.State)\t\(.Created[0:16])"
' | column -t
Output Rules
- TOKEN EFFICIENCY: Target 50 lines per output
- Use
take and skip parameters for pagination
- Never dump full deployment process — extract step summaries
Common Operations
Deployment Dashboard
#!/bin/bash
echo "=== Dashboard ==="
octopus_api GET "dashboard" | jq '{
environments: [.Environments[] | .Name],
projects: (.Items | group_by(.ProjectId) | map({
project: .[0].ProjectId,
deployments: [.[] | {env: .EnvironmentId, state: .State, version: .ReleaseVersion}]
}) | .[:10])
}'
echo ""
echo "=== Recent Deployments (detailed) ==="
octopus_api GET "deployments?take=15" | jq -r '
.Items[] |
"\(.Name // .Id)\t\(.State)\t\(.TaskId)\t\(.Created[0:16])"
' | column -t
echo ""
echo "=== Failed Deployments ==="
octopus_api GET "tasks?states=Failed&take=10&name=Deploy" | jq -r '
.Items[] |
"\(.Description[0:50])\t\(.State)\t\(.CompletedTime[0:16] // "unknown")\t\(.ErrorMessage[0:60] // "")"
' | column -t
Project Management
#!/bin/bash
PROJECT_ID="${1:?Project ID or slug required}"
echo "=== Project Details ==="
octopus_api GET "projects/${PROJECT_ID}" | jq '{
Id, Name, Slug,
LifecycleId, ProjectGroupId,
IsDisabled, TenantedDeploymentMode,
IncludedLibraryVariableSetIds: (.IncludedLibraryVariableSetIds | length),
DeploymentProcessId: .DeploymentProcessId
}'
echo ""
echo "=== Deployment Process ==="
PROCESS_ID=$(octopus_api GET "projects/${PROJECT_ID}" | jq -r '.DeploymentProcessId')
octopus_api GET "deploymentprocesses/${PROCESS_ID}" | jq -r '
.Steps[] | "\(.Name)\troles=\(.Properties["Octopus.Action.TargetRoles"] // "any")\tactions=\([.Actions[].Name] | join(","))"
' | column -t
echo ""
echo "=== Recent Releases ==="
octopus_api GET "projects/${PROJECT_ID}/releases?take=10" | jq -r '
.Items[] | "\(.Id)\tv\(.Version)\t\(.Assembled[0:16])\tchannel=\(.ChannelId)"
' | column -t
Environment Management
#!/bin/bash
echo "=== Environment Details ==="
octopus_api GET "environments?take=20" | jq -r '
.Items[] | "\(.Id)\t\(.Name)\tsort=\(.SortOrder)\tguided=\(.UseGuidedFailure)"
' | column -t
echo ""
echo "=== Machines by Environment ==="
octopus_api GET "environments" | jq -r '.Items[].Id' | while read env_id; do
ENV_NAME=$(octopus_api GET "environments/${env_id}" | jq -r '.Name')
MACHINES=$(octopus_api GET "environments/${env_id}/machines?take=100" | jq '.TotalResults')
echo "${env_id}\t${ENV_NAME}\t${MACHINES} machines"
done | column -t
echo ""
echo "=== Deployment Targets ==="
octopus_api GET "machines?take=20" | jq -r '
.Items[] | "\(.Name)\tstatus=\(.HealthStatus)\troles=\(.Roles | join(","))\tenvs=\(.EnvironmentIds | length)"
' | column -t
Variable Sets
#!/bin/bash
PROJECT_ID="${1:?Project ID required}"
echo "=== Project Variables ==="
octopus_api GET "variables/variableset-${PROJECT_ID}" | jq -r '
.Variables[] | "\(.Name)\tscope=\(.Scope | to_entries | map("\(.key)=\(.value | length)") | join(",") // "all")\ttype=\(.Type // "String")\tsensitive=\(.IsSensitive)"
' | column -t | head -25
echo ""
echo "=== Library Variable Sets ==="
octopus_api GET "libraryvariablesets?take=20" | jq -r '
.Items[] | "\(.Id)\t\(.Name)\tvariables=\(.Variables // 0)\tdescription=\(.Description[0:40] // "")"
' | column -t
Tenant Management
#!/bin/bash
echo "=== Tenants ==="
octopus_api GET "tenants?take=20" | jq -r '
.Items[] | "\(.Id)\t\(.Name)\tprojects=\(.ProjectEnvironments | keys | length)\ttags=\(.TenantTags | join(","))"
' | column -t
echo ""
echo "=== Tenant Details ==="
TENANT_ID="${1:-}"
if [ -n "$TENANT_ID" ]; then
octopus_api GET "tenants/${TENANT_ID}" | jq '{
Id, Name,
TenantTags,
ProjectEnvironments: (.ProjectEnvironments | to_entries | map({project: .key, environments: .value}))
}'
fi
Runbook Execution
#!/bin/bash
PROJECT_ID="${1:?Project ID required}"
echo "=== Runbooks ==="
octopus_api GET "projects/${PROJECT_ID}/runbooks?take=20" | jq -r '
.Items[] | "\(.Id)\t\(.Name)\t\(.Description[0:40] // "")"
' | column -t
echo ""
echo "=== Recent Runbook Runs ==="
octopus_api GET "tasks?name=RunbookRun&take=10" | jq -r '
.Items[] | "\(.Description[0:50])\t\(.State)\t\(.CompletedTime[0:16] // "running")"
' | column -t
Release & Deployment
#!/bin/bash
PROJECT_ID="${1:?Project ID required}"
RELEASE_VERSION="${2:-}"
if [ -n "$RELEASE_VERSION" ]; then
echo "=== Release Details ==="
octopus_api GET "projects/${PROJECT_ID}/releases/${RELEASE_VERSION}" | jq '{
Id, Version, Assembled, ChannelId,
SelectedPackages: [.SelectedPackages[] | {ActionName, Version: .Version}]
}'
echo ""
echo "=== Deployment History for Release ==="
RELEASE_ID=$(octopus_api GET "projects/${PROJECT_ID}/releases/${RELEASE_VERSION}" | jq -r '.Id')
octopus_api GET "releases/${RELEASE_ID}/deployments?take=10" | jq -r '
.Items[] | "\(.EnvironmentId)\t\(.State)\t\(.Created[0:16])\ttask=\(.TaskId)"
' | column -t
else
echo "=== Latest Releases ==="
octopus_api GET "projects/${PROJECT_ID}/releases?take=10" | jq -r '
.Items[] | "v\(.Version)\t\(.Assembled[0:16])\tchannel=\(.ChannelId)"
' | column -t
fi
Anti-Hallucination Rules
- NEVER guess project IDs — always discover via API first (format is
Projects-123)
- NEVER fabricate environment or tenant IDs — use discovery endpoints
- NEVER assume Space ID — default is
Spaces-1 but verify
- Octopus uses hyphenated IDs (e.g.,
Environments-1, Tenants-5) — do not use names as IDs
Safety Rules
- NEVER create deployments without explicit user confirmation
- NEVER delete projects, environments, or tenants without user approval
- NEVER modify variable sets without understanding scope impact
- NEVER expose sensitive variable values — API masks them by default
- NEVER run runbooks without confirming the target environment
Output Format
Present results as a structured report:
Managing Octopus Deploy Report
══════════════════════════════
Resources discovered: [count]
Resource Status Key Metric Issues
──────────────────────────────────────────────
[name] [ok/warn] [value] [findings]
Summary: [total] resources | [ok] healthy | [warn] warnings | [crit] critical
Action Items: [list of prioritized findings]
Target ≤50 lines of output. Use tables for multi-resource comparisons.
Counter-Rationalizations
| Shortcut | Counter | Why |
|---|
| "I'll skip discovery and check known resources" | Always run Phase 1 discovery first | Resource names change, new resources appear — assumed names cause errors |
| "The user only asked for a quick check" | Follow the full discovery → analysis flow | Quick checks miss critical issues; structured analysis catches silent failures |
| "Default configuration is probably fine" | Audit configuration explicitly | Defaults often leave logging, security, and optimization features disabled |
| "Metrics aren't needed for this" | Always check relevant metrics when available | API/CLI responses show current state; metrics reveal trends and intermittent issues |
| "I don't have access to that" | Try the command and report the actual error | Assumed permission failures prevent useful investigation; actual errors are informative |
Common Pitfalls
- Space scoping: All resources are scoped to a Space — include Space ID in API path
- ID format: Octopus uses
Type-Number format (e.g., Projects-42) — not slugs or names
- Lifecycle phases: Environments follow lifecycle ordering — deployments must follow the defined progression
- Tenanted deployments: Tenanted projects require tenant selection for deployment — untenanted and tenanted are separate modes
- Variable scoping: Variables can be scoped to environments, roles, machines, channels — scope conflicts cause unexpected behavior
- Guided failure: Environments with guided failure enabled pause on failure for manual intervention
- Channels: Channels control which packages and lifecycles apply to a release — check channel rules