Convert Harness v0 expressions to v1 format. Useful for converting individual expressions outside of a full pipeline conversion, or for understanding how specific expressions transform.
POST /api/v1/convert/expression
Default HTTP port: 8092
{
"expression": "<+pipeline.stages.build.spec.execution.steps.step1.output>",
"context": {
"current_step_id": "step1",
"current_step_type": "Run",
"current_step_v1_path": "pipeline.stages.build.steps.step1",
"step_type_map": {
"step1": "Run",
"step2": "Action"
},
"step_v1_path_map": {
"step1": "pipeline.stages.build.steps.step1",
"step2": "pipeline.stages.build.steps.step2"
},
"use_fqn": true
}
}| Field | Type | Required | Description |
|---|---|---|---|
expression |
string | One of expression or expressions required |
A single v0 expression to convert |
expressions |
string[] | One of expression or expressions required |
Multiple v0 expressions to convert |
context |
object | Optional | Context for context-aware conversion |
| Field | Type | Description |
|---|---|---|
current_step_id |
string | ID of the current step (when converting expressions inside a step) |
current_step_type |
string | Type of the current step (e.g., "Run", "Action", "Plugin") |
current_step_v1_path |
string | V1 FQN base path to the current step |
step_type_map |
map[string]string | Maps step IDs to their types for all steps in the pipeline |
step_v1_path_map |
map[string]string | Maps step IDs to their v1 FQN base paths |
use_fqn |
boolean | Enable FQN mode for step expressions |
{
"expression": "<+pipeline.stages.build.steps.step1.output>",
"checksum": "sha256:abc123..."
}{
"expressions": {
"<+pipeline.stages.build.spec.execution.steps.step1.output>": "<+pipeline.stages.build.steps.step1.output>",
"<+stage.spec.execution.steps.step2.output>": "<+stage.steps.step2.output>"
},
"checksum": "sha256:def456..."
}Convert a simple expression without context:
curl -X POST http://localhost:8092/api/v1/convert/expression \
-H "Content-Type: application/json" \
-d '{
"expression": "<+pipeline.stages.build.spec.execution.steps.step1.output>"
}'Response:
{
"expression": "<+pipeline.stages.build.steps.step1.output>",
"checksum": "sha256:abc123..."
}Convert a step-relative expression with step type context:
curl -X POST http://localhost:8092/api/v1/convert/expression \
-H "Content-Type: application/json" \
-d '{
"expression": "<+step.spec.command>",
"context": {
"current_step_type": "Run"
}
}'Response:
{
"expression": "<+step.spec.script>",
"checksum": "sha256:abc123"
}Convert to fully qualified names when use_fqn is enabled:
curl -X POST http://localhost:8092/api/v1/convert/expression \
-H "Content-Type: application/json" \
-d '{
"expression": "<+step.spec.command>",
"context": {
"current_step_type": "Run",
"current_step_v1_path": "pipeline.stages.build.steps.runStep1",
"use_fqn": true
}
}'Response:
{
"expression": "<+pipeline.stages.build.steps.runStep1.spec.script>",
"checksum": "sha256:abc123"
}Convert multiple expressions at once:
curl -X POST http://localhost:8092/api/v1/convert/expression \
-H "Content-Type: application/json" \
-d '{
"expressions": [
"<+pipeline.stages.build.spec.execution.steps.step1.output>",
"<+stage.spec.execution.steps.step2.output>",
"<+pipeline.variables.myVar>"
]
}'Response:
{
"expressions": {
"<+pipeline.stages.build.spec.execution.steps.step1.output>": "<+pipeline.stages.build.steps.step1.output>",
"<+stage.spec.execution.steps.step2.output>": "<+stage.steps.step2.output>",
"<+pipeline.variables.myVar>": "<+pipeline.variables.myVar>"
},
"checksum": "sha256:abc123"
}When converting expressions that reference other steps (using steps.STEPID):
curl -X POST http://localhost:8092/api/v1/convert/expression \
-H "Content-Type: application/json" \
-d '{
"expression": "<+steps.otherStep.spec.command>",
"context": {
"current_step_id": "currentStep",
"current_step_type": "Run",
"current_step_v1_path": "pipeline.stages.build.steps.currentStep",
"step_type_map": {
"currentStep": "Run",
"otherStep": "Run"
},
"step_v1_path_map": {
"currentStep": "pipeline.stages.build.steps.currentStep",
"otherStep": "pipeline.stages.build.steps.otherStep"
},
"use_fqn": true
}
}'| V0 Expression | V1 Expression | Notes |
|---|---|---|
<+pipeline.stages.STAGE.spec.execution.steps.STEP.*> |
<+pipeline.stages.STAGE.steps.STEP.*> |
Removes spec.execution |
<+stage.spec.execution.steps.STEP.*> |
<+stage.steps.STEP.*> |
Removes spec.execution |
<+pipeline.stages.STAGE.spec.execution.rollbackSteps.STEP.*> |
<+pipeline.stages.STAGE.rollback.STEP.*> |
Rollback steps |
| V0 Expression | V1 Expression | Step Type |
|---|---|---|
<+step.spec.command> |
<+step.spec.script> |
Run |
<+step.spec.image> |
<+step.spec.container.image> |
Run |
<+step.spec.shell> |
<+step.spec.shell> |
Run |
<+step.spec.envVariables.X> |
<+step.spec.env.X> |
Run |
Use the expression conversion directly in Go code:
package main
import (
"fmt"
"github.com/drone/go-convert/service/converter"
)
func main() {
// Simple conversion without context
result := converter.ConvertExpression(
"<+pipeline.stages.build.spec.execution.steps.step1.output>",
nil,
)
fmt.Println(result) // <+pipeline.stages.build.steps.step1.output>
// Context-aware conversion (relative)
ctx := &converter.ExpressionContext{
CurrentStepType: "Run",
}
result = converter.ConvertExpression("<+step.spec.command>", ctx)
fmt.Println(result) // <+step.spec.script>
// Context-aware conversion (FQN mode)
ctx = &converter.ExpressionContext{
CurrentStepType: "Run",
CurrentStepV1Path: "pipeline.stages.build.steps.runStep1",
UseFQN: true,
}
result = converter.ConvertExpression("<+step.spec.command>", ctx)
fmt.Println(result) // <+pipeline.stages.build.steps.runStep1.spec.script>
// Batch conversion
expressions := []string{
"<+pipeline.variables.myVar>",
"<+stage.spec.execution.steps.step1.output>",
}
results := converter.ConvertExpressions(expressions, nil)
for orig, converted := range results {
fmt.Printf("%s -> %s\n", orig, converted)
}
}{
"code": "MISSING_FIELD",
"message": "either 'expression' or 'expressions' field is required"
}{
"code": "INVALID_JSON",
"message": "unexpected EOF"
}-
Context is optional: Basic path conversions work without context (e.g.,
spec.execution.steps→steps). Context is only needed for step-type-specific field conversions. -
Step type resolution: For step-specific field conversions (like
spec.command→spec.scriptfor Run steps), provide:current_step_type— for expressions starting withstep.step_type_map— for expressions referencing other steps viasteps.STEPID
-
FQN mode: When
use_fqn: true:- Relative expressions (
step.spec.X) become fully qualified (pipeline.stages.STAGE.steps.STEP.spec.X) - Requires
current_step_v1_pathfor the current step - Requires
step_v1_path_mapfor cross-step references
- Relative expressions (
-
Non-expression strings: Input without
<+markers is returned unchanged.