From 432372f78a4d56d6c3d0576ebdc4ac2d12063e29 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Tue, 20 Oct 2026 15:35:22 +0200 Subject: [PATCH] ci: add example `chiplab-cli` integration as a smoke test Unlike the Claude-driven `/smoke-test`, this needs no LLM: `chiplab-cli` runs a fixed test suite, so results are reproducible and cheap enough to run on every relevant PR. Each workflow gets its own Chiplab project so their runs don't mix. `CHIPLAB_API_KEY` must be switched to a token for the new account that owns these projects. Closes: DEV-2431 --- .github/chiplab/hello-world.test.ts | 7 ++ .github/chiplab/stm32f4-discovery.board.json | 1 + .github/workflows/chiplab-smoke.yml | 77 ++++++++++++++++++++ .github/workflows/claude-chiplab-smoke.yml | 2 +- AGENTS.md | 14 ++++ 5 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 .github/chiplab/hello-world.test.ts create mode 100644 .github/chiplab/stm32f4-discovery.board.json create mode 100644 .github/workflows/chiplab-smoke.yml diff --git a/.github/chiplab/hello-world.test.ts b/.github/chiplab/hello-world.test.ts new file mode 100644 index 0000000..a530fbc --- /dev/null +++ b/.github/chiplab/hello-world.test.ts @@ -0,0 +1,7 @@ +// Chiplab smoke test: the firmware prints "Hello world!" over the captured UART. +import { expect } from "jsr:@std/expect"; + +Deno.test("firmware greets", async () => { + const outcome = await simulation.runUntilUartLine("Hello world!", 5000); + expect(outcome.kind).toBe("matched"); +}); diff --git a/.github/chiplab/stm32f4-discovery.board.json b/.github/chiplab/stm32f4-discovery.board.json new file mode 100644 index 0000000..246d4b4 --- /dev/null +++ b/.github/chiplab/stm32f4-discovery.board.json @@ -0,0 +1 @@ +{ "model": "stm32f4_discovery", "uarts": ["usart2"] } diff --git a/.github/workflows/chiplab-smoke.yml b/.github/workflows/chiplab-smoke.yml new file mode 100644 index 0000000..c3b54e0 --- /dev/null +++ b/.github/workflows/chiplab-smoke.yml @@ -0,0 +1,77 @@ +# Deterministic Chiplab smoke test: build the bare-metal stm32f4-discovery example and +# run it on a virtual board via chiplab-cli, asserting "Hello world!" on USART2. +# Doubles as a template for integrating chiplab-cli into your own CI. +# +# Requires: +# secrets.CHIPLAB_API_KEY - Chiplab personal access token (veecle_pat_*) for the +# account owning the project below (see AGENTS.md) +# +# Every run costs Chiplab credits, so it only triggers on changes to that example. +name: Chiplab smoke test + +on: + push: + branches: [main] + paths: &paths + - "examples/bare-metal/stm32f4-discovery/**" + - ".github/chiplab/**" + - ".github/workflows/chiplab-smoke.yml" + pull_request: + paths: *paths + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + stm32f4-discovery: + name: bare-metal/stm32f4-discovery + runs-on: ubuntu-latest + timeout-minutes: 5 + # Secrets are not available to fork PRs; skip instead of failing. + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository + steps: + - uses: actions/checkout@v7 + + - uses: dtolnay/rust-toolchain@stable + with: + targets: thumbv7m-none-eabi + + - name: Build firmware + working-directory: examples/bare-metal/stm32f4-discovery + run: cargo build --release --locked + + - name: Install chiplab-cli + run: | + dir=$(mktemp -d "$RUNNER_TEMP/chiplab-cli.XXXXXX") + cd "$dir" + curl -fsSLO https://github.com/veecle/chiplab-cli/releases/latest/download/chiplab-cli-x86_64-unknown-linux-musl.tar.gz + curl -fsSLO https://github.com/veecle/chiplab-cli/releases/latest/download/sha256sums.txt + sha256sum --check --ignore-missing sha256sums.txt + tar -xzf chiplab-cli-x86_64-unknown-linux-musl.tar.gz + echo "$dir" >> "$GITHUB_PATH" + + - name: Run smoke test on Chiplab + env: + CHIPLAB_TOKEN: ${{ secrets.CHIPLAB_API_KEY }} + # "chiplab examples CI (chiplab-smoke)"; keep in sync with AGENTS.md. + CHIPLAB_PROJECT_ID: project_01m5cxr7ghex8rqx3n91nz180f + run: | + chiplab-cli run-test-suite \ + --project "$CHIPLAB_PROJECT_ID" \ + --firmware examples/bare-metal/stm32f4-discovery/target/thumbv7m-none-eabi/release/hello-stm32f4-discovery \ + --test-suite .github/chiplab/hello-world.test.ts \ + --board .github/chiplab/stm32f4-discovery.board.json \ + --download-dir chiplab-artifacts + + - name: Upload Chiplab artifacts + if: ${{ !cancelled() }} + uses: actions/upload-artifact@v7 + with: + name: chiplab-artifacts + path: chiplab-artifacts + if-no-files-found: ignore diff --git a/.github/workflows/claude-chiplab-smoke.yml b/.github/workflows/claude-chiplab-smoke.yml index eb37718..cf529fe 100644 --- a/.github/workflows/claude-chiplab-smoke.yml +++ b/.github/workflows/claude-chiplab-smoke.yml @@ -175,7 +175,7 @@ jobs: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} show_full_output: true prompt: | - Build the firmware in examples/bare-metal/stm32f4-discovery and test it on Chiplab, following the workflow in AGENTS.md. Diagnose and report any issues. + Build the firmware in examples/bare-metal/stm32f4-discovery and test it on Chiplab, following the workflow in AGENTS.md. Use the CI project_id given there for claude-chiplab-smoke.yml. Diagnose and report any issues. If the firmware does not build, or the captured UART output does not contain "Hello world!", exit with a non-zero status so the workflow fails. claude_args: | diff --git a/AGENTS.md b/AGENTS.md index 071f769..407872a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -80,6 +80,20 @@ The run returns synchronously. Read the captured output, which contains `Hello world!` (the `stm32wba52-nucleo` example prints it once per second, so you'll see several lines). +## Chiplab projects for this repo's CI + +Each of this repo's CI workflows records its runs under its own project, owned by the +account behind the `CHIPLAB_API_KEY` secret: + +| Workflow | `project_id` | +|---|---| +| `.github/workflows/chiplab-smoke.yml` | `project_01m5cxr7ghex8rqx3n91nz180f` | +| `.github/workflows/claude-chiplab-smoke.yml` | `project_01m5cy2mqrehetd0xk0p69r7xg` | + +When running in this repo's CI, use the `project_id` for your workflow; don't list or +create projects. Outside CI (on your own account), resolve or create your own project as +the discovery/help tool describes, because you won't have access to the projects above. + ## Tool reference Chiplab exposes its tools over standard MCP tool discovery — your MCP client