Skip to content
Crow CI

Step outputs

A step can hand values to later steps of the same workflow. It writes them to the file in $CI_STEP_OUTPUT, and a later step names each value it wants with from_step:, the same way it takes a secret with from_secret:.

This also works for plugins. A plugin cannot source a file from an earlier step, but the agent sets the values as environment variables when it starts the plugin’s container.

steps:
  - name: version
    image: alpine
    commands:
      - echo "tag=$(cat VERSION)" >> "$CI_STEP_OUTPUT"

  - name: publish
    image: my/plugin
    depends_on: [version]
    settings:
      repo: example/app
      tags:
        from_step: version.tag

$CI_STEP_OUTPUT holds the path of the file to append outputs to. Write one key=value line per output:

echo "tag=1.2.3" >> "$CI_STEP_OUTPUT"
echo "image_id=sha256:4b1c..." >> "$CI_STEP_OUTPUT"

For a value with line breaks, start it with key<<DELIMITER and end it with a line that holds only DELIMITER:

{
  echo "notes<<EOF"
  git log --oneline -5
  echo "EOF"
} >> "$CI_STEP_OUTPUT"
  • Keys consist of letters, digits, _ and -, and do not start with a digit or -.
  • Empty lines are ignored. A key written twice keeps the last value.
  • The file may be at most 4096 bytes, and on Kubernetes less than that. A larger file, or a line that is not in one of the two forms, fails the step.
  • Outputs are only collected from a step that succeeded and that another step references. In other steps $CI_STEP_OUTPUT points at /dev/null (NUL in Windows containers), so writing to it does not fail. Tart and Hyper-V do not set it.

from_step: <step>.<key> works in settings: and in environment::

steps:
  - name: deploy
    image: alpine
    depends_on: [version]
    environment:
      TAG:
        from_step: version.tag
    commands:
      - ./deploy.sh "$TAG"

The key follows the last dot, so step names may contain dots.

from_step: has to be the whole value of a setting or variable. It cannot be nested in a list or map, since the value is only known when the step starts. Services and clone steps cannot use it.

Variables the agent and backends read themselves cannot take an output: HOME, USERPROFILE, and anything starting with CI_ or DRONE_. Plugin settings are not affected, since they become PLUGIN_* variables. A variable that takes an output cannot also be set by a secret or another setting with the same resulting name, such as a-b next to a_b.

The linter rejects a reference to a step that

  • does not exist,
  • is the step itself or is detached, or
  • the step does not wait for. In a workflow that uses depends_on, the step has to depend on it directly or through other steps. Otherwise it has to be listed above the step.

If the referenced step was skipped, failed with failure: ignore, or did not write the key, the step that references it fails before it starts instead of running without the value. Give a step that uses an output the same when as the step that provides it, so that both are skipped together.

Rerunning a single step also reruns the steps whose outputs it uses, since outputs are not kept between runs.

Only the values a step names reach it. An earlier step, including one running code from a pull request, cannot set other variables on a plugin through its outputs, such as PLUGIN_* settings, DOCKER_HOST or LD_PRELOAD.

The values themselves are input from the step that wrote them. On a pull request that step runs the pull request’s code, so treat an output like any other untrusted input, especially when a privileged plugin uses it.

Outputs are not secrets: they are not masked in logs. Do not write secrets to $CI_STEP_OUTPUT.

Backend Where the step writes
Docker /.crow/step-output in the container, copied out once it stopped. The file is writable by any user.
Podman Same as Docker.
Kubernetes /dev/termination-log, read from the container’s termination message. Kubernetes keeps only the last 4096 bytes, so the file has to stay below that.
Local A file in the workflow’s temporary directory, created when the step first writes it.

Windows containers, Tart and Hyper-V do not support step outputs. A workflow on them fails at the step whose outputs are referenced.

Outputs live in the memory of the agent that runs the workflow. When an agent restarts and adopts a running workflow, outputs of steps that finished before the restart are gone, and steps that reference them fail. Both the server and the agents need a version that supports step outputs; an older agent runs the step without the values.