New files: - PLATFORMHUB.md: index for Platform Hub guidance - platformhub/architecture.md: Git→PlatformHub→Projects model - platformhub/ocl-syntax.md: complete OCL reference for templates - platformhub/process-template-patterns.md: 5 proven patterns - platformhub/gotchas.md: every error hit and how to fix it - platformhub/api-reference.md: API vs UI capabilities - best-practices/octopus-process-templates.md: consolidated best practices Learned from building PlatformHub-Demo (30 microservices, 3 clouds). Key discoveries: step templates are space-scoped (can't cross-reference), worker_pool parameter is mandatory, publishing/sharing is UI-only. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5.4 KiB
5.4 KiB
Platform Hub API Reference
What can and cannot be managed via the Octopus Deploy API versus the UI.
API-Manageable Resources
These can be created, read, updated, and deleted via the REST API:
| Resource | Endpoint | Notes |
|---|---|---|
| Spaces | POST /api/spaces |
Requires SpaceManagersTeamMembers |
| Environments | POST /api/{SpaceId}/environments |
|
| Lifecycles | POST /api/{SpaceId}/lifecycles |
Include phase definitions |
| Project Groups | POST /api/{SpaceId}/projectgroups |
|
| Docker Feeds | POST /api/{SpaceId}/feeds |
FeedType: "Docker" |
| Step Templates | POST /api/{SpaceId}/actiontemplates |
Space-scoped |
| Projects | POST /api/{SpaceId}/projects |
|
| Channels | POST /api/{SpaceId}/channels |
With lifecycle assignment |
| Releases | POST /api/{SpaceId}/releases |
With channel and package selection |
| Runbooks | POST /api/{SpaceId}/runbooks |
|
| Deployment Processes | GET/PUT /api/{SpaceId}/deploymentprocesses/{id} |
|
| Variables | GET/PUT /api/{SpaceId}/variables/{id} |
UI-Only Operations
These cannot be done via API or CLI — must use the Octopus web UI:
| Operation | Why |
|---|---|
| Publish process template (create version) | Platform Hub feature, no API endpoint |
| Share process template with spaces | Platform Hub feature, no API endpoint |
| Configure Platform Hub Git connection | Instance-level setting |
| Convert project to Config as Code | POST .../git/convert exists but requires Git credentials interactively |
Common API Patterns
Authentication
All API calls require the X-Octopus-ApiKey header:
API_KEY=$(grep 'value:' ~/dev/claude/secrets/taniwha.octopus.app/api_key | awk '{print $2}')
curl -s -H "X-Octopus-ApiKey: $API_KEY" \
"https://taniwha.octopus.app/api/Spaces-103/environments"
Create a Space
curl -s -H "X-Octopus-ApiKey: $API_KEY" \
-H "Content-Type: application/json" \
-X POST "https://taniwha.octopus.app/api/spaces" \
-d '{
"Name": "My Space",
"SpaceManagersTeamMembers": ["Users-21"],
"IsDefault": false
}'
Note: SpaceManagersTeamMembers must not be empty — at least one user or team required.
Create Environments
for env in Development Staging Production; do
curl -s -H "X-Octopus-ApiKey: $API_KEY" \
-H "Content-Type: application/json" \
-X POST "https://taniwha.octopus.app/api/$SPACE_ID/environments" \
-d "{\"Name\": \"$env\"}"
done
Create Lifecycles with Auto-Deploy Phases
# Non-Prod: Dev → Staging (auto-deploy both)
curl -s -H "X-Octopus-ApiKey: $API_KEY" \
-H "Content-Type: application/json" \
-X POST "https://taniwha.octopus.app/api/$SPACE_ID/lifecycles" \
-d '{
"Name": "Non-Prod",
"Phases": [
{
"Name": "Development",
"AutomaticDeploymentTargets": ["Environments-104"],
"OptionalDeploymentTargets": [],
"MinimumEnvironmentsBeforePromotion": 0,
"IsOptionalPhase": false
},
{
"Name": "Staging",
"AutomaticDeploymentTargets": ["Environments-105"],
"OptionalDeploymentTargets": [],
"MinimumEnvironmentsBeforePromotion": 0,
"IsOptionalPhase": false
}
]
}'
Create Docker Feed (GHCR)
curl -s -H "X-Octopus-ApiKey: $API_KEY" \
-H "Content-Type: application/json" \
-X POST "https://taniwha.octopus.app/api/$SPACE_ID/feeds" \
-d '{
"FeedType": "Docker",
"Name": "GHCR Non-Prod",
"FeedUri": "https://ghcr.io"
}'
Create Step Template (Action Template)
curl -s -H "X-Octopus-ApiKey: $API_KEY" \
-H "Content-Type: application/json" \
-X POST "https://taniwha.octopus.app/api/$SPACE_ID/actiontemplates" \
-d '{
"Name": "Run Unit Tests",
"Description": "Language-specific unit test suite",
"ActionType": "Octopus.Script",
"Properties": {
"Octopus.Action.Script.ScriptSource": "Inline",
"Octopus.Action.Script.Syntax": "PowerShell",
"Octopus.Action.Script.ScriptBody": "Write-Host \"Running tests...\""
},
"Parameters": [
{
"Name": "Language",
"Label": "Programming Language",
"DefaultValue": "go",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
}
]
}'
Create Release via API (CI-driven)
curl -s -X POST \
-H "X-Octopus-ApiKey: $API_KEY" \
-H "Content-Type: application/json" \
"https://taniwha.octopus.app/api/$SPACE_ID/releases" \
-d '{
"ProjectId": "Projects-XXX",
"ChannelId": "Channels-XXX",
"Version": "1.2.3+202603251530",
"SelectedPackages": [{
"ActionName": "Deploy Non-Prod Image",
"PackageReferenceName": "service-image",
"Version": "1.2.3+202603251530"
}]
}'
Idempotent Script Pattern
For automation scripts that may be re-run:
# Check if resource exists before creating
existing=$(curl -s -H "X-Octopus-ApiKey: $API_KEY" \
"https://taniwha.octopus.app/api/$SPACE_ID/projectgroups?take=100" \
| python3 -c "
import sys, json
name = sys.argv[1]
for item in json.load(sys.stdin).get('Items', []):
if item['Name'] == name:
print(item['Id'])
break
" "Marketplace" 2>/dev/null || echo "")
if [[ -n "$existing" ]]; then
echo "Already exists: $existing"
else
# Create it
curl -s -X POST ...
fi