End-to-End Example: STM32 + GitHub Actions + BenchCI Cloud¶
This page shows the full path from firmware build to real hardware validation.
STM32 firmware
↓
GitHub Actions build
↓
BenchCI Cloud run
↓
Cloud-connected Agent
↓
real hardware bench
↓
results + measurements + evidence in CLI + dashboard
Goal¶
By the end of this example, a CI workflow will:
build firmware
upload the firmware artifact
ask BenchCI to run a hardware test
flash the board through a registered Agent
collect results and logs
show the run, evidence, traceability, and artifacts in the BenchCI dashboard
Prerequisites¶
You need:
a BenchCI account and active workspace
a hardware machine connected to the DUT
a working
bench.yamla working
suite.yamla registered cloud Agent
a GitHub repository containing your firmware project
Verify the bench is visible:
benchci benches list
Example result:
my-bench online idle
1. Verify local hardware execution¶
On the hardware-connected machine:
benchci run \
--bench bench.yaml \
--suite suite.yaml \
--artifact build/fw.elf \
--verbose
Do not continue until this works locally.
This gives you a clean hardware baseline before adding CI variables such as workflow credentials, artifact paths, runner setup, or cloud scheduling.
2. Start the cloud Agent¶
On the hardware-connected machine:
benchci agent cloud \
--token YOUR_AGENT_TOKEN \
--bench bench.yaml \
--bench-id my-bench
The Agent makes outbound requests to the BenchCI backend.
Your lab machine does not need a public inbound port.
3. Add GitHub secrets¶
In GitHub:
Settings → Secrets and variables → Actions → New repository secret
Add:
BENCHCI_EMAIL=engineer@company.com
BENCHCI_PASSWORD=your-password
BENCHCI_BENCH_ID=my-bench
Use a dedicated CI account when possible.
4. Add GitHub Actions workflow¶
Create:
.github/workflows/hardware-ci.yml
Example:
name: Hardware CI
on:
push:
branches:
- main
pull_request:
jobs:
build-firmware:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install ARM toolchain
run: |
sudo apt-get update
sudo apt-get install -y make gcc-arm-none-eabi binutils-arm-none-eabi
- name: Build firmware
run: |
make
mkdir -p build
cp path/to/firmware.elf build/firmware.elf
- name: Upload firmware artifact
uses: actions/upload-artifact@v4
with:
name: firmware
path: build/firmware.elf
hardware-test:
runs-on: ubuntu-24.04
needs: build-firmware
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download firmware artifact
uses: actions/download-artifact@v4
with:
name: firmware
path: build
- name: Install BenchCI
run: |
python -m pip install --upgrade pip
pip install --upgrade benchci
- name: Login to BenchCI
run: |
benchci login \
--email "$BENCHCI_EMAIL" \
--password "$BENCHCI_PASSWORD"
env:
BENCHCI_EMAIL: ${{ secrets.BENCHCI_EMAIL }}
BENCHCI_PASSWORD: ${{ secrets.BENCHCI_PASSWORD }}
- name: Run hardware test
run: |
benchci run \
--cloud \
--bench-id "$BENCHCI_BENCH_ID" \
--suite suite.yaml \
--artifact build/firmware.elf \
--verbose
env:
BENCHCI_BENCH_ID: ${{ secrets.BENCHCI_BENCH_ID }}
- name: Upload BenchCI results
if: always()
uses: actions/upload-artifact@v4
with:
name: benchci-results
path: benchci-results/
Update these paths for your project:
path/to/firmware.elf
suite.yaml
5. Push and inspect the run¶
After pushing:
GitHub builds firmware
the firmware artifact is passed to the hardware-test job
BenchCI logs in
BenchCI schedules the run on the selected bench
the Agent flashes firmware and executes the suite
BenchCI downloads results and evidence into
benchci-results/by defaultGitHub uploads results as workflow artifacts
6. Inspect in the dashboard¶
Open:
https://app.benchci.dev
Use the dashboard to inspect:
run status
bench assignment
agent assignment
event timeline
failure context
artifacts
Example suite.yaml¶
version: "1"
suite:
name: firmware_smoke
tests:
- name: boot_ok
steps:
- expect_uart:
node: dut
transport: console
contains: "[BOOT] OK"
within_ms: 3000
- name: ping
steps:
- send_uart:
node: dut
transport: console
data: "PING\n"
- expect_uart:
node: dut
transport: console
contains: "PONG"
within_ms: 1000
Expected artifacts¶
BenchCI writes results into:
benchci-results/
Typical contents include:
results.json
evidence.json
evidence.html
manifest.json
flash.log
transport-*.log
gpio.log
power.log
The exact logs depend on your bench and suite.
Evidence produced by this workflow¶
The hardware-test job also produces evidence artifacts:
benchci-results/
├── cloud_<run_id>.zip
└── ...
Inside the downloaded ZIP you should find files such as:
results.json
evidence.json
evidence.html
manifest.json
evidence.json
evidence.html
metadata.json
inputs/bench.yaml
inputs/suite.yaml
evidence.json records the firmware hash, Git metadata, CI job URL, bench/suite hashes, and traceability fields from suite.yaml. evidence.html is the human-readable report.
In the dashboard, open the run detail page to see the Evidence and Traceability sections.
Why this example matters¶
This is the workflow BenchCI is designed for:
software CI discipline
+
real hardware validation
A pull request can now build firmware, schedule a real hardware run, flash a device, validate behavior, and return machine-readable results.
Preflight diagnostics before CI¶
Before relying on GitHub Actions or another CI system, run the local readiness workflow from Diagnostics on the hardware-connected machine. Then start the cloud Agent and verify the bench appears as healthy or degraded in the dashboard.
A bench that is failing or unknown is not eligible for scheduled cloud runs.