Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
07e931b46This file is pinned to the selected release. Download the original to open it in your design tool.
name: Firmware builds
# Every composition, compiled, on every firmware change - one job each.
#
# For two months this repository shipped a firmware whose CI compiled nothing:
# the boundary and ABI checks in firmware-checks.yml finish in seconds and
# catch what a grep can catch, but a core change that broke only one edition
# was found by whoever next ran `firmware/bundles/build.sh all` at their desk.
# The 3.9.1 cycle moved the network onto its own core across a dozen files
# and reached dev without a compiler ever seeing it in CI. That is what this
# workflow closes: `build.sh one <composition>` - default, audio, performance,
# clock, midi - each in its own job, so the wall clock is one build rather
# than five in a row, and each image scanned for the marker strings that prove
# it carries exactly its features. Not every composition is on the shelf
# (clock and midi are compositions the tree keeps buildable); every one of
# them has to compile, because the point of the feature seam is that a core
# change breaks nothing it cannot see.
#
# No secrets file exists on the runner, so every image here is built the way
# a published one is (the placeholder SSID, not somebody's Wi-Fi). Nothing is
# uploaded: the shelf is cut by shelf.sh, by hand, on purpose.
on:
pull_request:
paths:
- "firmware/**"
- ".github/workflows/firmware-build.yml"
push:
branches: [main]
paths:
- "firmware/**"
workflow_dispatch:
concurrency:
group: firmware-build-${{ github.ref }}
cancel-in-progress: true
permissions: {}
jobs:
build:
name: ${{ matrix.composition }}
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
composition: [default, audio, performance, clock, midi]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
# The xtensa toolchain and the Arduino core are ~700 MB; the build tree
# under ~/pf-build keeps the framework's objects between compositions
# and between runs. Keyed on platformio.ini, which names both. Five jobs
# share the key: the first to finish saves it, the rest find it saved.
- name: Cache PlatformIO packages and the build tree
uses: actions/cache@v4
with:
path: |
~/.platformio
~/pf-build
key: pio-${{ runner.os }}-${{ hashFiles('firmware/patternflow/platformio.ini') }}
restore-keys: |
pio-${{ runner.os }}-
- name: Install PlatformIO
run: pip install --quiet platformio==6.1.19
- name: Build ${{ matrix.composition }} and scan the image for its features
run: bash firmware/bundles/build.sh one ${{ matrix.composition }}
# Flash is not the scarce resource here; internal DRAM is, and a loadable
# pattern's code budget is whatever is left of it. The size printed above
# measures the one that does not matter. This reads the composition's elf
# and fails on a static-RAM move, per composition, because the whole point
# of the split is that the blast radius differs.
- name: Internal RAM this composition has already spent
run: python firmware/toolchain/check_footprint.py --only ${{ matrix.composition }}