> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/step-groups.md).

# Group steps using step groups

Steps can be added to pipelines individually or as a step group.

Individual steps and steps in step groups can be run serially or in parallel.

Unlike individual steps, a step group can apply conditional execution (skip conditions) and a failure strategy to all steps in the group.

You can also run pipeline **stages** in parallel. Deploy multiple services simultaneously and perform flow control using Barriers. Go to [synchronize deployments using barriers](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/flow-control/synchronize-deployments-using-barriers.md) for more information. This topic describes how to add a step group in a stage.

Review the following topics before you add step groups.

* [Kubernetes CD quickstart](/continuous-delivery/use-continuous-delivery/deploy-services-on-different-platforms/kubernetes/kubernetes-cd-quickstart.md)

### Important notes <a href="#important-notes" id="important-notes"></a>

* Currently, Harness supports [step groups](/harness-ai/use-harness-platform/pipelines/use-step-groups.md) in Build, Deploy, and Custom stages only.
* When you run steps in parallel you cannot reference the outputs of one step in another step. The output for one step might not be available when another step requests it.
* Delegate selectors can be configured for each step in the step group. You cannot configure a delegate selector at the group level.

### Containerized step groups <a href="#containerized-step-groups" id="containerized-step-groups"></a>

By default, the tasks performed by Harness CD steps are run on the Harness Delegate host system, for example, the Kubernetes cluster where a Kubernetes delegate is running.

To provide greater control over the resources used for CD steps, Harness also lets you use your own Kubernetes cluster as the runtime infrastructure for CD steps.

You can use a CD step group that points to your cluster as the runtime infrastructure. Next, in the step group, you can add the steps supported by containerized step groups.

{% hint style="info" %}
Containerized step groups cannot have nested step groups, but you can put groups of steps next to each other in a containerized step group:

<img src="/files/x3TvrATicSWIv5PEnu18" alt="" data-size="original">

The steps **in** each group run in parallel but each group runs serially.
{% endhint %}

For more information, go to [Containerize step groups](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/containerized-steps/containerized-step-groups.md).

### Visual summary <a href="#visual-summary" id="visual-summary"></a>

This short video walks through step groups:

{% embed url="<https://www.youtube.com/watch?v=J5eHYSbE8cg>" %}

### Common parallel steps <a href="#common-parallel-steps" id="common-parallel-steps"></a>

Running steps in parallel can be beneficial in many ways, such as:

* Simulating load using multiple [HTTP steps](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/utilities/http-step.md).
* Running multiple [Verify steps](/continuous-delivery/use-continuous-delivery/verify-deployments/verify-deployments-with-the-verify-step.md) for different providers (AppDynamics, Splunk, Prometheus, etc).
* Running independent steps that don't need to be run serially.
* Running multiple Kubernetes [Apply steps](/continuous-delivery/use-continuous-delivery/deploy-services-on-different-platforms/kubernetes/cd-k8s-ref/kubernetes-apply-step.md) to deploy multiple Kubernetes resources at once.
* [Deleting](/continuous-delivery/use-continuous-delivery/deploy-services-on-different-platforms/kubernetes/kubernetes-executions/delete-kubernetes-resources.md) multiple resources at once.
* Creating or updating multiple Jira issues using [Jira Create](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/ticketing-systems/create-jira-issues-in-cd-stages.md) and [Jira Update](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/ticketing-systems/update-jira-issues-in-cd-stages.md) steps.
* Provisioning multiple resources using Terraform. Go to [provision with the Terraform Apply step](/continuous-delivery/use-continuous-delivery/provision-infrastructure/terraform-infra/run-a-terraform-plan-with-the-terraform-apply-step.md) for more details.
* Save time. You might have 5 steps but you can run steps 2 and 3 in parallel because they are independent. Step 4 is run once they have completed.

### Add and name the step group <a href="#add-and-name-the-step-group" id="add-and-name-the-step-group"></a>

In your stage, in **Execution**, select **Add Step** and then select **Step Group**.

![](/files/8t1wMi3RCsr22ZJSXm2B)

The step group setting appear.

Enter a name for the step group.

### Step group variables <a href="#step-group-variables" id="step-group-variables"></a>

Step group variables are custom variables that you can add and refer in your pipeline. They're available across the pipeline.

Variables of type string, secret, or number can be added in step group. Their values can be fixed value, runtime input, or expression.

You can refer step group variables within the step group using the expression, `<+execution.steps.[step group id].variables.[variable name]>`.

You can refer step group variables outside the step group using the expression, `<+pipeline.stages.[stage Id].spec.execution.steps.[step group id].variables.[variable name]>`.

#### Output variables <a href="#output-variables" id="output-variables"></a>

You can reference step group output variables using expressions using the step group name. Here's a sample expression: `<+execution.steps.<stepGroupID>.steps.stepID.outputVariables.[variable name]>`.

If you are accessing the output variable in a step within the same step group you can use a shorter notation, `<+stepGroup.steps.step1Identifier.output.outputVariables.[variable name]>`.

If your step group is configured as a loop, an index is added at the end of the identifier to identify the unique loop instance. You can use this index to reference output variables. For example, `<+execution.steps.<stepGroupID_[index]>.steps.stepID.outputVariables.[variable name]>`.

{% hint style="info" %}
Execution input is not supported for step group variables.
{% endhint %}

### Step group expressions <a href="#step-group-expressions" id="step-group-expressions"></a>

The following expressions are for step groups in pipeline stages.

* `<+stepGroup.variables>`: References a collection of variables within the step group.
* `<+stepGroup.getParentStepGroup>`: References a collection of variables from the parent of the step group.

### Conditional execution <a href="#conditional-execution" id="conditional-execution"></a>

A step group can have its own conditional execution settings separate from the conditional execution settings for the stage. The conditional execution settings of the step group apply to all of its steps.

For more information, go to [Define conditional executions for stages and steps](/harness-ai/use-harness-platform/pipelines/step-skip-condition-settings.md).

The conditional execution settings of any step in a step group overrides the conditional execution settings of the step group.

If you do not use step group conditional execution settings, then the stage's conditional execution settings are used.

### Step group failure strategy <a href="#step-group-failure-strategy" id="step-group-failure-strategy"></a>

A step group can have its own failure strategy separate from the failure strategy for the stage.

The failure strategy can execute the Rollback steps for the step/stage.

Go to [step failure strategy settings](/harness-ai/use-harness-platform/pipelines/failure-handling/define-a-failure-strategy-on-stages-and-steps.md) for more information.

The failure strategy of any step in a step group overrides the Failure Strategy of the step group.

If you do not use a step group failure strategy, then the stage's failure strategy is used.

### Add steps to the step group <a href="#add-steps-to-the-step-group" id="add-steps-to-the-step-group"></a>

Once the step group is added, in its **Execution** section, in the new step group, select **Add Step**.

Add any step and configure its **Advanced** settings.

A step's **Advanced** settings override the **Advanced** settings of the step group.

### Reference step group steps <a href="#reference-step-group-steps" id="reference-step-group-steps"></a>

You reference steps in step groups using the step group Id.

![](/files/RkLw6D9JVbAh0V6yqeBA)

The FQN format is:

`<+pipeline.stages.[stage Id].spec.execution.steps.[step group Id].steps.[step Id].[step setting name]>`

For example, to reference the URL setting in an HTTP step in a step group with the Id `Group1`, the FQN would be:

`<+pipeline.stages.HTTP.spec.execution.steps.Group1.steps.OPTIONS.spec.url>`

### Override service variables in step groups <a href="#override-service-variables-in-step-groups" id="override-service-variables-in-step-groups"></a>

You can customize and override service variables during the execution of a step group. This provides significant flexibility and control over your pipelines. The expression `<+serviceVariableOverrides.VARIABLE_NAME>`overrides the original value of `VARIABLE_NAME`. You can use this expression in values YAML files and other parts of the pipeline where variables are used.

{% hint style="info" %}
**IMPORTANT NOTES**

* An overridden value is available only within the scope of the step group execution. In cases where a child group is included in a parent group, the child group override takes precedence.

  The pipeline overrides variables based on the following priority:

  1. Step group override (child group, during execution)
  2. Step group override (parent group, during execution)
  3. Service environment overrides
  4. Environment configuration
  5. Service variable value (default)
* Step group overrides are not recommended for artifacts and other objects fetched in the **Service** section of a pipeline stage. The one exception is scripts in [custom remote manifests](/continuous-delivery/use-continuous-delivery/deploy-services-on-different-platforms/kubernetes/cd-kubernetes-category/add-a-custom-remote-script-and-manifests.md), because they can also be used during the **Execution** section of a pipeline stage.
  {% endhint %}

<details>

<summary>Pipeline example: overriding variables in step groups</summary>

The following pipeline illustrates how to override service variables. The service definition has two defined variables, `svar1` and `svar2`. The pipeline overrides these variables as follows:

* The `parent` step group overrides `svar1` with the value `fromStepGroup_OverriddenAtParentStepGroup`.
* The `parent` step group also has a variable `svarParent` with the value `DefinedAtParentLevel`. The `child` step group overrides this with the value `OverridenByChildStepGroup`.
* The `child` step group overrides `svar2` with the value `fromStepGroup_OverriddenAtChildLevel`.

<figure><img src="/files/qKteMN6HMIyWDNxwjUhT" alt=""><figcaption><p>Overriding service variables in a pipeline - example</p></figcaption></figure>

```yaml
pipeline:
  projectIdentifier: svcredesignhinger
  orgIdentifier: harness
  tags: {}
  stages:
    - stage:
        name: dep
        identifier: dep
        description: ""
        type: Deployment
        spec:
          deploymentType: Kubernetes
          service:
            serviceRef: TestStepGroupOverridesService
          environment:
            environmentRef: qa
            environmentInputs:
              identifier: qa
              type: PreProduction
              variables:
                - name: rtvar1123
                  type: String
                  value: <+input>
            deployToAll: false
            infrastructureDefinitions:
              - identifier: delegateInfra2
          execution:
            steps:
              - stepGroup:
                  name: parent
                  identifier: parent
                  steps:
                    - step:
                        type: ShellScript
                        name: ShellScript_2
                        identifier: ShellScript_2
                        spec:
                          shell: Bash
                          onDelegate: true
                          source:
                            type: Inline
                            spec:
                              script: echo <+serviceVariableOverrides.svarParent>
                          environmentVariables: []
                          outputVariables: []
                        timeout: 10m
                    - stepGroup:
                        name: child
                        identifier: child
                        steps:
                          - step:
                              type: ShellScript
                              name: ShellScript_1
                              identifier: ShellScript_1
                              spec:
                                shell: Bash
                                onDelegate: true
                                source:
                                  type: Inline
                                  spec:
                                    script: |+
                                      echo <+serviceVariableOverrides.svar1>
                                      echo <+serviceVariableOverrides.svar2>

                                      echo "child overriding parent value"
                                      echo <+serviceVariableOverrides.svarParent>

                                environmentVariables: []
                                outputVariables: []
                              timeout: 10m
                        variables:
                          - name: svar2
                            type: String
                            value: fromStepGroup_OverriddenAtChildLevel
                            description: ""
                            required: false
                          - name: svarParent
                            type: String
                            value: OverridenByChildStepGroup
                            description: ""
                            required: false
                  variables:
                    - name: svar1
                      type: String
                      value: fromStepGroup_OverriddenAtParentStepGroup
                      description: ""
                      required: false
                    - name: svarParent
                      type: String
                      value: DefinedAtParentLevel
                      description: ""
                      required: false
            rollbackSteps: []
        tags: {}
        failureStrategies:
          - onFailure:
              errors:
                - AllErrors
              action:
                type: StageRollback
  identifier: StepGroupLevelOverrides
  name: StepGroupLevelOverrides
```

</details>
