Skip to content
Back to skills

1648 Steps Overview B01945c0

ASecurity

Comprehensive technical reference for GitLab CI/CD Steps feature syntax, capabilities, and step definition structure. Source: <https://docs.gitlab.com/ci/steps/>

  • 9 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 11, 2026
developmentrustgojavashellbashexpressdockergitci/cd

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 1648-steps-overview_b01945c0 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 1648 Steps Overview B01945c0?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 1648 Steps Overview B01945c0
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-1648-steps-overview-b01945c0/badge)](https://www.skillsdirectory.com/skills/tools-only-1648-steps-overview-b01945c0)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# GitLab CI/CD Steps: Overview and Specifications

Comprehensive technical reference for GitLab CI/CD Steps feature syntax, capabilities, and step definition structure.

Source: <https://docs.gitlab.com/ci/steps/>

## Feature Definition

Steps are reusable units of work at the job level that replace traditional `script` keyword. They enable:

- Reusability across jobs and projects
- Composability through input/output chaining
- Independence through explicit contracts
- Testability of discrete units
- Retrieval of supporting files

## Job Execution Model

Jobs using `run` keyword execute steps sequentially. Steps run in Docker containers created by GitLab (container image: <https://gitlab.com/gitlab-org/step-runner/-/blob/main/Dockerfile>).

Steps access:

- CI/CD job variables (restricted: CI*, DOCKER*, GITLAB\_ prefixed only)
- Environment variables
- File system (project directory per CI_PROJECT_DIR)
- Networking

Current limitations:

- Linux only (Windows/macOS in development)
- Run in dedicated containers (job environment execution planned)
- Cannot combine `run` with `script`, `before_script`, `after_script`

## Step Specification Structure

Step `step.yml` file contains two YAML documents separated by `---`:

### Document 1: Specification

Defines input/output contracts and types. Syntax:

```yaml
spec:
  inputs:
    input_name:
      type: [string|number|boolean|array|struct]
      default: value # optional, makes input optional
  outputs:
    output_name:
      type: [string|number|boolean|array|struct]
      default: value # optional, returned if step doesn't provide
```

Input/output names: alphanumeric and underscores only, must not start with number.

Special case - delegated outputs: Return all sub-step outputs:

```yaml
spec:
  outputs: delegate
```

No inputs or outputs: Use empty spec:

```yaml
spec:
```

### Document 2: Definition

Specifies step implementation. Three patterns:

#### Pattern 1: Environment Variables

```yaml
env:
  VARIABLE_NAME: value
  ANOTHER_VAR: "${{inputs.some_input}}"
```

Variables available to executable command or all sub-steps in sequence.

#### Pattern 2: Command Execution

```yaml
exec:
  work_dir: ${{step_dir}}
  command:
    - bash
    - -c
    - "command here"
```

Fields:

- `command` (required): Array of command tokens
- `work_dir` (optional): Working directory path, defaults to step directory

Environment variables set in `env` keyword available to process.

#### Pattern 3: Step Sequencing

```yaml
run:
  - name: step_one
    step: ./step-one
    inputs:
      param1: value
    env:
      VAR: value
  - name: step_two
    step: ./step-two
    inputs:
      data: "${{steps.step_one.outputs.result}}"
```

Sub-steps run sequentially. Each step requires:

- `name` (alphanumeric, underscore, not starting with number)
- One of: `step`, `script`, `action`

Optional: `inputs`, `env`, `env` at sequence level applies to all steps.

## Step Locations

### File System

Load from relative path:

```yaml
step: ./path/to/step
```

Path format: forward slashes always, even on Windows. Folder must contain `step.yml`.

### Git Repository

Load from Git source with revision specifier:

```yaml
step: gitlab.com/components/echo@v1.0.0
step: gitlab.com/components/echo@main
step: gitlab.com/components/echo@commit_sha
```

Loads `step.yml` from `steps` folder by default.

### Expanded Git Syntax

Specify custom directory and filename:

```yaml
step:
  git:
    url: gitlab.com/components/echo
    rev: main
    dir: my-steps/sub-directory # optional, defaults to repo root
    file: my-step.yml # optional, defaults to step.yml
```

## Expressions

Mini-language for dynamic values. Enclosed in `${{ }}`. Evaluated at step execution (before step runs), distinguished from component expressions `$[[ ]]` (evaluated at pipeline creation).

Valid in:

- Input values
- Environment variable values
- Step location URL
- Executable command
- Executable work directory
- Step sequence outputs
- `script` steps
- `action` steps

### Expression Variables

| Variable       | Syntax                             | Description                                                          | Access Rules                         |
| -------------- | ---------------------------------- | -------------------------------------------------------------------- | ------------------------------------ |
| Environment    | `${{env.VAR}}`                     | Environment variables set in execution environment or previous steps | All                                  |
| Inputs         | `${{inputs.name}}`                 | Step inputs                                                          | Within step only                     |
| Job            | `${{job.VAR}}`                     | CI/CD variables                                                      | CI*, DOCKER*, GITLAB\_ prefixed only |
| Prior outputs  | `${{steps.step_name.outputs.var}}` | Prior step outputs                                                   | After that step executes             |
| Step directory | `${{step_dir}}`                    | Downloaded step location                                             | Executable steps                     |
| Work directory | `${{work_dir}}`                    | Current working directory                                            | Executable steps                     |
| Output file    | `${{output_file}}`                 | Path to output file                                                  | Executable steps                     |
| Export file    | `${{export_file}}`                 | Path to environment export file                                      | Executable steps                     |

## Input/Output Handling

### Inputs

Inputs are optional unless no default specified. Passed when using a step:

```yaml
run:
  - name: my_step
    step: ./step
    inputs:
      greeting: "hello world"
      count: 42
```

Input types:

- `string`: Text
- `number`: 64-bit float
- `boolean`: true/false
- `array`: List of untyped items
- `struct`: Structured object with key-value pairs

### Outputs from Executable Steps

Write to `${{output_file}}` in JSON Lines format. Each line: JSON object with `name` (string) and `value` (must match declared output type):

```bash
echo '{"name":"result","value":"value_string"}' >${{output_file}}
echo '{"name":"count","value":42}' >${{output_file}}
echo '{"name":"items","value":["a","b"]}' >${{output_file}}
```

Value types must match step specification:

- `array` → JSON array
- `boolean` → JSON boolean
- `number` → JSON number
- `string` → JSON string
- `struct` → JSON object

### Outputs from Step Sequences

Return from sub-steps using `outputs` keyword:

```yaml
run:
  - name: install_java
    step: ./common/install-java
outputs:
  java_version: "${{steps.install_java.outputs.java_version}}"
```

Or delegate all outputs:

```yaml
run:
  - name: install_java
    step: ./common/install-java
outputs:
  delegate: install_java
```

## Environment Variables

### Setting Variables

Set in step `env` keyword or passed when invoking step:

```yaml
spec:
---
env:
  FIRST_NAME: Sally
  LAST_NAME: Seashells
```

Executable step environment variables available to command. Sequence environment variables available to all sub-steps.

### Exporting Variables

Executable steps export for subsequent steps by writing to `${{export_file}}` in JSON Lines format:

```bash
echo '{"name":"GOPATH","value":"/go"}' >${{export_file}}
```

### Precedence (Highest to Lowest)

1. `step.yml` `env` keyword
2. Passed `env` keyword (when using step)
3. Sequence-level `env` keyword
4. Previously exported variables (step `${{export_file}}`)
5. Runner environment
6. Container environment

## Using Steps in Jobs

Basic job structure:

```yaml
my_job:
  run:
    - name: step_identifier
      step: step_location
      inputs:
        param1: value
      env:
        VAR: value
    - name: another_step
      step: ./another
      inputs:
        data: "${{steps.step_identifier.outputs.result}}"
```

Cannot use `script`, `before_script`, `after_script` when using `run` keyword.

## Step Types in Sequences

### Step Type

Reference external step definition:

```yaml
- name: my_step
  step: gitlab.com/components/echo@v1.0.0
  inputs:
    message: "text"
```

### Script Type

Execute shell command:

```yaml
- name: my_script
  script: echo hello ${{job.GITLAB_USER_LOGIN}}
```

Shell: `bash`, fallback to `sh`. Runs in CI_PROJECT_DIR. Environment variables passed via `env` set in shell.

### Action Type

Execute GitHub Action (requires `dind` service):

```yaml
- name: use_action
  action: mikefarah/yq@master
  inputs:
    cmd: echo ["data"] | yq .[0]
```

Inputs and environment passed directly to action. Action outputs returned as step outputs.

Known limitation: Actions cannot upload artifacts directly; write to filesystem and cache instead, select with `artifacts` and `cache` keywords.

## Combining with CI/CD Components

Components use `$[[ ]]` expressions (pipeline creation time), Steps use `${{ }}` (job execution time). Components provide job-level configuration; steps handle job composition.

Example component using steps internally:

```yaml
spec:
  inputs:
    fmt_packages:
      description: Go packages to format
    go_version:
      default: "1.22"
---
format_code:
  run:
    - name: install_go
      step: ./languages/go/install
      inputs:
        version: $[[ inputs.go_version ]]
    - name: format_code
      step: ./languages/go/go-fmt
      inputs:
        go_binary: ${{ steps.install_go.outputs.go_binary }}
        fmt_packages: $[[ inputs.fmt_packages ]]
```

## Troubleshooting

### HTTPS Certificate Validation Failures

Error: `tls: failed to verify certificate: x509: certificate signed by unknown authority`

Cause: Docker image lacks trusted root certificates.

Resolution options:

1. Install certificates in container before fetching steps:

```yaml
ubuntu_job:
  image: ubuntu:24.04
  run:
    - name: install_certs
      script: apt update && apt install --assume-yes --no-install-recommends ca-certificates
    - name: fetch_step
      step: https://gitlab.com/user/my_steps/hello_world@main
```

2. Bake certificates into job image.

3. For Runner-based resolution: Install certificates in Runner Docker executor configuration.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.