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>
This commit is contained in:
276
platformhub/ocl-syntax.md
Normal file
276
platformhub/ocl-syntax.md
Normal file
@@ -0,0 +1,276 @@
|
||||
# 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)
|
||||
Reference in New Issue
Block a user