|
28 | 28 |
|
29 | 29 | jobs: |
30 | 30 | firmware-qemu: |
31 | | - runs-on: ubuntu-24.04 |
| 31 | + runs-on: ubuntu-22.04 |
32 | 32 | timeout-minutes: 90 |
33 | 33 | steps: |
34 | 34 | - name: Checkout |
@@ -133,55 +133,111 @@ jobs: |
133 | 133 | west twister -T soc_firmware/tests -T soc_firmware/app \ |
134 | 134 | -p qemu_riscv64 --inline-logs -v -O twister-out |
135 | 135 |
|
136 | | - - name: Dump twister handler logs on failure |
| 136 | + - name: Dump twister logs on failure |
137 | 137 | if: failure() |
138 | 138 | run: | |
139 | | - find twister-out -name "handler.log" -o -name "qemu.log" | while read -r f; do |
140 | | - echo "===== $f =====" |
| 139 | + # Twister keeps the emulator's own output in qemu.stdout / |
| 140 | + # qemu.stderr inside each build directory — NOT in handler.log, |
| 141 | + # which only carries the guest's serial console. A "unexpected |
| 142 | + # eof" verdict means the `ninja run` target died before the |
| 143 | + # harness saw its end marker, and the reason is in qemu.stderr. |
| 144 | + for f in $(find twister-out \( -name "handler.log" \ |
| 145 | + -o -name "qemu.stdout" \ |
| 146 | + -o -name "qemu.stderr" \ |
| 147 | + -o -name "device.log" \) -size +0); do |
| 148 | + echo "::group::$f" |
141 | 149 | cat "$f" |
| 150 | + echo "::endgroup::" |
142 | 151 | done |
143 | 152 |
|
144 | | - - name: QEMU smoke test on failure |
145 | | - # Re-runs the twister-built image by hand so QEMU's own stderr |
146 | | - # (bad option, missing lib, wrong binary) lands in the job log — |
147 | | - # twister swallows it. |
| 153 | + # Per-configuration verdicts, so the failing scenario is named |
| 154 | + # even when the console stayed empty. |
| 155 | + if [ -f twister-out/twister.json ]; then |
| 156 | + echo "===== scenario status =====" |
| 157 | + jq -r '.testsuites[] | "\(.status)\t\(.name)\t\(.reason // "")"' \ |
| 158 | + twister-out/twister.json || true |
| 159 | + fi |
| 160 | +
|
| 161 | + - name: Re-run a failed configuration by hand |
| 162 | + # Runs the exact `ninja run` target twister invoked, with its |
| 163 | + # output on stdout instead of in a file nobody reads. Catches the |
| 164 | + # cases twister reports only as "unexpected eof": a re-configure |
| 165 | + # error, a missing emulator binary, rejected machine arguments. |
148 | 166 | if: failure() |
149 | 167 | run: | |
| 168 | + echo "QEMU_BIN=$QEMU_BIN" |
150 | 169 | "$QEMU_BIN" --version || true |
151 | | - ELF=$(find twister-out -name zephyr.elf | head -1) |
152 | | - echo "ELF: $ELF" |
153 | | - timeout 15 "$QEMU_BIN" -machine virt -bios none -m 256 \ |
154 | | - -cpu rv64i,i=on,m=on,a=on,f=on,d=on,c=on,zicsr=on,zifencei=on,zicntr=on,pmp=on,u=on \ |
155 | | - -global virtio-mmio.force-legacy=false -nographic \ |
156 | | - -netdev user,id=n1 -device virtio-net-device,netdev=n1,bus=virtio-mmio-bus.0 \ |
157 | | - -kernel "$ELF" 2>&1 | head -40 || true |
| 170 | +
|
| 171 | + DIR=$(jq -r '[.testsuites[] | select(.status != "passed")][0].name // empty' \ |
| 172 | + twister-out/twister.json 2>/dev/null) |
| 173 | + echo "first failing scenario: ${DIR:-<unknown>}" |
| 174 | +
|
| 175 | + # Map the scenario back to its build directory; fall back to any |
| 176 | + # build directory that has a zephyr.elf. |
| 177 | + BUILD=$(find twister-out -name build.ninja -printf '%h\n' | head -1) |
| 178 | + if [ -n "$DIR" ]; then |
| 179 | + CAND=$(find twister-out -type d -name "$(basename "$DIR")" | head -1) |
| 180 | + [ -n "$CAND" ] && BUILD="$CAND" |
| 181 | + fi |
| 182 | + echo "build dir: $BUILD" |
| 183 | +
|
| 184 | + # `run` needs a reader on the fifo or QEMU blocks; give it one. |
| 185 | + mkfifo "$BUILD/qemu-fifo.in" "$BUILD/qemu-fifo.out" 2>/dev/null || true |
| 186 | + timeout 30 ninja -C "$BUILD" run < /dev/null 2>&1 | tail -60 || true |
158 | 187 |
|
159 | 188 | - name: Upload twister artifacts |
160 | 189 | # Skipped under act: no artifact service (ACTIONS_RUNTIME_TOKEN). |
161 | 190 | if: ${{ always() && !env.ACT }} |
162 | 191 | uses: actions/upload-artifact@v4 |
163 | 192 | with: |
164 | 193 | name: twister-out |
165 | | - path: twister-out/**/handler.log |
| 194 | + path: | |
| 195 | + twister-out/twister.json |
| 196 | + twister-out/twister.log |
| 197 | + twister-out/**/handler.log |
| 198 | + twister-out/**/qemu.stdout |
| 199 | + twister-out/**/qemu.stderr |
| 200 | + twister-out/**/build.log |
166 | 201 | if-no-files-found: ignore |
167 | 202 |
|
168 | 203 | - name: Build QEMU image (TAP networking) |
169 | 204 | run: west build -b qemu_riscv64 -d soc_firmware/app/build_qemu soc_firmware/app |
170 | 205 |
|
| 206 | + # ---- NMOS conformance: needs a host TAP device ---- |
| 207 | + # Creating "zeth" requires NET_ADMIN, which act's container does not |
| 208 | + # have by default ("Failed to send flush request: Operation not |
| 209 | + # permitted"). The steps below are therefore skipped under act; to |
| 210 | + # run them locally anyway, give the container the capability: |
| 211 | + # |
| 212 | + # act --container-options "--cap-add=NET_ADMIN --device=/dev/net/tun" |
| 213 | + # |
| 214 | + # Everything up to and including twister runs under act unchanged. |
171 | 215 | - name: TAP interface for QEMU |
| 216 | + if: ${{ !env.ACT }} |
172 | 217 | run: sudo scripts/ci/qemu-net-setup.sh |
173 | 218 |
|
174 | 219 | - name: Fetch nmos-testing |
| 220 | + if: ${{ !env.ACT }} |
175 | 221 | run: git clone --depth 1 https://github.com/AMWA-TV/nmos-testing "$RUNNER_TEMP/nmos-testing" |
176 | 222 |
|
177 | 223 | - name: NMOS conformance (IS-04 / IS-05 / IS-08) |
| 224 | + if: ${{ !env.ACT }} |
178 | 225 | run: | |
179 | 226 | NMOS_TESTING="$RUNNER_TEMP/nmos-testing" \ |
180 | 227 | BUILD_DIR="$PWD/soc_firmware/app/build_qemu" \ |
181 | 228 | RESULTS_DIR="$PWD/nmos-results" \ |
182 | 229 | QEMU="$QEMU_BIN" \ |
183 | 230 | scripts/ci/run-nmos-conformance.sh |
184 | 231 |
|
| 232 | + - name: Note skipped steps (act) |
| 233 | + # So a green local run is not mistaken for full coverage. |
| 234 | + if: ${{ env.ACT }} |
| 235 | + run: | |
| 236 | + echo "Skipped under act: TAP setup + NMOS conformance (no NET_ADMIN)." |
| 237 | + echo "Built and ran: twister unit suites + QEMU boot test." |
| 238 | + echo "To include NMOS locally, re-run act with:" |
| 239 | + echo " --container-options \"--cap-add=NET_ADMIN --device=/dev/net/tun\"" |
| 240 | +
|
185 | 241 | - name: Upload NMOS results |
186 | 242 | # Skipped under act: no artifact service (ACTIONS_RUNTIME_TOKEN). |
187 | 243 | if: ${{ always() && !env.ACT }} |
|
0 commit comments