Skip to content

Commit addcbbd

Browse files
authored
ci: build the board, run twister, and a scoped compliance pass
Build matrix (default/audio/ir/ble/wifi/demo) + native_sim twister + scoped compliance on the official Zephyr CI container, replacing the verify.sh-only workflow. Closes #17.
1 parent c84e8d3 commit addcbbd

5 files changed

Lines changed: 228 additions & 4 deletions

File tree

.checkpatch.conf

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--emacs
2+
--summary-file
3+
--show-types
4+
--max-line-length=100
5+
--min-conf-desc-length=1
6+
--typedefsfile=scripts/checkpatch/typedefsfile
7+
8+
--ignore PRINTK_WITHOUT_KERN_LEVEL
9+
--ignore SPLIT_STRING
10+
--ignore VOLATILE
11+
--ignore CONFIG_EXPERIMENTAL
12+
--ignore PREFER_KERNEL_TYPES
13+
--ignore PREFER_SECTION
14+
--ignore AVOID_EXTERNS
15+
--ignore NETWORKING_BLOCK_COMMENT_STYLE
16+
--ignore DATE_TIME
17+
--ignore MINMAX
18+
--ignore CONST_STRUCT
19+
--ignore FILE_PATH_CHANGES
20+
--ignore SPDX_LICENSE_TAG
21+
--ignore C99_COMMENT_TOLERANCE
22+
--ignore REPEATED_WORD
23+
--ignore UNDOCUMENTED_DT_STRING
24+
--ignore DT_SPLIT_BINDING_PATCH
25+
--ignore DT_SCHEMA_BINDING_PATCH
26+
--ignore TRAILING_SEMICOLON
27+
--ignore COMPLEX_MACRO
28+
--ignore MULTISTATEMENT_MACRO_USE_DO_WHILE
29+
--ignore ENOSYS
30+
--ignore IS_ENABLED_CONFIG
31+
--ignore EXPORT_SYMBOL
32+
--ignore COMPARISON_TO_NULL

.gitattributes

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Normalize source/text files to LF in the repository regardless of the
2+
# checkout or edit host. Windows tooling can leave CRLF in the working copy;
3+
# pinning the committed blobs to LF keeps bash/python runnable under WSL/Linux
4+
# and stops checkpatch from flagging DOS line endings. git applies this on
5+
# checkin, so a CRLF working copy still commits as LF (and compares as LF, so
6+
# it does not show as modified).
7+
*.sh text eol=lf
8+
*.py text eol=lf
9+
*.c text eol=lf
10+
*.h text eol=lf
11+
*.dts text eol=lf
12+
*.dtsi text eol=lf
13+
*.overlay text eol=lf
14+
*.conf text eol=lf
15+
*.yml text eol=lf
16+
*.yaml text eol=lf
17+
*.cmake text eol=lf
18+
*.md text eol=lf
19+
*.rst text eol=lf
20+
CMakeLists.txt text eol=lf
21+
Kconfig* text eol=lf
22+
.checkpatch.conf text eol=lf

.github/workflows/ci.yml

Lines changed: 168 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,180 @@
11
name: CI
22

3+
# Build the firmware for every overlay, run the native_sim unit tests, and run a
4+
# scoped Zephyr compliance pass (issue #17). The board, drivers and dts-bindings
5+
# live out-of-tree in this repo and are built against a pinned upstream Zephyr
6+
# via BOARD_ROOT + ZEPHYR_EXTRA_MODULES, mirroring scripts/build_m5sticks3.sh.
7+
38
on:
49
push:
10+
branches: [main]
511
pull_request:
612

13+
concurrency:
14+
group: ci-${{ github.ref }}
15+
cancel-in-progress: true
16+
17+
# The Zephyr CI container runs `run:` steps with `sh` by default; force bash so
18+
# the build step's bash arrays parse.
19+
defaults:
20+
run:
21+
shell: bash
22+
23+
env:
24+
# Pinned upstream Zephyr. Keep this in sync with the container tag (the ghcr ci
25+
# image is hard-coded in each job's `container:`) and the SDK path below: the
26+
# image must bundle the Zephyr SDK this revision wants (zephyr/SDK_VERSION).
27+
ZEPHYR_REV: v4.4.0
28+
# GitHub overrides HOME for container jobs, so the SDK's own cmake package
29+
# registry is not found. Point cmake straight at the SDK the image bundles, or
30+
# every build and twister run fails to locate a toolchain.
31+
ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-1.0.1
32+
733
jobs:
834
repo-integrity:
935
runs-on: ubuntu-latest
1036
steps:
1137
- uses: actions/checkout@v4
12-
- name: Run repository integrity checks
38+
- name: Repository integrity checks
1339
run: bash verify.sh
40+
41+
build:
42+
runs-on: ubuntu-latest
43+
timeout-minutes: 30
44+
container: ghcr.io/zephyrproject-rtos/ci:v0.29.1
45+
strategy:
46+
fail-fast: false
47+
matrix:
48+
include:
49+
- { name: default, overlay: "", blob: false }
50+
- { name: audio, overlay: "overlay-audio.conf", blob: false }
51+
- { name: ir, overlay: "overlay-ir.conf", blob: false }
52+
- { name: ble, overlay: "overlay-ble.conf", blob: true }
53+
- { name: wifi, overlay: "overlay-wifi.conf", dtc: "overlay-wifi.overlay", blob: true }
54+
- { name: demo, overlay: "overlay-ble.conf;overlay-audio.conf;overlay-ir.conf", blob: true }
55+
steps:
56+
- uses: actions/checkout@v4
57+
with:
58+
path: repo
59+
- name: Cache Zephyr workspace
60+
uses: actions/cache@v4
61+
with:
62+
path: |
63+
ws/.west
64+
ws/zephyr
65+
ws/modules
66+
ws/bootloader
67+
ws/tools
68+
key: zephyr-ws-${{ env.ZEPHYR_REV }}
69+
- name: Set up Zephyr workspace
70+
run: |
71+
if [ ! -d ws/.west ]; then
72+
west init -m https://github.com/zephyrproject-rtos/zephyr --mr "$ZEPHYR_REV" ws
73+
fi
74+
cd ws && west update --narrow -o=--depth=1 && west zephyr-export
75+
- name: Fetch Espressif HAL blobs
76+
if: ${{ matrix.blob }}
77+
run: cd ws && west blobs fetch hal_espressif
78+
- name: Build (${{ matrix.name }})
79+
working-directory: ws
80+
env:
81+
BOARD_ROOT: ${{ github.workspace }}/repo
82+
ZEPHYR_EXTRA_MODULES: ${{ github.workspace }}/repo
83+
run: |
84+
args=(-p always -b m5stack_sticks3/esp32s3/procpu "$GITHUB_WORKSPACE/repo/app")
85+
extra=()
86+
if [ -n "${{ matrix.overlay }}" ]; then
87+
extra+=(-DEXTRA_CONF_FILE="${{ matrix.overlay }}")
88+
fi
89+
if [ -n "${{ matrix.dtc }}" ]; then
90+
extra+=(-DEXTRA_DTC_OVERLAY_FILE="${{ matrix.dtc }}")
91+
fi
92+
if [ ${#extra[@]} -gt 0 ]; then
93+
args+=(-- "${extra[@]}")
94+
fi
95+
west build "${args[@]}"
96+
97+
twister:
98+
runs-on: ubuntu-latest
99+
timeout-minutes: 30
100+
container: ghcr.io/zephyrproject-rtos/ci:v0.29.1
101+
steps:
102+
- uses: actions/checkout@v4
103+
with:
104+
path: repo
105+
- name: Cache Zephyr workspace
106+
uses: actions/cache@v4
107+
with:
108+
path: |
109+
ws/.west
110+
ws/zephyr
111+
ws/modules
112+
ws/bootloader
113+
ws/tools
114+
key: zephyr-ws-${{ env.ZEPHYR_REV }}
115+
- name: Set up Zephyr workspace
116+
run: |
117+
if [ ! -d ws/.west ]; then
118+
west init -m https://github.com/zephyrproject-rtos/zephyr --mr "$ZEPHYR_REV" ws
119+
fi
120+
cd ws && west update --narrow -o=--depth=1 && west zephyr-export
121+
- name: Twister (native_sim)
122+
working-directory: ws
123+
env:
124+
ZEPHYR_EXTRA_MODULES: ${{ github.workspace }}/repo
125+
run: west twister -p native_sim --inline-logs -v -T "$GITHUB_WORKSPACE/repo/tests"
126+
- name: Upload twister output on failure
127+
if: ${{ failure() }}
128+
uses: actions/upload-artifact@v4
129+
with:
130+
name: twister-out
131+
path: ws/twister-out/**/*.log
132+
if-no-files-found: ignore
133+
134+
compliance:
135+
# PRs only: the checks run over the PR's own commits (base..head). On a push
136+
# to main the range is the squash-merge commit, which carries no body and no
137+
# Signed-off-by, so Gitlint/Identity would false-fail there.
138+
if: ${{ github.event_name == 'pull_request' }}
139+
runs-on: ubuntu-latest
140+
timeout-minutes: 20
141+
container: ghcr.io/zephyrproject-rtos/ci:v0.29.1
142+
steps:
143+
- uses: actions/checkout@v4
144+
with:
145+
path: repo
146+
fetch-depth: 0
147+
- name: Cache Zephyr workspace
148+
uses: actions/cache@v4
149+
with:
150+
path: |
151+
ws/.west
152+
ws/zephyr
153+
ws/modules
154+
ws/bootloader
155+
ws/tools
156+
key: zephyr-ws-${{ env.ZEPHYR_REV }}
157+
- name: Set up Zephyr workspace
158+
run: |
159+
if [ ! -d ws/.west ]; then
160+
west init -m https://github.com/zephyrproject-rtos/zephyr --mr "$ZEPHYR_REV" ws
161+
fi
162+
cd ws && west update --narrow -o=--depth=1 && west zephyr-export
163+
- name: Compliance (subset that fits an out-of-tree module repo)
164+
working-directory: repo
165+
env:
166+
ZEPHYR_BASE: ${{ github.workspace }}/ws/zephyr
167+
run: |
168+
git config --global --add safe.directory "$GITHUB_WORKSPACE/repo"
169+
# Run only the checks that are meaningful for this repo's layout. These
170+
# are deliberately NOT run because they false-fail on an out-of-tree
171+
# module/showcase repo, not on a real defect:
172+
# Kconfig / SysbuildKconfig - our own CONFIG_* live in this module,
173+
# which the compliance Kconfig pass does not load, so it reports
174+
# them as undefined references.
175+
# LicenseAndCopyrightCheck / BinaryFiles - flag the evidence/ media
176+
# and serial logs (records kept on purpose), not source.
177+
# ClangFormat - the tree follows checkpatch, not clang-format.
178+
python3 "$ZEPHYR_BASE/scripts/ci/check_compliance.py" \
179+
-c "${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}" \
180+
-m Checkpatch -m Gitlint -m Identity -m DevicetreeBindings -m Nits

app/src/audio.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,8 @@ static int loop_tx(const int16_t *block)
401401
if (ret < 0) {
402402
/* Slab exhausted: a prior underrun left the I2S in ERROR still holding
403403
* the TX blocks. PREPARE is the ONLY recovery from ERROR and frees the
404-
* queued blocks back to the slab (DROP does not). Then retry once. */
404+
* queued blocks back to the slab (DROP does not). Then retry once.
405+
*/
405406
(void)i2s_trigger(i2s_dev, I2S_DIR_BOTH, I2S_TRIGGER_PREPARE);
406407
ret = k_mem_slab_alloc(&tx_slab, &mem, K_MSEC(LOOP_IO_TIMEOUT_MS));
407408
if (ret < 0) {
@@ -809,7 +810,8 @@ static void do_play(void)
809810
* it is what frees the held mem_slab blocks (DROP from ERROR does not, so the
810811
* pool leaks empty -> -EAGAIN). Then play TX-ONLY, mirroring the proven
811812
* self-test. (Full-duplex playback under-ran at ~256 ms: the RX read stalled
812-
* TX.) */
813+
* TX.)
814+
*/
813815
(void)i2s_trigger(i2s_dev, I2S_DIR_BOTH, I2S_TRIGGER_DROP);
814816
(void)i2s_trigger(i2s_dev, I2S_DIR_BOTH, I2S_TRIGGER_PREPARE);
815817
audio_codec_start_output(codec_dev);

app/src/audio.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ void audio_record_request(void);
9191
void audio_play_request(void);
9292

9393
/* Ask the audio thread to stop the in-progress recording early (keeps what was
94-
* captured so far). A no-op when not recording. */
94+
* captured so far). A no-op when not recording.
95+
*/
9596
void audio_record_stop_request(void);
9697

9798
/* Current record/playback state, for the UI. */

0 commit comments

Comments
 (0)