Flow
- Last updated on January 19, 2026
- •
- 3-4 minutes to read
A pipeline is a linear sequence of steps. Every step represents a single task, which produces and may consume artifacts. The artifacts that tasks share with each other are temporary.
This sequence ends with the finalize task, which sets the artifacts that will be the pipeline result and removes the temporary artifacts.

Temporary artifacts
The artifacts that the task consumes are specified in inputArtifacts, and those that it produces and puts into artifact storage are outputArtifacts.
The first task of every pipeline does not consume artifacts, since it must get files from either the project, asset storage, or another site. The following tasks come first:
extract-project-designandextract-project-resourceget the project designs or resources.extract-assetsgets an asset from asset storage.download-filesdownloads files from the specified URL.
Temporary artifacts exist only until the end of the pipeline.
Final artifacts
The last task in a pipeline is finalize, in which we specify the resulting artifacts as finalArtifacts. They will be attached to the project. The remaining artifacts will be considered temporary and removed from the artifact storage.
Controlling task execution by condition
You can control whether a task is executed based on conditions. This is useful for creating flexible pipelines where certain tasks should only run if specific criteria are met.
General rules for conditions
- None of these parameters can appear more than once in the parameter dictionary.
- Each task checks if these parameters are set before execution.
- If a parameter is set, the task verifies that its conditions are correctly formatted as
"<left> <operator> <right>". If any condition is malformed, the task ends with an error. - The condition is split into two parts by
<operator>. The supported operators are=and!=. - If a condition contains multiple operators, it is considered malformed.
- The
<left>and<right>parts are compared case-insensitively, and leading/trailing spaces are trimmed. - The
<left>and<right>parts can be empty strings. - Argument interpolation works according to standard rules.
Positive conditions (run logic)
Positive conditions (runIf*) keep the pipeline logic clear and easy to maintain. You can use positive conditions to explicitly define when a task should run:
"runIf": "<left> <operator> <right>"
"runIfAny": ["<left> <operator> <right>", "<left> <operator> <right>", "<left> <operator> <right>"]
"runIfAll": ["<left> <operator> <right>", "<left> <operator> <right>", "<left> <operator> <right>"]
Example: Rendering with mockups
Suppose you want to run a rendering task only if at least one of the following custom project fields is set:
{
"tasks": [
...
{
"description": "Render project with mockups",
"type": "render-with-mockups",
"inputArtifacts": [ ... ],
"parameters": {
"runIfAny": [
"{{project.items.@.fields.render_w_mockup}} = 1",
"{{project.items.@.fields.render_mockup}} = 1"
],
"mockupTemplate": "default-mockup-template.psd",
...
},
"outputArtifacts": [ ... ]
},
...
]
}
In this example:
- The task runs if either
render_w_mockupis1orrender_mockupis1. - If neither condition is met, the task is skipped.
Negative conditions (skip logic)
If you need to skip a task based on conditions, you can use the following parameters:
"skipIf": "<left> <operator> <right>"
"skipIfAny": ["<left> <operator> <right>", "<left> <operator> <right>", "<left> <operator> <right>"]
"skipIfAll": ["<left> <operator> <right>", "<left> <operator> <right>", "<left> <operator> <right>"]
"skipIfNot": "<left> <operator> <right>"
"skipIfNotAny": ["<left> <operator> <right>", "<left> <operator> <right>", "<left> <operator> <right>"]
"skipIfNotAll": ["<left> <operator> <right>", "<left> <operator> <right>", "<left> <operator> <right>"]
Example: Conditional trim operation
Suppose you want to apply a trim operation to artifacts only if the trim custom field is set to true. You can use the skipIf parameter to skip the task if this field is not set:
{
"tasks": [
...
{
"description": "Apply trim operation to artifacts",
"type": "trim-artifacts",
"inputArtifacts": [ ... ],
"parameters": {
"skipIf": "{{project.items.@.fields.trim}} != true",
"trimPattern": "default-trim-pattern.pdf",
...
},
"outputArtifacts": [ ... ]
},
...
]
}
In this example:
- If
{{project.items.@.fields.trim}}is nottrue, the task is skipped. - If
{{project.items.@.fields.trim}}istrue, the task executes and applies the trim operation.
Evaluation rules
Positive conditions (runIf*) are recommended for most scenarios because they make the pipeline logic clearer and easier to maintain. They avoid the complexity of double negatives, which can be confusing when reading or debugging pipelines.
However, negative conditions (skipIf*) are still useful in specific cases:
- When you need to skip a task by default and only run it under exceptional circumstances.
- When integrating with legacy pipelines or scripts that already use
skipIf*logic. - When the condition logic is naturally expressed as an exclusion.
In the next article, you will learn more details about tasks.