---
title: Designing Workflow Steps
slug: /platform-engineers/workflow/workflow
---
## Overview
`Workflow` allows you to customize steps in `Application`, glue together additional delivery processes and specify arbitrary delivery environments. In short, `Workflow` provides customized control flow and flexibility based on the original delivery model of Kubernetes(Apply). For example, `Workflow` can be used to implement complex operations such as pause, manual approval, waiting status, data flow, multi-environment gray release, A/B testing, etc.
`Workflow` is a further exploration and best practice based on OAM model in KubeVela, it obeys the modular concept and reusable characteristics of OAM. Each workflow module is a "super glue" that can combine your arbitrary tools and processes. In modern complex cloud native application delivery environment, you can completely describe all delivery processes through a declarative configuration, ensuring the stability and convenience of the delivery process.
## Using workflow
`Workflow` consists of steps, you can either use KubeVela's [built-in workflow steps], or write their own `WorkflowStepDefinition` to complete the operation.
We can use `vela def` to define workflow steps by writing `Cue templates`. Let's write an `Application` that apply a Tomcat using Helm chart and automatically send message to Slack when the Tomcat is running.
### Workflow Steps
KubeVela provides several CUE actions for writing workflow steps. These actions are provided by the `vela/op` package. In order to achieve the above scenario, we need to use the following three CUE actions:
| Action | Description | Parameter |
| :---: | :--: | :-- |
| [ApplyApplication](./cue-actions#apply) | Apply all the resources in Application. | - |
| [Read](./cue-actions#read) | Read resources in Kubernetes cluster. | value: the resource metadata to be get. And after successful execution, `value` will be updated with resource definition in cluster.
err: if an error occurs, the `err` will contain the error message. |
| [ConditionalWait](./cue-actions#conditionalwait) | The workflow step will be blocked until the condition is met. | continue: The workflow step will be blocked until the value becomes `true`. |
> For all the workflow actions, please refer to [Cue Actions](./cue-actions)
After this, we need two `WorkflowStepDefinitions` to complete the Application:
1. Apply Tomcat and wait till it's status become running. We need to write a custom workflow step for it.
2. Send Slack notifications, we can use the built-in [webhook-notification] step for it.
#### Step: Apply Tomcat
First, use `vela def init` to generate a `WorkflowStepDefinition` template:
```shell
vela def init my-helm -t workflow-step --desc "Apply helm charts and wait till it's running." -o my-helm.cue
```
The result is as follows:
```shell
$ cat my-helm.cue
"my-helm": {
annotations: {}
attributes: {}
description: "Apply helm charts and wait till it's running."
labels: {}
type: "workflow-step"
}
template: {
}
```
Import `vela/op` and complete the Cue code in `template`:
```
import (
"vela/op"
)
"my-helm": {
annotations: {}
attributes: {}
description: "Apply helm charts and wait till it's running."
labels: {}
type: "workflow-step"
}
template: {
// Apply all the resources in Application
apply: op.#ApplyApplication & {}
resource: op.#Read & {
value: {
kind: "Deployment"
apiVersion: "apps/v1"
metadata: {
name: "tomcat"
// we can use context to get any metadata in Application
namespace: context.namespace
}
}
}
workload: resource.value
// wait till it's ready
wait: op.#ConditionalWait & {
continue: workload.status.readyReplicas == workload.status.replicas && workload.status.observedGeneration == workload.metadata.generation
}
}
```
Apply it to the cluster:
```shell
$ vela def apply my-helm.cue
WorkflowStepDefinition my-helm in namespace vela-system updated.
```
#### Step: Send Slack notifications
Use the built-in step, [webhook-notification].
### Apply the Application
```yaml
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: first-vela-workflow
namespace: default
spec:
components:
- name: tomcat
type: helm
properties:
repoType: helm
url: https://charts.bitnami.com/bitnami
chart: tomcat
version: "9.2.20"
workflow:
steps:
- name: tomcat
# specify the step type
type: my-helm
outputs:
- name: msg
# get value from the deployment status in my-helm
valueFrom: resource.value.status.conditions[0].message
- name: send-message
type: webhook-notification
inputs:
- from: msg
# use the output value in the previous step and pass it into the properties slack.message.text
parameterKey: slack.message.text
properties:
slack:
# the address of your slack webhook, please refer to: https://api.slack.com/messaging/webhooks
url:
```
Apply the Application to the cluster and you can see that all resources have been successfully applied and Slack has received the messages of the Deployment status.