GitHub Action
Build firmware and run it on real hardware with onmcu/onmcu-action.
onmcu/onmcu-action installs the OnMCU CLI and runs firmware on real hardware. The step fails if the hardware job fails, is cancelled, or times out.
Quick start
name: Hardware
on: [push]
permissions:
contents: read
jobs:
run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build firmware
run: cargo build --release
- name: Run on real hardware
uses: onmcu/onmcu-action@v1
with:
board: NUCLEO-H743ZI
file: target/thumbv7em-none-eabihf/release/my-firmware
api-key: ${{ secrets.ONMCU_API_KEY }}Create ONMCU_API_KEY as a repository or organization secret before running the workflow.
Inputs
| Input | Required | Default | Description |
|---|---|---|---|
board | yes | — | Board identifier, for example NUCLEO-H743ZI. |
file | yes | — | Firmware path, resolved relative to working-directory. |
api-key | yes | — | OnMCU API key. Always pass a GitHub secret. |
server | no | https://ctrl1.onmcu.com | OnMCU controller URL. |
version | no | latest | CLI release, such as 0.4.1, or latest. An optional leading v is accepted. |
chunk-size | no | 5 | Upload chunk size in MiB. |
retries | no | 3 | Retries for each failed upload chunk. |
timeout | no | 600 | Maximum hardware job runtime in seconds. |
working-directory | no | . | Directory where the onmcu run command executes. |
args | no | empty | Extra raw options appended to onmcu run. |
Pin the CLI version
onmcu/onmcu-action@v1 pins the action's major version. The version input selects the CLI release. Set both if a CLI update must not change a run.
Build Rust and capture the ELF
Use Cargo's JSON output to find the linked executable without guessing its path:
- name: Provision Rust toolchain and targets
run: rustup show
- uses: Swatinem/rust-cache@v2
- name: Build
id: build
run: |
set -euo pipefail
shopt -s inherit_errexit
elf=$(cargo build --release --message-format=json \
| jq -r 'select(.reason=="compiler-artifact" and .executable!=null) | .executable' \
| tail -n1)
echo "elf=$elf" >> "$GITHUB_OUTPUT"
- name: Run on real hardware
uses: onmcu/onmcu-action@v1
with:
board: NUCLEO-H743ZI
file: ${{ steps.build.outputs.elf }}
api-key: ${{ secrets.ONMCU_API_KEY }}inherit_errexit makes the step fail if the build inside the command substitution fails.
Serial logging and other CLI options
Use args for optional onmcu run flags:
- uses: onmcu/onmcu-action@v1
with:
board: NUCLEO-F401RE
file: build/serial-test.elf
api-key: ${{ secrets.ONMCU_API_KEY }}
args: --logging serial --baud 115200The action splits args on spaces. Use it for CLI options, not for untrusted input.
Working directory
When the firmware crate lives below the repository root, set the same directory for the build and run steps:
- name: Build
working-directory: firmware/nucleo-h743zi
run: cargo build --release
- uses: onmcu/onmcu-action@v1
with:
working-directory: firmware/nucleo-h743zi
board: NUCLEO-H743ZI
file: target/thumbv7em-none-eabihf/release/my-firmware
api-key: ${{ secrets.ONMCU_API_KEY }}What the action does
- Reuses a compatible
onmcualready onPATH, or downloads the requested CLI release. - Writes an ephemeral
onmcu-ci.tomlunderRUNNER_TEMPwith the server, upload, retry, and timeout inputs. - Exposes the API key as
ONMCU_API_KEYonly to the run step. - Invokes
onmcu run --api-key-from-envwith the selected board and firmware.
The CLI's exit code becomes the action step's exit code.
Minimize hardware runs on pull requests
For a repository with one directory per board, use a paths filter and a matrix to run only the firmware that changed. See the c-examples workflow: a board change runs that board, while a shared-library change runs every board.