From cab356699a7d6007fe12d7d25cb3f26f4a21f0b5 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Sat, 29 Aug 2026 16:39:51 +0800 Subject: [PATCH] ci: enforce the name equality rules/mcpp.toml calls load-bearing rules/mcpp.toml states that the package name and the module name are kept EQUAL, and that this is what makes the package work on every engine rather than on the newest one. Nothing enforced it. The check next to this one compares the three versions, which is a different invariant. mcpp before 2026.8.29.1 registers a host module under the dependency's `package.name`; from that release it uses the name the interface declares. Only equality satisfies both. The break is asymmetric, so one compiler cannot reveal it: renaming either alone still builds under GCC, which locates a BMI by its declared name through gcm.cache, and fails under Clang and MSVC, which are handed an explicit `=` mapping built from the registered name. A consumer on an older engine would see this package work on one compiler and not on the others. Both names are read in a single awk rather than a `sed | head -1` pipeline, so a successful match cannot be reported as 141 through SIGPIPE under `pipefail`, and an empty result fails instead of passing -- an extractor that matched nothing would otherwise report success on a file it never parsed. Comment lines begin with `#` and match neither pattern, so the prose in this very file that explains the rule cannot answer the assertion. Measured: passes on the current tree, red when the package name is changed, green again once restored. --- .github/workflows/ci.yml | 45 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 606e5e3..421dd21 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -183,6 +183,51 @@ jobs: [ "$lib" = "$rule" ] || { echo "FAIL: grpcgen ($rule) != grpc ($lib)"; rc=1; } exit $rc + # rules/mcpp.toml states that the package name and the module name are + # kept EQUAL, and that this is what makes the package work on every + # engine. Nothing enforced it: the check above compares versions. + # + # mcpp < 2026.8.29.1 registers a host module under the dependency's + # `package.name`; from that release it uses the name the interface + # declares. Only equality satisfies both. + # + # ⚠️ AND THE BREAK IS ASYMMETRIC, so one compiler cannot reveal it: + # renaming either alone still builds under GCC, which finds a BMI by its + # declared name through gcm.cache, and fails under Clang and MSVC, which + # are handed an explicit `=` mapping built from the registered + # name. This repository's own header says so; now something checks it. + - name: the rule's package name and module name must match + shell: bash + run: | + set -euo pipefail + toml=rules/mcpp.toml + iface=rules/src/grpcgen.cppm + test -f "$toml" || { echo "FAIL: no $toml"; exit 1; } + test -f "$iface" || { echo "FAIL: no $iface"; exit 1; } + # One awk, no pipeline: `... | head -1` would let the writer take + # SIGPIPE and, under `pipefail`, report 141 for a successful match. + # Comment lines begin with '#' and match neither pattern, so the + # prose in this file that explains the rule cannot satisfy it. + pkg=$(awk '/^\[package\]/{p=1;next} /^\[/{p=0} + p && /^[[:space:]]*name[[:space:]]*=/ { + if (match($0, /"[^"]*"/)) { + print substr($0, RSTART+1, RLENGTH-2); exit } }' "$toml") + mod=$(awk '/^[[:space:]]*export[[:space:]]+module[[:space:]]+/ { + sub(/^[[:space:]]*export[[:space:]]+module[[:space:]]+/, "") + sub(/[[:space:]]*;.*$/, "") + print; exit }' "$iface") + echo "package.name='${pkg}' export module='${mod}'" + # Both must be non-empty. An extractor that matched nothing would + # otherwise report success on a file it never parsed. + [ -n "$pkg" ] || { echo "FAIL: could not read [package].name from $toml"; exit 1; } + [ -n "$mod" ] || { echo "FAIL: could not read 'export module' from $iface"; exit 1; } + [ "$pkg" = "$mod" ] || { + echo "FAIL: package name '$pkg' != module name '$mod'" + echo "Consumers on mcpp < 2026.8.29.1 import the package name;" + echo "from 2026.8.29.1 they import the declared name. Keep them equal." + exit 1; } + echo "OK: both are '$pkg'" + template-matches-example: name: templates/greeter == examples/greeter runs-on: ubuntu-latest