Templating & Variables

Overview

FirmwareCI provides two mechanisms for dynamic content:

Templates: Resolved at test start from external sources. Syntax: [[category.identifier]]

Variables: Defined and modified during test execution. Syntax: {{ variable_name }}

Template Syntax

Format

[[category.identifier]]

Category: Template source (input, attributes, reservation, storage, secrets, ssh-keys)

Identifier: Specific value name. Allowed characters: a-z, A-Z, 0-9, _, -. Attribute and storage names must not contain -.

Template Categories

CategorySourceResolution TimeRequiredTypical Use Cases
inputJob trigger parametersJob startYes (if referenced)Firmware binaries, test parameters
attributesDUT configurationTest startYes (if referenced)Host addresses, device IDs, credentials
reservationExternal reservation systemTest startYes (if configured)Dynamic IDs, allocated resources
storageStorage configurationTest startYes (if referenced)Tool paths, test data locations
secretsWorkflow secretsTest startYes (if referenced)API tokens, passwords
ssh-keysOrganization SSH keysTest startYes (if referenced)SSH authentication

Input Templates

Syntax: [[input.InputName]]

Description: References dynamic data provided when triggering workflows. All referenced inputs must be supplied at job submission or the job will not start.

A binary input resolves to its file in the test container, at /tmp/<InputName>/<file name>. Each input has a directory of its own, so two inputs may carry the same file name:

Submitted[[input.…]] resolves to
Binary=build/coreboot.rom[[input.Binary]] → /tmp/Binary/coreboot.rom
DebugBinary=build-debug/coreboot.rom[[input.DebugBinary]] → /tmp/DebugBinary/coreboot.rom

Refer to a binary through its template rather than a fixed path such as /tmp/coreboot.rom.

Example:

pre-stage:
  - cmd: dutctl
    name: Flash firmware
    parameters:
      agent: "[[attributes.Agent]]"
      device: "[[attributes.Device]]"
      command: flash
      args: [write, "[[input.Binary]]"]
    options:
      timeout: 10m

The dutctl command name flash comes from the agent’s configuration (see Commands).

See Templating guide for examples.

Attribute Templates

Syntax: [[attributes.AttributeName]], [[attributes.Map.Key]], [[attributes.List.0]]

Description: References values from DUT configuration. Defined in dut.yaml files. A dot path goes into a map by key and into a list by index, counting from 0.

Example:

# dut.yaml
attributes:
  Host: board-1.lab
  Fans: [FAN0, FAN1]
  PSU:
    Count: 2
# test file
parameters:
  host: "[[attributes.Host]]"         # board-1.lab
  url: "https://[[attributes.Host]]"  # https://board-1.lab
  fan: "[[attributes.Fans.1]]"        # FAN1
  count: "[[attributes.PSU.Count]]"   # 2, as a number if the field takes a number
  fans: "[[attributes.Fans]]"         # ["FAN0", "FAN1"]

Every single attribute value is text. A token that is the complete quoted value gives it the type that its field takes: 30 goes into a number field as the number 30 and into a text field as the text "30", and true goes into a boolean field as true. Number forms such as 0x1F, 1_000 and .5 are read as numbers for a number field and stay as written in text. A whole list or map must be the complete quoted value, as in fans above: FirmwareCI then puts the list or map in place of the string. Inside a longer string, every scalar becomes text, and a list or map, such as "all: [[attributes.Fans]]", stops the job with an error.

A token that the DUT cannot fill stops the job before it starts: a path that does not exist, a list or map inside a longer string, or a value that the field cannot take, such as a list for a text field. The job error gives the test, the step, the line, the problem and how to correct it, for example:

The job did not start.
Where: test "fans", stage "Check" step "Read fan 5" (line 14)
Problem: [[attributes.Fans.5]] does not exist: "Fans" on DUT "board-1" is a list with 2 items.
Hint: Use an index from 0 to 1.

fwci validate and the sync report the same problems as warnings, for each DUT whose label the workflow runs on.

See DUT Configuration for schema details.

Reservation Templates

Syntax: [[reservation.AttributeName]]

Description: References dynamic data from external reservation systems. Populated by the configured reservation system prior to test execution.

Configuration: Set reservation-system field in dut.yaml to enable external reservation integration.

See DUT Configuration for reservation system setup.

Storage Templates

Syntax: [[storage.StorageName]]

Description: References paths to storage items. Resolves to the mounted path where the storage is available during test execution.

Example:

parameters:
  source: "[[storage.tools]]/binary"
  destination: /tmp/binary

See Storage Configuration and Storage guide.

Secret Templates

Syntax: [[secrets.SecretName]]

Description: References sensitive data stored in workflow configuration. Secrets are encrypted and only accessible during test execution.

Example:

parameters:
  token: "[[secrets.APIToken]]"
  url: "[[secrets.ServiceURL]]"

See Secrets guide for managing secrets.

SSH Key Templates

Syntax Reference

TemplateDescriptionReturns
[[ssh-keys.key_name]]Private key path (default)/path/to/key_name
[[ssh-keys.key_name.private]]Private key path (explicit)/path/to/key_name
[[ssh-keys.key_name.public]]Public key path/path/to/key_name.pub
[[ssh-keys.default]]Instance default private key/path/to/default
[[ssh-keys.default.private]]Instance default private key/path/to/default
[[ssh-keys.default.public]]Instance default public key/path/to/default.pub

Description

References organization-level SSH keys mounted into test containers. Keys are automatically discovered if identity_file is not specified in transport configuration.

Usage

transport:
  proto: ssh
  options:
    host: "[[attributes.Host]]"
    user: root
    identity_file: "[[ssh-keys.deploy_key]]"

Auto-Discovery

If identity_file is omitted, all available organization SSH keys are tried automatically:

transport:
  proto: ssh
  options:
    host: "[[attributes.Host]]"
    user: root
    # No identity_file - uses auto-discovery

See SSH Key Management for key setup and management.

YAML Anchors (Defaults)

Syntax

Define anchors under the defaults keyword:

defaults:
  name: &anchor_name
    key: value

Reference anchors using *anchor_name:

field: *anchor_name

Description

YAML anchors reduce redundancy by defining reusable configuration blocks. FirmwareCI supports standard YAML 1.2 anchor and alias syntax.

Usage

defaults:
  transport: &transport
    proto: ssh
    options:
      host: "[[attributes.Host]]"
      user: root

stages:
  - name: Test
    steps:
      - cmd: cmd
        transport: *transport
        parameters:
          executable: uname

See YAML specification for complete syntax.

Variables

Syntax

Declaration:

variables:
  var_name: "initial_value"

Assignment (in step):

parameters:
  variable: "var_name"

Reference:

args: ["{{ var_name }}"]

Description

Variables store and reuse dynamic data during test execution. Variables can be:

  • Declared globally at test file start
  • Assigned by step output during execution
  • Referenced in any subsequent step

Variable Naming

Allowed characters: a-z, A-Z, 0-9, _. A name must not start with a digit.

Variable Values

A stored value keeps only a-z, A-Z, 0-9 and / _ . : + -; every other character is dropped. This keeps versions such as v2.18.0+gabc and times such as 12:00:01 intact, and keeps a space or a quote from breaking the step that uses the value. The ipmi and redfish steps say in the log when they drop characters.

Scope

Variables are scoped to the test file. All stages and steps within the test can access defined variables.

Usage

variables:
  tmpdir: "/tmp/default"

stages:
  - name: Create and Use Directory
    steps:
      - cmd: cmd
        name: Create directory
        parameters:
          executable: mktemp
          args: ["-d", "/tmp/test.XXXXXX"]
          variable: "tmpdir"

      - cmd: cmd
        name: List directory
        parameters:
          executable: ls
          args: ["{{ tmpdir }}"]

Variable Assignment

Commands that support variable assignment capture stdout and store it in the specified variable. The IPMI and Redfish steps store the value they read instead, for example a firmware version before an update or a power reading for a later sum. Check individual command documentation in Test Step Commands for variable support.

Template Resolution Order

Templates are resolved in this order during test execution:

  1. Pre-execution: input, attributes, reservation, secrets, storage, ssh-keys templates resolved before test starts
  2. During execution: Variables resolved at each step based on current state
  3. YAML anchors: Expanded during YAML parsing before template resolution