Templating & Variables
Template Types
FirmwareCI offers a variety of template groups. These templates are sourced from various origins, such as device-specific information. Each template is identified by a combination of a category identifier and a name identifier, separated by a period (e.g., [[input.Binary]]
). The name identifier can include characters from a-z, A-Z, underscores (_), and hyphens (-).
Dynamic Job Input
pre.yaml
pre-stage:
- cmd: dutctl
name: Flash the firmware binary.
parameters:
host: "my-flasher-address"
command: flash
args: [write, "[[input.Binary]]"]
Templates using the [[input.*]]
syntax require you to supply the referenced inputs for each job request. These inputs are typically firmware binaries or other dynamic data to be tested with a test run. For example, in the pre.yaml
configuration, the [[input.Binary]]
placeholder must be provided with the path to the binary you wish to flash.
When submitting a job, ensure that all required inputs referenced in your pre-stage, post-stage, and test files are included. The job will not start unless every referenced input is supplied.
Attributes
Attributes of DUTs can be referenced using attributes.name-of-attribute
. Common use-cases include addresses of the target device, the flash device, or flags used in testing tools.
Refer to the DUT Configuration for additional information.
- cmd: ping
name: Wait for SSH service
options:
timeout: 2m
parameters:
host: "[[attributes.Host]]"
In this example, attributes.Host
specifies the target address for the ping command.
Reservation
Reservation attributes of DUTs can be referenced using reservation.attribute-name
. These are typically used for accessing dynamic data provided by external reservation systems, such as UUIDs or dynamically assigned host addresses. An external reservation can be specified in the reservation-system
field of your dut.yaml
file. When configured, the reservation system may populate various key-value pairs based on its integration.
For more information, please refer to the DUT Configuration documentation.
- cmd: ping
name: Wait for SSH service
options:
timeout: 2m
parameters:
host: "[[reservation.DynamicHost]]"
In this example, reservation.DynamicHost
references a target address dynamically assigned by the reservation system. This value must be provided by the configured reservation system prior to test execution.
Storage
A storage can be referenced via storage.name-of-storage
. Common use-cases include individual tools, which are copied onto the Device Under Test (DUT) for testing purposes. If a storage is referenced inside a test, it is available at the path resolved by the template.
Refer to the storage documentation & the storage guide for additional information.
- cmd: copy
name: Copy tooling to DUT
transport: *transport
parameters:
source: "[[storage.tool]]/system-suite"
destination: /root/default-tools/system-suite
recursive: true
In this example, a directory from the storage system_suite
is copied by referencing its parent path using the template storage.tool
.
Secrets
Secrets can be referenced via secrets.name-of-secret
. Common use-cases include API-Tokens.
Refer to the secrets tutorial for additional information.
name: Binarly Scan
description: Test the firmware with Binarly
#The binarly test works without a DUT, therefore we can leave the pre- & post-stage empty
pre-stage: empty
post-stage: empty
stages:
- name: Binarly Scan
steps:
- cmd: binarly report
name: Binarly Scan
parameters:
url: "[[secrets.BinarlyURL]]"
token: "[[secrets.BinarlyToken]]"
file_path: "[[input.Binary]]"
In this example multiple secrets are templated from the workflow secrets data.
Defaults
YAML Anchors can be utilized within tests to minimize redundant statements. These anchors should be defined under the defaults
keyword in the test file.
Example:
# Boot Test Configuration for ARM-based board
name: Boot Test
description: This test verifies that the ARM-based board boots correctly.
defaults:
transport: &transport
proto: ssh
options:
host: "[[attributes.Host]]"
user: root
password: root
stages:
- name: Boot Stage
steps:
- cmd: ping
name: Wait for SSH service
options:
timeout: 2m
parameters:
host: "[[attributes.Host]]"
- cmd: cmd
name: Run echo "Hello" on the device
transport: *transport
parameters:
executable: echo
args: ["Hello"]
- cmd: cmd
name: Run echo "World!" on the device
transport: *transport
parameters:
executable: echo
args: ["World!"]
Variables
Variables enable the storage and reuse of dynamic data within your test workflows. You can define variables globally at the beginning of your test file using the variables
key, or assign and update them within individual test steps as the workflow executes. Variables are referenced using the {{ key }}
syntax, allowing their current values to be inserted into parameters or other supported fields. This approach facilitates the transfer of data between steps, such as dynamically generated file paths, command outputs, or configuration values, thereby enhancing the flexibility and maintainability of your test definitions.
Example:
variables:
tmpdir: "/tmp/dir/abc"
stages:
- name: Example Stage
steps:
- cmd: cmd
name: Create temp dir
parameters:
executable: "mktemp"
args: ["-d", "/tmp/dir/mydir.XXXXXX"]
variable: "tmpdir" # Save output to variable 'tmpdir'
- cmd: cmd
name: Use temp dir
parameters:
executable: "ls"
args: ["{{ tmpdir }}"] # Use the value of 'tmpdir' here
In this example, the first step creates a temporary directory and saves its path to the tmpdir variable, which is then used in the next step.