From d2d94b99b47e87e16ea7e3d398f96cde8c5169c2 Mon Sep 17 00:00:00 2001 From: Boernsman <5207214+Boernsman@users.noreply.github.com> Date: Sat, 10 Oct 2026 12:24:38 +0200 Subject: [PATCH] fix: the unit design gate could not fail, and the release found out The v0.1.1 release build failed in Doxygen, on sources that CI had just passed. Two defects, and the second is the one worth reading. **A bare \dot in prose.** 00-mainpage.dox describes where the diagrams come from and wrote the directive literally. Ubuntu's doxygen 1.9 reads that as the START of a dot block and then hits end of file looking for the end of it; 1.18, which is what I had locally, does not. So the same sources passed here and failed on the runner. Escaped as @c \\dot, which is the convention the rest of that file already uses for \implements and \param, and udd.sh now prints the doxygen version, because a log that does not name the tool cannot show a version difference. **The CI gate could not fail.** The step ran `tools/udd.sh | tee udd.log`, and GitHub runs these steps with `bash -e` and NOT pipefail, so the pipeline reported tee's exit status and swallowed the script's. Every Doxygen failure this job existed to catch was invisible to it, for as long as it has existed. The release workflow runs udd.sh without a pipe, which is the only reason this was found at all. Measured rather than assumed: with a deliberate broken block in the sources, `set -o pipefail; tools/udd.sh | tee` exits 1 and `tools/udd.sh | tee` exits 0. This is the same mistake as the `|| true` that hid the QEMU job failing three different ways. A gate that cannot fail is worse than no gate, because it gets counted as evidence -- and this one was counted in a release note. --- .github/workflows/ci.yml | 14 +++++++++++++- firmware/supervisor/doc/00-mainpage.dox | 2 +- tools/udd.sh | 8 ++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4943927..217f286 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -484,7 +484,19 @@ jobs: run: sudo apt-get update -qq && sudo apt-get install -y -qq doxygen graphviz - name: Generate, with documentation warnings as errors - run: tools/udd.sh | tee udd.log + run: | + # `set -o pipefail`, and it is not decoration: GitHub runs these + # steps with `bash -e` and NOT pipefail, so `tools/udd.sh | tee` + # reported tee's exit status and swallowed the script's. This gate + # had been green on those terms for as long as it has existed, and + # the release workflow -- which runs udd.sh without a pipe -- is + # what found the Doxygen failure this job could not fail on. + # + # The same mistake as the `|| true` that hid the QEMU job's three + # different failures. A gate that cannot fail is worse than no gate, + # because it is counted as evidence. + set -o pipefail + tools/udd.sh | tee udd.log - name: Summarise what the document covers if: always() diff --git a/firmware/supervisor/doc/00-mainpage.dox b/firmware/supervisor/doc/00-mainpage.dox index 4f5b464..0421fbf 100644 --- a/firmware/supervisor/doc/00-mainpage.dox +++ b/firmware/supervisor/doc/00-mainpage.dox @@ -82,7 +82,7 @@ documented in @ref selfcheck.h : @section udd_diagrams The two diagrams -Both are drawn from `\dot` blocks in the headers beside the code they +Both are drawn from @c \\dot blocks in the headers beside the code they describe, so they are versioned with it and cannot drift from it the way a picture in another document does: diff --git a/tools/udd.sh b/tools/udd.sh index fa414d5..a69c1ca 100755 --- a/tools/udd.sh +++ b/tools/udd.sh @@ -33,6 +33,14 @@ for arg in "$@"; do esac done +# Named in the output because the version matters and has bitten: Ubuntu's +# doxygen 1.9 treats a bare \dot in prose as the start of a dot block where +# 1.18 does not, so the same sources passed here and failed in CI. A log that +# does not say which tool produced it cannot show that. +if command -v doxygen >/dev/null 2>&1; then + echo "doxygen: $(doxygen --version)" +fi + if ! command -v doxygen >/dev/null 2>&1; then echo "doxygen is not installed." >&2 echo " macOS: brew install doxygen" >&2