Files
claude-foundations/platformhub/ocl-syntax.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

277 lines
8.3 KiB
Markdown

# OCL Syntax Reference for Process Templates
## Grammar Rules
OCL (Octopus Configuration Language) follows a strict format. The EBNF grammar is defined at https://github.com/OctopusDeploy/Ocl.
### Core Rules
- **Name, `=`, and value** must be on the same line
- **Block name, labels, and `{`** must be on the same line
- **Closing `}`** must be on its own line (except empty blocks like `value "default" {}`)
- **Strings** use double quotes, cannot contain unescaped `"`
- **Multi-line strings** use heredoc: `<<-EOT` / `EOT`
- **Arrays** use `["item1", "item2"]`
- **Dictionaries** use `{ key = "value" }` (one entry per line inside braces)
### Name Restrictions
Template and step names can only contain: letters, numbers, periods, commas, dashes, underscores, hashes.
**Invalid:** `Run Security Scan (SAST/SCA)` — parentheses and slashes not allowed
**Valid:** `Run Security Scan - SAST and SCA`
## Process Template File Structure
```hcl
name = "Template Display Name"
description = "What this template does"
# Parameters (consumed by projects, referenced in steps)
parameter "param_name" {
display_settings = {
Octopus.ControlType = "SingleLineText"
}
help_text = "Description for UI"
label = "Display Label"
value "default_value" {} # Optional default
}
# Worker pool parameter (REQUIRED — every template needs this)
parameter "worker_pool" {
display_settings = {
Octopus.ControlType = "WorkerPool"
}
help_text = "Worker pool for server-side steps"
label = "Worker Pool"
}
# Steps (executed in order)
step "step-slug" {
name = "Step Display Name"
start_trigger = "StartAfterPrevious" # or "StartWithPrevious"
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 "Hello from #{Octopus.Project.Name}"
EOT
OctopusUseBundledTooling = "False"
}
worker_pool_variable = "worker_pool"
}
}
```
## Parameter Types
| Type | `Octopus.ControlType` | Can Default | Notes |
|------|----------------------|-------------|-------|
| Single-line text | `SingleLineText` | Yes | Most common for string values |
| Multi-line text | `MultiLineText` | Yes | For scripts, YAML, JSON |
| Sensitive | `Sensitive` | Yes | Encrypted in DB |
| Checkbox | `Checkbox` | Yes | Boolean |
| Dropdown | `Select` | Yes | Predefined options |
| Target Tags | `TargetTags` | No | For Kubernetes/deployment targets |
| Worker Pool | `WorkerPool` | No | **Required on every template** |
| Package | (package) | No | Container image references |
| Environments | (environments) | No | |
| Channels | (channels) | No | |
### Default Values
```hcl
# String default
parameter "cloud_target" {
display_settings = { Octopus.ControlType = "SingleLineText" }
help_text = "Cloud provider"
label = "Cloud Target"
value "gcp" {} # Default value in empty block
}
# No default (must be set by consuming project)
parameter "target_tags" {
display_settings = { Octopus.ControlType = "TargetTags" }
help_text = "K8s target tags"
label = "Target Tags"
}
```
## Step Structure
### Inline Script Step (most common in process templates)
```hcl
step "step-slug" {
name = "Display Name"
start_trigger = "StartAfterPrevious"
action {
action_type = "Octopus.Script"
properties = {
Octopus.Action.RunOnServer = "true"
Octopus.Action.Script.ScriptSource = "Inline"
Octopus.Action.Script.Syntax = "PowerShell" # or "Bash"
Octopus.Action.Script.ScriptBody = <<-EOT
# PowerShell script here
$project = $OctopusParameters['Octopus.Project.Name']
Write-Host "Deploying $project"
EOT
OctopusUseBundledTooling = "False"
}
worker_pool_variable = "worker_pool"
}
}
```
### Deployment Target Step (runs on targets, not server)
```hcl
step "deploy-step" {
name = "Deploy to K8s"
start_trigger = "StartAfterPrevious"
properties = {
Octopus.Action.TargetRoles = "#{target_tags}" # References parameter
}
action {
action_type = "Octopus.Script"
properties = {
Octopus.Action.RunOnServer = "false" # Runs on target
Octopus.Action.Script.ScriptSource = "Inline"
Octopus.Action.Script.Syntax = "PowerShell"
Octopus.Action.Script.ScriptBody = <<-EOT
Write-Host "Deploying to target"
EOT
OctopusUseBundledTooling = "False"
}
worker_pool_variable = "worker_pool"
}
}
```
### Kubernetes Raw YAML Step
```hcl
step "k8s-deploy" {
name = "Apply Kubernetes YAML"
properties = {
Octopus.Action.TargetRoles = "#{target_tags}"
}
action {
action_type = "Octopus.KubernetesDeployRawYaml"
properties = {
Octopus.Action.GitRepository.FilePathFilters = "#{{yaml_path}}"
Octopus.Action.GitRepository.Source = "External"
Octopus.Action.Kubernetes.DeploymentTimeout = "180"
Octopus.Action.Kubernetes.ResourceStatusCheck = "True"
Octopus.Action.Kubernetes.ServerSideApply.Enabled = "True"
Octopus.Action.Kubernetes.ServerSideApply.ForceConflicts = "True"
Octopus.Action.KubernetesContainers.Namespace = "#{namespace}"
Octopus.Action.Script.ScriptSource = "GitRepository"
}
worker_pool_variable = "worker_pool"
git_dependencies {
default_branch = "main"
file_path_filters = ["#{yaml_path}"]
git_credential_type = "Anonymous"
repository_uri = "#{repo_url}"
}
}
}
```
## Referencing Variables
### Octopus System Variables
Use `$OctopusParameters['Variable.Name']` in PowerShell scripts:
```powershell
$project = $OctopusParameters['Octopus.Project.Name']
$release = $OctopusParameters['Octopus.Release.Number']
$env = $OctopusParameters['Octopus.Environment.Name']
$channel = $OctopusParameters['Octopus.Release.Channel.Name']
```
### Template Parameters
In OCL properties (outside scripts): `#{parameter_name}`
In PowerShell scripts: `$OctopusParameters['parameter_name']`
```hcl
# In OCL properties
Octopus.Action.TargetRoles = "#{target_tags}"
# In script body
$cloudTarget = $OctopusParameters['cloud_target']
```
**Double-bracing escape:** In some OCL properties, use `#{{param}}` to escape Octopus variable substitution:
```hcl
Octopus.Action.GitRepository.FilePathFilters = "#{{yaml_path}}"
```
### Output Variables
Set output variables from scripts for use in later steps:
```powershell
Write-Host "##octopus[setVariable name='CoveragePercent' value='87']"
```
Read in subsequent steps:
```powershell
$coverage = $OctopusParameters['Octopus.Action[run-unit-tests].Output.CoveragePercent']
```
## Channel Scoping
Scope steps to specific channels (for dual-image patterns):
```hcl
action {
action_type = "Octopus.Script"
channels = ["non-prod"] # Only runs in this channel
properties = { ... }
}
```
## Environment Scoping
```hcl
action {
environments = ["production"] # Only in prod
excluded_environments = ["development"] # Not in dev
}
```
## Step Properties Reference
| Property | Type | Values | Default |
|---|---|---|---|
| `step.condition` | enum | `Success`, `Failure`, `Always`, `Variable` | `Success` |
| `step.start_trigger` | enum | `StartAfterPrevious`, `StartWithPrevious` | `StartAfterPrevious` |
| `step.package_requirement` | enum | `LetOctopusDecide`, `BeforePackageAcquisition`, `AfterPackageAcquisition` | `LetOctopusDecide` |
| `action.channels` | string[] | channel slugs | all |
| `action.environments` | string[] | environment slugs | all |
| `action.excluded_environments` | string[] | environment slugs | none |
| `action.is_disabled` | bool | | `False` |
| `action.is_required` | bool | | `False` |
| `action.notes` | string | step description | |
| `action.worker_pool` | string | worker pool slug | |
| `action.worker_pool_variable` | string | variable name | |
## References
- [OCL Format Specification](https://octopus.com/docs/projects/version-control/ocl-file-format)
- [Config as Code Reference](https://octopus.com/docs/projects/version-control/config-as-code-reference)
- [OCL Grammar (EBNF)](https://github.com/OctopusDeploy/Ocl)