Files
claude-foundations/platformhub/gotchas.md
Paul O'Reilly 6c0f2db169 Add Octopus Deploy Platform Hub knowledge base
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>
2026-03-25 09:54:09 +13:00

5.2 KiB

Platform Hub Gotchas and Troubleshooting

Every error encountered while building the PlatformHub-Demo project, and how to fix it.

OCL Parse Errors

"Action Template with ID 'ActionTemplates-XX' and version v0 specified in OCL was not found"

Cause: Process template references a step template (ActionTemplate) by ID, but step templates are space-scoped. Platform Hub operates at instance level and can't see step templates in individual spaces.

Fix: Don't reference step templates in process template OCL. Use inline action_type definitions instead:

# WRONG — cross-space reference
action {
    properties = {
        Octopus.Action.Template.Id = "ActionTemplates-64"
        Octopus.Action.Template.Version = "0"
    }
}

# RIGHT — inline action
action {
    action_type = "Octopus.Script"
    properties = {
        Octopus.Action.RunOnServer = "true"
        Octopus.Action.Script.ScriptSource = "Inline"
        Octopus.Action.Script.Syntax = "PowerShell"
        Octopus.Action.Script.ScriptBody = <<-EOT
Write-Host "Inline script here"
EOT
        OctopusUseBundledTooling = "False"
    }
    worker_pool_variable = "worker_pool"
}

"A step must specify a worker pool parameter"

Cause: Every step in a process template must have a worker pool, either directly or via a variable. The template itself must define a WorkerPool parameter.

Fix: Add a worker_pool parameter to the template and reference it from every action:

# Add this parameter to the template
parameter "worker_pool" {
    display_settings = {
        Octopus.ControlType = "WorkerPool"
    }
    help_text = "Worker pool for server-side steps"
    label = "Worker Pool"
}

# On EVERY action (both RunOnServer=true and RunOnServer=false):
action {
    action_type = "Octopus.Script"
    properties = { ... }
    worker_pool_variable = "worker_pool"    # Must reference the parameter
}

Note: worker_pool_variable = "" (empty string) will NOT work. It must reference an actual parameter name.

"Name value contains invalid characters"

Cause: Template or step names contain characters outside the allowed set.

Allowed: Letters, numbers, periods, commas, dashes, underscores, hashes Not allowed: Parentheses (), slashes /, ampersands &, colons :, at-signs @

# WRONG
name = "Run Security Scan (SAST/SCA)"

# RIGHT
name = "Run Security Scan - SAST and SCA"

API and Scripting Issues

Step template names created as numbers instead of text

Cause: The bash variable GROUPS is pre-set by bash completion scripts (contains numeric group IDs). Assigning to GROUPS in a script that sources other files will silently use the pre-existing value.

Fix: Use a unique variable name that won't collide with shell builtins or completion scripts:

# WRONG — GROUPS may already be set by bash completion
GROUPS=("Marketplace" "Payments" "Orders")

# RIGHT — use a unique name
PROJECT_GROUPS=("Marketplace" "Payments" "Orders")

Action template (step template) creation: HTTP 400 with name errors

Cause: Same name restriction as process templates. The API enforces the same character rules.

Octopus API POST with nested command substitution loses values

Cause: Nested $(...) in bash can mangle variable expansion. Avoid constructing JSON inside $(octopus_post "/endpoint" "$(python3 ...)").

Fix: Build the JSON body in a separate variable first:

# WRONG — nested substitution
response=$(octopus_post "/projectgroups" "$(python3 -c "..." "$name")")

# RIGHT — build body first
body="{\"Name\": \"$name\"}"
response=$(octopus_post "/projectgroups" "$body")

Publishing and Sharing

Templates visible in Platform Hub but not in project spaces

Cause: Templates must be explicitly published (versioned) and shared with target spaces. Both operations are UI-only — there is no API or CLI for this.

Fix: For each template:

  1. Go to Platform Hub in the Octopus UI
  2. Click the template → Publish (creates a version)
  3. Click Share → select target spaces → Save

Template changes not reflected in consuming projects

Cause: Template versioning. Changes in Git are picked up by Platform Hub but won't affect projects until a new version is published. Projects with version_mask = "1.X" will auto-update on minor/patch publications.

OCL Syntax Specifics

Heredoc for multi-line scripts

PowerShell scripts with double quotes need heredoc syntax:

Octopus.Action.Script.ScriptBody = <<-EOT
$name = $OctopusParameters['Octopus.Project.Name']
Write-Host "Deploying $name"
EOT

The <<-EOT variant (with dash) allows the closing EOT to be indented. Without the dash, EOT must be at column 0.

Parameter references: single vs double braces

  • #{param_name} — standard Octopus variable substitution (most properties)
  • #{{param_name}} — escaped substitution (used in some properties like GitRepository.FilePathFilters)

PowerShell variable access in scripts

Inside script bodies, use $OctopusParameters['Variable.Name'], not #{Variable.Name}:

# In script body:
$project = $OctopusParameters['Octopus.Project.Name']
$cloud = $OctopusParameters['cloud_target']

# NOT this (only works in OCL properties, not script text):
# #{Octopus.Project.Name}