> 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/cd-steps-faqs.md).

# CD Steps FAQs

Answers to common questions about Continuous Delivery steps and step groups

This topic answers common questions about Continuous Delivery (CD) steps and step groups. Go to [Steps](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps.md) to browse the step topics.

***

## Container steps

<details>

<summary>Why are step group variables not accessible between steps when a Container step uses the stepGroup expression?</summary>

The Container step creates its step group, with the Init and Run steps, during pipeline execution. It creates that step group because the Init step creates a build pod with containers.

The `<+stepGroup>` expression in the Container step script refers to that inner step group, not the outer Deployment Dry Run group. You cannot use `<+stepGroup>` in the Container step to read steps from the outer step group.

Use these expressions to get the Deployment Dry Run step identifier or name in the Container step.

Get the Deployment Dry Run step identifier:

```
<+execution.steps.kubernetes_compliance_check1.steps.k8s_dry_run.identifier>
```

or:

```
<+pipeline.stages.Test_Policy.spec.execution.steps.kubernetes_compliance_check1.steps.k8s_dry_run.identifier>
```

Get the Deployment Dry Run step name:

```
<+execution.steps.kubernetes_compliance_check1.steps.k8s_dry_run.name>
```

or:

```
<+pipeline.stages.Test_Policy.spec.execution.steps.kubernetes_compliance_check1.steps.k8s_dry_run.name>
```

</details>

<details>

<summary>Does the Container step override the entry point when you use the command input?</summary>

Yes. Harness overwrites the entry point in the base image so it can run the commands specified in the Run step.

</details>

<details>

<summary>Is there an alternative to the Container step in Continuous Delivery?</summary>

Yes. Use a containerized step group and a Run step. Go to [Add a containerized step group](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/containerized-steps/containerized-step-groups.md#add-a-containerized-step-group) to add one.

</details>

<details>

<summary>Does Harness support a distroless image in the container Run step?</summary>

No. Harness does not support distroless images yet. Support for distroless images is planned.

</details>

***

## Command step

<details>

<summary>What is the Command step?</summary>

The Command step runs commands on target hosts in SSH and WinRM deployments, and in deployment templates. You can use it for tasks such as these:

* Running scripts on all target hosts.
* Downloading the deployment artifact.
* Copying the artifact or configuration files.

</details>

<details>

<summary>How do you loop the Command step on all target hosts?</summary>

Use the Repeat looping strategy with the expression `stage.output.hosts` after the Fetch Instances step for deployment templates. The commands then run on each host returned by the Fetch Instances step.

</details>

<details>

<summary>Is there a way to pass output variables between commands within a Command step?</summary>

No. Output variables can be passed between steps or stages, not within a single Command step. Go to [Chained pipeline output variables](https://developer.harness.io/docs/platform/variables-and-expressions/chained-pipeline-output-variables/) to pass outputs between pipelines.

</details>

<details>

<summary>Can you use the Command step in a Custom stage?</summary>

No. This is not supported today. The Command step applies only to SSH and WinRM deployments.

</details>

<details>

<summary>Why does the Command step skip in a WinRM execution when no condition is configured?</summary>

The Command step skips when **Skip instances with the same artifact version already deployed** is selected in **Advanced**.

</details>

<details>

<summary>Why can I not use a particular shell type with the Command step?</summary>

The Command step shell depends on the deployment type.

A WinRM deployment has only the PowerShell option. An SSH deployment has only the Bash option.

To use these shells interchangeably, do one of the following:

* Add a Shell Script step instead of a Command step.
* Run the Command step without **Run on Delegate**, so it runs on the host instead of the delegate.

</details>

<details>

<summary>Why am I getting the error "Host information is missing in Command Step"?</summary>

```
Invalid argument(s): Host information is missing in Command Step. Please make sure the looping strategy (repeat) is provided.
```

The Command step requires the Repeat looping strategy. This error means the Command step ran without a Repeat looping strategy. Set the Repeat looping strategy on the Command step. Go to [SSH and WinRM](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/utilities/download-and-copy-artifacts-using-the-command-step.md#ssh-and-winrm) for the Command step and its looping strategies.

</details>

***

## Email step

<details>

<summary>How can you add a newline in the mail body sent from the Email step?</summary>

The email body uses HTML, so a newline character does not add a line break. Use the HTML line break `<br>`.

</details>

<details>

<summary>Can I send pipeline content as an attachment in an email within Harness?</summary>

No. The Email step in pipelines does not support attachments.

</details>

***

## HTTP step

<details>

<summary>Can you use a JSON functor in the HTTP step with functions such as length and concat?</summary>

Yes. You can use JSON functors such as length and concat in an HTTP step.

Concat:

```
<+json.concat("Hello ", "World!")>
```

Length:

```
<+json.length(<+pipeline.variables.array>)>
```

In both cases, the JSON functor changes the input values and returns a new value that the HTTP step can use.

</details>

<details>

<summary>Does the HTTP step for an mTLS endpoint also ignore the certificate check?</summary>

If you do not provide a certificate for the endpoint, ignoring TLS forces the client not to validate the server. That does not apply to a server that also expects a certificate for client validation. An mTLS endpoint fails in that case.

</details>

<details>

<summary>Does the HTTP step support mTLS?</summary>

Yes. The HTTP step supports mTLS. Use the certificate and private key to establish the mTLS connection with the endpoint.

</details>

<details>

<summary>Is it possible to store an HTTP step output as a secret?</summary>

Masking is not supported on an HTTP step in this way. You can use a Shell Script step and list the output variable as a secret in that step output. Later steps then treat the value as a secret. Go to [Command step](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/utilities/download-and-copy-artifacts-using-the-command-step.md) for the download and copy steps.

</details>

<details>

<summary>How can you use output variables from one pipeline stage or execution in another execution?</summary>

To pass output variables from one pipeline stage to another, use pipeline chaining. In the parent pipeline, define the output variable in the output section of the first stage. In the second stage, use this expression to reference that output variable:

```
<+pipeline.[pipeline_stage_identifier].[output_variable_defined_under_output_section]>
```

When you run the parent pipeline, the output variable from the first stage is passed to the second stage as an input variable.

You can also call this endpoint from a Shell Script step or an HTTP step to fetch execution details for another pipeline:

```
api/pipelines/execution/v2/{planExecutionId}
```

If you pass `renderFullBottomGraph` as `true` in that API call, the response includes all variables in the pipeline. Parse that response for the output variables you need, then publish them for other steps or pipelines.

</details>

<details>

<summary>How do you set unsupported fields when creating a Jira issue?</summary>

By default, Jira plugins do not support cascading lists and other custom types. You can set the unsupported fields with the [HTTP step](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/utilities/http-step.md). Go to [Use the HTTP step to set unsupported fields when creating a Jira issue](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/ticketing-systems/create-cascading-fields-jira.md) for the procedure.

</details>

***

## Shell Script step

<details>

<summary>How do you clone files from a Git repository within a Shell Script step?</summary>

Harness does not support using a GitHub connector inside a shell script. Configure SSH key or HTTP authentication in the shell script with the same secret the connector uses. You then define and rotate the credentials in one place.

</details>

<details>

<summary>Is there a way to inspect artifact details in a Shell Script step for SSH, and change deployment behavior, without copying the artifact to the target server first?</summary>

Yes. Use the Command step to copy the artifact to the delegate, then inspect it there. Go to [Command step](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/utilities/download-and-copy-artifacts-using-the-command-step.md) to download and copy artifacts.

</details>

<details>

<summary>Where is the delegate selector in a Shell Script step?</summary>

The delegate selector is shown only for some step types. On a Shell Script step, the field moved from the **Advanced** tab to the optional configuration on the step parameters tab.

</details>

<details>

<summary>Can you use a Git connector to get a file in a Shell Script step?</summary>

No. You cannot reference a Git connector inside the Shell Script step. To clone a repository, use Git CLI commands. Store the Git credentials in Harness secrets and reference those secrets in the CLI command.

</details>

<details>

<summary>How can I deploy an application to a custom path in an Azure web app?</summary>

Harness does not currently deploy an Azure web app to a custom path. Use a Shell Script step and pass the required argument with the Azure CLI.

</details>

<details>

<summary>Why does echoing the date in a PowerShell Shell Script step add an extra line?</summary>

Use `Write-Host` instead of `echo`. The result is then one line.

</details>

<details>

<summary>Does the Shell Script step use the delegate selector from the connector?</summary>

No. By default, a shell script does not use the connector selector, and the task can run on any delegate. To use the same delegate, specify the selector.

</details>

<details>

<summary>How do you trigger a pipeline when another pipeline completes?</summary>

Add a Shell Script step with a custom webhook `curl` command at the end of the pipeline to trigger the other pipeline.

</details>

<details>

<summary>Can a Shell Script step output variable set the failure strategy of the same step or a later step, for example after a DNS name check?</summary>

No. When a Shell Script step ends with a non-zero exit status, the output variable stays unset, so you cannot use it in later steps or in the failure strategy. Use the non-zero exit status to trigger the failure strategy. Go to [Step and stage failure strategy references](/continuous-delivery/use-continuous-delivery/cd-building-blocks/executions/step-failure-strategy-settings.md) to configure a failure strategy.

</details>

<details>

<summary>How do you read files under a project Helm folder during a project deployment?</summary>

Harness cannot read a values file directly and then read variables from it. The file is read only as part of the service deployment.

To use values from the file, pull the file from your repository in a Shell Script step, then publish the value as an output variable.

</details>

<details>

<summary>How do you use a variable from an environment namespace that a Shell Script step defines?</summary>

Add a Custom stage and export an output variable. Use that output variable in the Deploy stage environment variable. During execution, the pipeline initializes the service and environment before it reaches the shell setup.

</details>

<details>

<summary>Can I use shell variables in Harness expressions to fetch a secret in a Shell Script step?</summary>

No. You cannot use a shell variable in a Harness expression. Harness resolves the expression before the step starts, and the shell variable is populated only when the Shell Script step runs.

You can store a Harness expression that references a secret in a variable, then use that variable in the script. The expression is then resolved independently of the script.

</details>

<details>

<summary>Is there a way to execute Python code directly in the Custom Shell Script step?</summary>

Harness runs the script with `/bin/bash ./file.sh`. It does not use `./file.sh`, which would honor a shebang line and start with Python. The script therefore runs only as a Bash script.

Put the Python command in a file and execute that file from the shell script. The Bash script does not run a Python command directly. A Python script invoked from the shell script does run.

</details>

<details>

<summary>When does Harness mask a secret value in a shell script?</summary>

Harness masks a secret in a script when the script references that secret at least once. For example, reference the secret as `echo <+secrets.getValue("pattoken")>`.

</details>

<details>

<summary>Is a delegate token masked if it is used in a shell script?</summary>

Yes. Delegate tokens are already in memory, and Harness masks them by default.

</details>

<details>

<summary>How do you pass a JSON string as a command-line argument in a shell script?</summary>

Pass the JSON string in single quotes. For example:

```bash
python3 example.py '<+trigger.payload>'
```

`<+trigger.payload>` resolves to JSON.

</details>

<details>

<summary>How do I preserve the formatting of a multiline secret in a shell script?</summary>

Use these commands:

```bash
echo ${secrets.getValue("key_file")} > /tmp/id_rsa_base64
cat /tmp/id_rsa_base64 | base64 -di
```

</details>

<details>

<summary>How can I change a value in the middle of a pipeline, for example with a Bash script?</summary>

Define the variable with a default value, then change that value in the middle of the pipeline.

Assign a stage variable from a shell script with **Script Output Variables** on the Shell Script step. Declare the variable in the script and export it. To set a stage variable named `myvar` to `123`, add this line:

```bash
export myvar=123
```

On the Shell Script step, open **Script Output Variables** and add an output variable. Set **Name** to the stage variable name (`myvar` in this example) and set **Value** to the exported variable name (`myvar` in this example). After the Shell Script step runs, `myvar` is `123`. Reference it in later steps with this expression:

```
<+execution.stages.[stage_id].output.outputVariables.myvar>
```

</details>

<details>

<summary>Can I store a CLI config file in Harness, instead of on the delegate, and reference it from a custom shell script?</summary>

Yes. Use the [File Store API](https://apidocs.harness.io/tag/File-Store#operation/listFilesAndFolders) to create or fetch files from the Harness File Store in the shell script.

</details>

<details>

<summary>Is it possible to get the uninstall flags from a Helm service through an expression?</summary>

Yes. This example finds the uninstall flags:

```sh
commandFlagsJson='<+json.format(<+pipeline.stages.deploy.spec.manifests.helm_hello_world.commandFlags>)>'
commandType=$(echo $commandFlagsJson | jq '.[] | select(.commandType=="Uninstall") | .flag')

echo $commandType
```

</details>

<details>

<summary>Is there an official way for a shell script to use a connector so GitHub requests do not need a machine token stored in Harness?</summary>

No. This is not possible yet, because the shell script is connector agnostic. If the shell script runs on a delegate that already has access or credentials, the command can use those credentials. You can file a Canny request for this.

</details>

<details>

<summary>How do you find the script file Harness creates to run a script task?</summary>

Harness creates a script file from the shell script configuration in the `/tmp` folder.

</details>

<details>

<summary>Can you pull from Bitbucket or GitHub on the Harness Delegate and then push to the target server?</summary>

Yes. Use the Git Clone step, then push the files to the target server with a Shell Script step or a Run step in the stage.

</details>

<details>

<summary>How do you use the Opsgenie plugin with Harness to create alerts from test-case health?</summary>

Harness has built-in notifications for Slack, email, Microsoft Teams, PagerDuty, and custom webhooks. To integrate Opsgenie, create a shell script that calls the Opsgenie API to raise the alert.

</details>

<details>

<summary>How do you delete a job after its execution is complete?</summary>

Add a shell script that checks the job status before the Kubernetes Delete step. `kubectl` commands need the Harness kubeconfig as an environment variable. This script is an example:

```bash
export KUBECONFIG=${HARNESS_KUBE_CONFIG_PATH}
kubectl wait --for=condition=complete job/myjob -n <+infra.namespace>
```

</details>

<details>

<summary>How do you trigger one pipeline from another and pass the first pipeline shell script output, including runtime inputs such as environment and infrastructure names?</summary>

Use output variables from one pipeline as inputs for another, and define the receiving pipeline variables as runtime inputs. Go to [Output variable for a PowerShell script](/continuous-delivery/troubleshooting-and-resources/knowledge-base-article/output-variable-for-powershell-script.md) for an example.

</details>

***

## Containerized step groups

<details>

<summary>How can I override the lite-engine image for the Container Run step so images are pulled from Amazon ECR instead of Docker Hub?</summary>

Use a Docker connector with your registry URL and anonymous access.

</details>

<details>

<summary>Can one custom plugin be used in steps for both Continuous Integration and Continuous Delivery?</summary>

Yes. You can create one custom plugin and use it in both modules. The plugin documentation is similar for both, and the same plugin can be used in both. The difference is where the pipeline uses the plugin. In Continuous Integration, the plugin is used in a [Plugin step](https://developer.harness.io/docs/continuous-integration/use-ci/use-drone-plugins/explore-ci-plugins/). In Continuous Delivery, it is used in a [Containerized step](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/containerized-steps/plugin-step.md). If the plugin is written for both step types, you can use it in both modules.

</details>

<details>

<summary>Is there a way to change write access on the /tmp directory so one team cannot delete it and disrupt other teams?</summary>

No. Harness does not provide that control. Use containerized step groups instead of sharing `/tmp` across teams. Go to [Containerized step groups](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/containerized-steps/containerized-step-groups.md) to run steps on their own pod.

</details>

<details>

<summary>How do you pass a dynamic image tag from a Continuous Integration pipeline to a Continuous Delivery pipeline so the pipeline can pull the image?</summary>

Create a project, organization, or account variable. In the first pipeline, add a Shell Script step or a Run step that exports the variable. The second pipeline can read that variable and use its value.

The shell script updates the variable with the [update variable API](https://apidocs.harness.io/tag/Variables#operation/updateVariable).

</details>

<details>

<summary>How do I use a Custom stage for the Terraform Cloud Run step?</summary>

The Run step is supported only in Continuous Integration and Continuous Delivery stages. In a Custom stage, use the Shell Script step.

</details>

<details>

<summary>Why does the pipeline not roll back when the Container step times out?</summary>

The Container step is deprecated, and Harness no longer provides support for it. Use a containerized step group and add a Run step. The Run step behaves like the Container step, and rollback works as expected.

</details>

<details>

<summary>Can I use the same cluster for the Harness Delegate and for containerized step groups?</summary>

Yes. You can use the same cluster for the Harness Delegate and for containerized step groups. A separate cluster is not required. Go to [Important notes](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/containerized-steps/containerized-step-groups.md#important-notes) for containerized step group limits.

</details>

<details>

<summary>How do you fetch files from the Harness File Store in the Run step?</summary>

Use this Run step as an example:

```yaml
- step:
    type: Run
    name: Fetch Files from File Store
    identifier: fetch_files
    spec:
      shell: Sh
      command: |
        harness file-store download-file --file-name <file_name> --destination <destination_path>
```

Replace `<file_name>` with the file name in the File Store, and replace `<destination_path>` with the path where you want to save the file on the target host.

</details>

<details>

<summary>Do the Run and Git Clone steps require a Continuous Integration license when they are used in a Continuous Delivery step group?</summary>

No. You do not need a Continuous Integration license to use the Run and Git Clone steps in a Continuous Delivery step group, even though those steps are listed under Build.

</details>

<details>

<summary>How can you use AWS CDK provisioning, and does it require a feature flag?</summary>

No feature flag is required. AWS CDK provisioning steps are available only inside a containerized step group designated for AWS CDK provisioning. The steps appear when you add a step in that step group. If that step group has no step, the AWS CDK steps are not shown. Go to [AWS CDK provisioning](/continuous-delivery/use-continuous-delivery/provision-infrastructure/aws-cdk/aws-cdk-provisioning.md) to add the steps.

</details>

<details>

<summary>Can I use Plugin or Git Clone steps in Deploy or Custom stages?</summary>

Yes. Add these steps in containerized step groups in Deploy or Custom stages.

</details>

<details>

<summary>Can I use any Continuous Integration steps in a containerized step group?</summary>

No. Only some step types are available in containerized step groups.

</details>

<details>

<summary>Where are steps in containerized step groups executed?</summary>

They run on a separate pod that Harness creates at runtime. Harness deletes the pod when the step group execution ends.

</details>

<details>

<summary>Are separate pods created for each step in a containerized step group?</summary>

No. Harness creates one pod for the containerized step group and runs all step containers in the group on that pod.

</details>

<details>

<summary>Can I access files from a containerized step group in a later Shell Script step?</summary>

No. Containerized step groups run on a separate pod from other steps. Files created in the containerized step group are not available to steps outside the group.

</details>

<details>

<summary>Can I run a containerized step group on a self-managed VM or on local infrastructure?</summary>

No. A containerized step group can run only on Kubernetes infrastructure.

</details>

<details>

<summary>Does the containerized step group command override CMD, ENTRYPOINT, or both?</summary>

The step group **Command** overwrites the image default entry point when the image has one.

To run the entry point and other commands, use an image that has no default entry point, then run all of the commands in the step group **Command**.

</details>

<details>

<summary>Does the Harness Slack integration notify on Jira events that are waiting for approval?</summary>

Harness supports a **Waiting for User Action** pipeline event. It sends a notification when a pipeline pauses for input, including Approval steps, Manual Intervention, and runtime execution inputs. Configure the event in the pipeline notification rules or in [centralized notifications](https://developer.harness.io/docs/platform/notifications/notifications/centralised-notification/). Alerts can use Slack, email, Microsoft Teams, PagerDuty, webhook, or Datadog. Go to [Select pipeline events](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/notify-users-of-pipeline-events.md#select-pipeline-events) to turn the event on.

This event notifies you whenever any step requires action. It cannot be limited to one approval type, such as Jira approvals only.

</details>

<details>

<summary>Is a containerized step group on Kubernetes the only way to use the Git Clone step?</summary>

The Git Clone step uses a containerized step group. If you are not using Kubernetes or similar infrastructure, use a Shell Script step and clone the repository with the Git CLI.

</details>

***

## Jenkins build step

<details>

<summary>Why is my Jenkins job failing with a 500 error?</summary>

```
Error occurred while starting Jenkins task
org.apache.http.client.HttpResponseException: status code: 500, reason phrase: Server Error
```

This can happen when the Jenkins job is parameterized and no parameters are passed. It can also happen when the Jenkins job is not parameterized and parameters are passed. Pass the parameters that match the Jenkins job.

</details>

<details>

<summary>Does Harness support dynamic runtime inputs such as Jenkins scripted dropdowns?</summary>

No. Harness does not support input fields that are populated dynamically at runtime, such as script-driven dropdowns, in the way Jenkins does.

The closest option is an input set, which defines values for runtime inputs in advance. Provide the input set when you trigger a pipeline with the [execute pipeline API](https://apidocs.harness.io/tag/Pipeline-Execution#operation/execute-pipeline).

</details>

***

## Approvals

<details>

<summary>How can I retrieve a list of approvers for approval stages in Harness pipelines?</summary>

Retrieving a list of approvers for approval stages requires querying the Harness database. The `/api/approvals` API endpoint can retrieve approval instances for a pipeline execution, but user data is not included directly. Custom dashboards might offer a way to visualize this data.

</details>

<details>

<summary>Does Harness use delegates for pipelines that are waiting or in an approval state?</summary>

Harness does not use delegates for Harness approvals. Harness uses delegates for ServiceNow, Jira, and custom approvals while it polls for approval criteria.

</details>

***

## ServiceNow

<details>

<summary>Does Harness support the RITM option for ServiceNow approvals?</summary>

No. Harness does not support the RITM option for ServiceNow approval ticket creation.

</details>

<details>

<summary>How can I trigger Harness from ServiceNow and Jira and pass ticket values?</summary>

Use Custom stages with shell scripts. Extract the values from the trigger payload and pass them to the approval steps.

</details>

<details>

<summary>Why does a deployment continue through several environments and then fail at approval because the permissions are wrong?</summary>

The workflow does not check deploy permission for the target environment until the approval step. There is no early permission check, so the deployment can run until that step and then fail. A pre-deployment permission check avoids that. Review the permission model and the deployment process for the same gap.

</details>

***

## Failure strategy

<details>

<summary>How can I configure a retry strategy for a Continuous Delivery stage?</summary>

Add a failure strategy to the stage. By default, Harness adds a rollback strategy for all error types. You can add more failure strategies for specific error types and for retry. If you create a Continuous Delivery stage and close the wizard without selecting a strategy, the failure strategy is blank.

</details>

<details>

<summary>How can you automate rollback strategies in Harness pipelines?</summary>

Use failure strategies that run rollback steps when a deployment fails.

</details>

<details>

<summary>How does the rollback strategy for e2e_stage behave when the stage is about to time out?</summary>

When `e2e_stage` is nearing its timeout, the configured failure strategy is applied. That strategy can be `EXPIRE_ALL`. The stage then rolls back to a previous stable state. The exact behavior depends on the configured rollback strategy and on the pipeline. Go to [Timeout settings](https://developer.harness.io/docs/platform/pipelines/failure-handling/timeout-settings) to set a timeout.

</details>

{% @harness-feedback/feedback %}
