From b397bb2b22c0398b05b099a6e0936a1c6c05c66a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabr=C3=ADcio=20Bracht?= Date: Fri, 9 Oct 2026 15:50:55 -0700 Subject: [PATCH 1/2] install mosquitto from the ubuntu archive in conformance ci --- .github/workflows/conformance.yml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml index 1b763cdb..c724cbed 100644 --- a/.github/workflows/conformance.yml +++ b/.github/workflows/conformance.yml @@ -116,11 +116,12 @@ jobs: - name: Start Mosquitto run: | - mkdir -p mosquitto-config - printf 'listener 1883 0.0.0.0\nallow_anonymous true\n' > mosquitto-config/mosquitto.conf - docker run -d --name mosquitto-interop -p 1883:1883 \ - -v "$PWD/mosquitto-config:/mosquitto/config" \ - public.ecr.aws/docker/library/eclipse-mosquitto:2 + sudo apt-get update + sudo apt-get install -y mosquitto + sudo systemctl stop mosquitto + mosquitto -h | head -1 + printf 'listener 1883 0.0.0.0\nallow_anonymous true\n' > mosquitto.conf + nohup mosquitto -c mosquitto.conf -v > mosquitto.log 2>&1 & for i in $(seq 1 30); do if timeout 1 bash -c '/dev/null; then echo "mosquitto ready after ${i}s" @@ -129,7 +130,7 @@ jobs: sleep 1 done echo "mosquitto did not become ready in time" >&2 - docker logs mosquitto-interop || true + cat mosquitto.log || true exit 1 - name: Run deferred-ack conformance against Mosquitto @@ -141,11 +142,11 @@ jobs: - name: Mosquitto log if: always() - run: docker logs mosquitto-interop || true + run: cat mosquitto.log || true - name: Stop Mosquitto if: always() - run: docker rm -f mosquitto-interop || true + run: pkill -x mosquitto || true - name: Upload report uses: actions/upload-artifact@v4 From 773a5d9052288505753d1ba31a4a99d157b408ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabr=C3=ADcio=20Bracht?= Date: Sat, 10 Oct 2026 09:40:12 -0700 Subject: [PATCH 2/2] pin the mosquitto interop runner and harden its broker start --- .github/workflows/conformance.yml | 34 +++++++++++++------ crates/mqtt5-conformance/CONFORMANCE_DIARY.md | 12 +++++++ 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml index c724cbed..4427116f 100644 --- a/.github/workflows/conformance.yml +++ b/.github/workflows/conformance.yml @@ -101,7 +101,7 @@ jobs: mosquitto-interop: name: Conformance (Mosquitto interop) - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 @@ -118,11 +118,18 @@ jobs: run: | sudo apt-get update sudo apt-get install -y mosquitto - sudo systemctl stop mosquitto - mosquitto -h | head -1 - printf 'listener 1883 0.0.0.0\nallow_anonymous true\n' > mosquitto.conf - nohup mosquitto -c mosquitto.conf -v > mosquitto.log 2>&1 & + sudo systemctl disable --now mosquitto + dpkg-query -W mosquitto + mkdir -p mosquitto-run + printf 'listener 1883 0.0.0.0\nallow_anonymous true\n' > mosquitto-run/mosquitto.conf + mosquitto -c mosquitto-run/mosquitto.conf -v > mosquitto-run/mosquitto.log 2>&1 & + echo $! > mosquitto-run/mosquitto.pid for i in $(seq 1 30); do + if ! kill -0 "$(cat mosquitto-run/mosquitto.pid)" 2>/dev/null; then + echo "mosquitto exited before becoming ready" >&2 + cat mosquitto-run/mosquitto.log >&2 || true + exit 1 + fi if timeout 1 bash -c '/dev/null; then echo "mosquitto ready after ${i}s" exit 0 @@ -130,7 +137,7 @@ jobs: sleep 1 done echo "mosquitto did not become ready in time" >&2 - cat mosquitto.log || true + cat mosquitto-run/mosquitto.log >&2 || true exit 1 - name: Run deferred-ack conformance against Mosquitto @@ -140,13 +147,20 @@ jobs: --report conformance-report-mosquitto.json \ deferred_qos2 - - name: Mosquitto log + - name: Stop Mosquitto if: always() - run: cat mosquitto.log || true + run: | + if [ -f mosquitto-run/mosquitto.pid ]; then + kill "$(cat mosquitto-run/mosquitto.pid)" || true + fi - - name: Stop Mosquitto + - name: Upload Mosquitto log if: always() - run: pkill -x mosquitto || true + uses: actions/upload-artifact@v4 + with: + name: broker-log-mosquitto + path: mosquitto-run/mosquitto.log + if-no-files-found: ignore - name: Upload report uses: actions/upload-artifact@v4 diff --git a/crates/mqtt5-conformance/CONFORMANCE_DIARY.md b/crates/mqtt5-conformance/CONFORMANCE_DIARY.md index 9a7644da..96fed303 100644 --- a/crates/mqtt5-conformance/CONFORMANCE_DIARY.md +++ b/crates/mqtt5-conformance/CONFORMANCE_DIARY.md @@ -38,6 +38,18 @@ ## Diary Entries +### Mosquitto interop job: Ubuntu archive package instead of a registry image (2026-10-09) + +**Trigger**: the Mosquitto interop job failed on PR #210 before any test ran. Docker Hub refused `eclipse-mosquitto:2` with `toomanyrequests: You have reached your unauthenticated pull rate limit`. #214 moved the pull to the ECR Public mirror (same digest, `sha256:38c0da4f…`), and the next run failed there with `toomanyrequests: Rate exceeded`. Hosted runners share IP addresses, so any anonymous registry pull can hit a limit, and logging in does not help pull requests from forks, which get no secrets. + +**Change**: the job installs `mosquitto` from the Ubuntu archive, runs `systemctl disable --now mosquitto` so the packaged service cannot answer on 1883, and starts its own process with the same config (`listener 1883 0.0.0.0`, `allow_anonymous true`). The readiness loop fails if that process exits, the process is stopped by PID, and its log is uploaded as the `broker-log-mosquitto` artifact. `runs-on` is pinned to `ubuntu-24.04`, so the Mosquitto version only moves when the pin does. + +**Version under test**: 2.0.18 (Ubuntu 24.04). `eclipse-mosquitto:2` had moved to 2.1.2. The fixture is `mosquitto-2.x.toml` and the job runs only `deferred_qos2`. + +**Checked locally** with the conformance CLI and the same command the job runs: against Ubuntu 24.04's package in a container (2.0.18), both `deferred_qos2` tests pass; against `eclipse-mosquitto:2` (2.1.2), both pass; with no broker on 1883, both fail. + +**Known gap**: the fixture's `restart_command` is `systemctl restart mosquitto`, which would restart the packaged service rather than the job's process. No conformance test calls `restart()` today, and the Docker setup did not match the hook either. + ### Statement text drift cleared: all 77 entries corrected against the normative body (2026-10-01) **Trigger**: issue #166, part 1. `known-text-drift.txt` listed 77 statements whose manifest text did not correspond to the reference text for their ID. The client audit for #164 had taken wrong IDs from the manifest as a result (the manifest filed "Client without session state receiving Session Present=1 MUST close" under MQTT-3.2.2-5; it is MQTT-3.2.2-4).