feat: S08.03 slice 5 BDD harness pointed at FreeRTOS-on-QEMU target#305
Conversation
Slice 5 of S08.03 (#304). Establishes the harness that lets BDD scenarios run against the FreeRTOS-on-QEMU target alongside the existing Linux/Windows runs. - target_driver.py module abstracts the example-spawn behind a BDD_TARGET env var; FreeRTOS dispatches to qemu-system-arm with the cross-built ELF, Linux/Windows keep the existing native subprocess flow. Same prompt-protocol over stdin/stdout (ExampleInteractive prints SolidSyslog> on every target) so wait_for_prompt / send_command are unchanged. - Per-target oracle pairs in ci/docker-compose.bdd.yml and .devcontainer/docker-compose.yml: syslog-ng-linux + behave-linux, syslog-ng-freertos + behave-freertos. Pairs never run together; network_mode: service:syslog-ng-freertos gives the FreeRTOS pair a shared netns so QEMU's slirp gateway 10.0.2.2 NATs to the pair's loopback. Both oracles alias as syslog-ng for backwards-compat. - bdd-freertos-qemu CI job depends on build-freertos-target's new ELF artifact upload; runs the freertos compose pair via --exit-code-from. Branch protection list and summary quality monitor updated. - Scenarios that don't pass on FreeRTOS today (hardcoded TEST_* hostname/PROCID/timestamp; no meta/origin/timeQuality SD wired; scenarios using cmdline args) tagged @freertoswip; the bdd-freertos CI command filters --tags='not @freertoswip and @udp'. Linux filter unchanged. Single passing scenario today is header_fields::App name matches the example program. - The cpputest-freertos-cross image bump (Python + behave) is prepared in CppUTestFreertosDocker but not yet pushed; the behave-freertos compose service inline-installs Python+behave until the image SHA advances. DEVLOG entry calls out the follow-up bump PR. Local verification: - behave-linux: 21 features / 46 scenarios pass, 0 failed. - behave-freertos: 1 feature / 1 scenario pass, 0 failed, 45 @freertoswip skipped. Closes #304.
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (13)
📝 WalkthroughWalkthroughThis PR integrates FreeRTOS-on-QEMU BDD testing into the existing syslog-ng oracle framework. Per-target Docker Compose service pairs (syslog-ng + behave) are introduced with shared network namespaces; a target driver abstraction handles QEMU-based or native process spawning; environment.py selects targets via BDD_TARGET; and scenarios are marked with ChangesFreeRTOS-on-QEMU BDD Harness
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
☀️ Quality Summary 🚦 build-linux-gcc: 100% successful (✔️ 1105 passed, 🙈 3 skipped) Created by Quality Monitor v1.14.0 (#f3859fd). More details are shown in the GitHub Checks Result. |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (6)
Bdd/features/steps/target_driver.py (2)
108-111: 💤 Low value
process.wait(timeout=timeout)on non-FreeRTOS path can raiseTimeoutExpired.If the example does not honor
quit(e.g. wedged service thread),waitraisessubprocess.TimeoutExpiredandstop_example_processleaves the process alive. The caller'sfinallyblock in_run_with_prompt_protocoldoes kill it, so it's not a leak — but consider catchingTimeoutExpired, sendingprocess.kill(), and re-raising / surfacing as anAssertionErrorso the failure mode is unambiguous in test reports rather than appearing as a generic timeout from a helper.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Bdd/features/steps/target_driver.py` around lines 108 - 111, The stop_example_process helper currently calls process.wait(timeout=timeout) which can raise subprocess.TimeoutExpired and leave the process alive; update stop_example_process to catch subprocess.TimeoutExpired, call process.kill() (and optionally process.wait() without timeout to reap), then raise an AssertionError (or re-raise a clearer test failure) with a message including the timeout and that the process ignored the "quit" request so callers of _run_with_prompt_protocol see a clear test failure instead of a generic timeout; reference the stop_example_process function and ensure the caller path in _run_with_prompt_protocol still handles/propagates the AssertionError as intended.
88-106: 💤 Low valueDocstring mentions a "short grace period" but the FreeRTOS branch kills immediately.
The docstring claims FreeRTOS is killed "after a short grace period," but in the code path,
process.stdin.write("quit\n")+flush()is followed immediately byprocess.kill()with no sleep or wait. Since the BDD scenario has already verified oracle reception, this is functionally fine, but the"quit\n"write is essentially best-effort and the comment is misleading. Either drop thequitwrite (it's redundant with the immediate kill) or add a brief settle (e.g.time.sleep(0.1)) so the docstring matches reality and a graceful UART task teardown has at least a chance to run before the kill.Proposed minor wording fix
if target == "freertos": - try: - process.stdin.write("quit\n") - process.stdin.flush() - except (BrokenPipeError, OSError): - pass + # The BDD scenario has already verified the oracle received the + # frame; QEMU's exit code carries no useful signal, so just kill. process.kill() process.wait(timeout=timeout) return None🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Bdd/features/steps/target_driver.py` around lines 88 - 106, The docstring for stop_example_process says FreeRTOS is killed "after a short grace period" but the freertos branch writes "quit\n" then immediately calls process.kill(); either remove the redundant process.stdin.write/flush of "quit\n" or insert a short sleep (e.g., time.sleep(0.1)) between the write/flush and process.kill() so the implementation matches the docstring; update imports if you add time.sleep and keep the behavior (process.kill() and process.wait(timeout=timeout)) unchanged..devcontainer/docker-compose.yml (1)
121-148: 💤 Low value
syslog-ng-freertosexposes no host ports — confirm oracle traffic is observable for devs.Unlike
syslog-ng-linux, this service deliberately omitsports:, which is correct becausefreertos-targetreaches it vianetwork_mode: service:syslog-ng-freertoson the shared loopback. Just flagging that, as a side effect, developers cannot directly send to or observe this oracle from the host (e.g. withnc localhost 5514); they mustdocker compose exec syslog-ng-freertos .... Worth a one-line note indocs/containers.mdorBdd/README.mdif not already covered.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.devcontainer/docker-compose.yml around lines 121 - 148, Add a one-line note to the project docs (e.g., docs/containers.md or Bdd/README.md) clarifying that the syslog-ng-freertos service (service name: syslog-ng-freertos) intentionally exposes no host ports because freertos-target reaches it via network_mode: service:syslog-ng-freertos on the shared loopback, and instruct developers how to observe/send traffic from the host (e.g., use docker compose exec syslog-ng-freertos ... rather than nc localhost:5514).ci/docker-compose.bdd.yml (3)
22-25: ⚖️ Poor tradeoffSame
syslog-ngalias on the default network — confirm CI never starts both pairs together.Both services attach to
defaultwith aliassyslog-ng. CI is currently safe because each job runsdocker compose up --exit-code-from behave-<target>which only pulls in that target's pair viadepends_on. If a future job ever runs both pairs in the same compose project (e.g. a combined matrix run), thesyslog-ngDNS lookup from any service on the default network will resolve non-deterministically.Two robust options if/when the matrix grows:
- Drop the shared
syslog-ngalias and have each consumer reach its oracle by service name (syslog-ng-linux/syslog-ng-freertos), removing the need forhost="syslog-ng"defaults inwait_for_tcp_port_*.- Put each pair on its own bridge network so the alias is scoped per-pair.
Same concern raised on
.devcontainer/docker-compose.yml— fixing both consistently is preferable.Also applies to: 73-76
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ci/docker-compose.bdd.yml` around lines 22 - 25, The shared "syslog-ng" network alias on the default network causes non-deterministic DNS if both pairs ever run together; either remove the common alias and update any consumers (update wait_for_tcp_port_* defaults and calls) to target the explicit service names "syslog-ng-linux" and "syslog-ng-freertos", or create separate bridge networks per pair and scope the alias to each network so the alias remains unique per-pair; apply the same change consistently for both the compose definitions that contain the alias (and update any wait_for_tcp_port_* helper defaults/uses to reference the new service names when you remove the shared alias).
102-110: ⚡ Quick winAdd
set -e(orset -euo pipefail) so install failures surface clearly.The bash command runs
apt-get update,apt-get install,pip install, thenbehavewithoutset -e. If the apt or pip step fails (e.g. transient network issue), the script will still try to invokebehave, which will fail with "command not found" or import errors that obscure the real cause. Failing fast at the install step makes CI logs much easier to triage.Proposed fix
command: - | + set -euo pipefail # Temporary install — once the cpputest-freertos-cross image # gains python3-pip + behave (CppUTestFreertosDocker bump), drop # this line and the `apt-get install` block below. apt-get update >/dev/null && apt-get install -y --no-install-recommends python3-pip >/dev/null pip install --no-cache-dir --break-system-packages -r Bdd/requirements.txt behave --junit --junit-directory Bdd/junit --tags='not `@wip` and not `@freertoswip` and `@udp`' Bdd/features/🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ci/docker-compose.bdd.yml` around lines 102 - 110, The shell command in the service entrypoint/command (the bash -c block that runs apt-get, pip install and behave) should fail fast; prepend a strict shell option like "set -euo pipefail" (or at minimum "set -e") as the first statement in that bash -c multiline command so any apt-get or pip failure aborts immediately and surfaces the real error instead of continuing to run behave.
2-30: ⚡ Quick winDRY:
syslog-ng-linuxandsyslog-ng-freertosare nearly identical — consider a YAML anchor.The two oracle services share image, entrypoint, command body, network alias, and healthcheck. The only differences are the named volumes (
bdd-output-<target>,syslog-ng-ctl-<target>). A YAML anchor / merge-key on the common block would keep them in lockstep (e.g. when the bash command is updated for both pairs). Compose supports anchors viax-syslog-ng-base: &syslog-ng-baseand<<: *syslog-ng-base.This will pay off as more target pairs are added (the comment at line 47-52 hints this is the plan).
Proposed sketch (not exhaustive)
x-syslog-ng-base: &syslog-ng-base image: balabit/syslog-ng:latest entrypoint: ["bash", "-c"] command: - | syslog-ng -F & pid=$$! deadline=$$((SECONDS + 30)) while [ ! -S /var/lib/syslog-ng/syslog-ng.ctl ]; do kill -0 "$$pid" 2>/dev/null || { echo "syslog-ng exited unexpectedly"; exit 1; } [ "$$SECONDS" -ge "$$deadline" ] && { echo "Timed out waiting for syslog-ng control socket"; kill "$$pid" 2>/dev/null; exit 1; } sleep 0.1 done chmod 0777 /var/lib/syslog-ng/syslog-ng.ctl wait networks: default: aliases: - syslog-ng healthcheck: test: ["CMD-SHELL", "test -S /var/lib/syslog-ng/syslog-ng.ctl"] interval: 2s timeout: 5s retries: 10 services: syslog-ng-linux: <<: *syslog-ng-base volumes: - ../Bdd/syslog-ng/syslog-ng.conf:/etc/syslog-ng/syslog-ng.conf - ../Bdd/syslog-ng/tls:/etc/syslog-ng/tls:ro - bdd-output-linux:/var/log/syslog-ng - syslog-ng-ctl-linux:/var/lib/syslog-ng syslog-ng-freertos: <<: *syslog-ng-base volumes: - ../Bdd/syslog-ng/syslog-ng.conf:/etc/syslog-ng/syslog-ng.conf - ../Bdd/syslog-ng/tls:/etc/syslog-ng/tls:ro - bdd-output-freertos:/var/log/syslog-ng - syslog-ng-ctl-freertos:/var/lib/syslog-ngAlso applies to: 53-81
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ci/docker-compose.bdd.yml` around lines 2 - 30, The two services syslog-ng-linux and syslog-ng-freertos duplicate the same image, entrypoint, command block, networks and healthcheck; extract these common fields into a YAML anchor (e.g. x-syslog-ng-base: &syslog-ng-base) and merge into each service using <<: *syslog-ng-base, leaving only the differing volumes (bdd-output-<target> and syslog-ng-ctl-<target>) defined per service; ensure the long multiline command, network alias, and healthcheck (test: ["CMD-SHELL", "test -S /var/lib/syslog-ng/syslog-ng.ctl"]) are moved into the anchor so future edits only need to touch x-syslog-ng-base.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.devcontainer/docker-compose.yml:
- Around line 58-61: Two services share the same DNS alias `syslog-ng` causing
ambiguous resolution; fix by giving each oracle a unique alias (e.g.,
`syslog-ng-linux` and `syslog-ng-freertos`) in the docker-compose service
definitions (`syslog-ng-linux`, `syslog-ng-freertos`) or by creating per-pair
bridge networks so the `syslog-ng` alias is scoped, and update consumers to use
the new alias; also make `syslog_steps.py`'s default host (used by
wait_for_tcp_port_open()/wait_for_tcp_port_closed()) configurable from an
environment variable (e.g., SYSLOG_HOST with fallback to "syslog-ng") instead of
hardcoding "syslog-ng"; finally add the missing depends_on: - syslog-ng-linux to
the `clang` service to match `gcc`/`behave-linux`.
In `@Bdd/features/environment.py`:
- Around line 100-109: The code currently treats any non-"freertos" BDD_TARGET
as Linux and silently misroutes "windows" or typos; update the logic around
context.target, default_binary and context.example_binary to explicitly handle
"windows" (set a Windows-specific default_binary path) and validate
context.target against allowed values (e.g., "linux", "freertos", "windows"); if
an invalid value is provided, log an error or raise an exception and fall back
to a safe default (or abort) so mis-typed BDD_TARGET values are not silently
ignored.
In `@ci/docker-compose.bdd.yml`:
- Around line 83-110: The behave-freertos service currently runs an inline
apt-get/pip install in its command block even though the
cpputest-freertos-cross:sha-44efeae image already includes python3 and behave;
remove the temporary install lines and the related TODO comment and leave only
the behave invocation. Specifically, edit the behave-freertos service
(entrypoint/command) to delete the apt-get update && apt-get install -y ...
python3-pip >/dev/null and the pip install --no-cache-dir ... line plus the
surrounding comment about the temporary install, ensuring the final command
simply runs behave --junit --junit-directory Bdd/junit --tags='not `@wip` and not
`@freertoswip` and `@udp`' Bdd/features/ so no runtime network installs occur.
In `@DEVLOG.md`:
- Around line 63-74: Add a blank line immediately before the markdown table that
begins with "| Feature | Why |" and a blank line immediately after its closing
row so the table is separated from surrounding content; update DEVLOG.md by
inserting a single empty line above the table header and a single empty line
after the table's final line to satisfy markdownlint rule MD058.
In `@docs/containers.md`:
- Around line 20-33: Update the top markdown table and any mentions of service
names to match the new per-target compose layout: replace legacy generic service
names with the current target-specific names (e.g., use "behave-linux" and
"syslog-ng-linux" for Linux, and "freertos-target" / "syslog-ng-freertos" for
FreeRTOS) and ensure the explanatory text still references the dependent
services (the "gcc" service depending on "syslog-ng-linux", and
"freertos-target" depending on "syslog-ng-freertos" with network_mode:
service:syslog-ng-freertos and QEMU gateway 10.0.2.2). Keep the existing example
wiring references (Example/Common/Example*Config.c) consistent with those
updated service names.
---
Nitpick comments:
In @.devcontainer/docker-compose.yml:
- Around line 121-148: Add a one-line note to the project docs (e.g.,
docs/containers.md or Bdd/README.md) clarifying that the syslog-ng-freertos
service (service name: syslog-ng-freertos) intentionally exposes no host ports
because freertos-target reaches it via network_mode: service:syslog-ng-freertos
on the shared loopback, and instruct developers how to observe/send traffic from
the host (e.g., use docker compose exec syslog-ng-freertos ... rather than nc
localhost:5514).
In `@Bdd/features/steps/target_driver.py`:
- Around line 108-111: The stop_example_process helper currently calls
process.wait(timeout=timeout) which can raise subprocess.TimeoutExpired and
leave the process alive; update stop_example_process to catch
subprocess.TimeoutExpired, call process.kill() (and optionally process.wait()
without timeout to reap), then raise an AssertionError (or re-raise a clearer
test failure) with a message including the timeout and that the process ignored
the "quit" request so callers of _run_with_prompt_protocol see a clear test
failure instead of a generic timeout; reference the stop_example_process
function and ensure the caller path in _run_with_prompt_protocol still
handles/propagates the AssertionError as intended.
- Around line 88-106: The docstring for stop_example_process says FreeRTOS is
killed "after a short grace period" but the freertos branch writes "quit\n" then
immediately calls process.kill(); either remove the redundant
process.stdin.write/flush of "quit\n" or insert a short sleep (e.g.,
time.sleep(0.1)) between the write/flush and process.kill() so the
implementation matches the docstring; update imports if you add time.sleep and
keep the behavior (process.kill() and process.wait(timeout=timeout)) unchanged.
In `@ci/docker-compose.bdd.yml`:
- Around line 22-25: The shared "syslog-ng" network alias on the default network
causes non-deterministic DNS if both pairs ever run together; either remove the
common alias and update any consumers (update wait_for_tcp_port_* defaults and
calls) to target the explicit service names "syslog-ng-linux" and
"syslog-ng-freertos", or create separate bridge networks per pair and scope the
alias to each network so the alias remains unique per-pair; apply the same
change consistently for both the compose definitions that contain the alias (and
update any wait_for_tcp_port_* helper defaults/uses to reference the new service
names when you remove the shared alias).
- Around line 102-110: The shell command in the service entrypoint/command (the
bash -c block that runs apt-get, pip install and behave) should fail fast;
prepend a strict shell option like "set -euo pipefail" (or at minimum "set -e")
as the first statement in that bash -c multiline command so any apt-get or pip
failure aborts immediately and surfaces the real error instead of continuing to
run behave.
- Around line 2-30: The two services syslog-ng-linux and syslog-ng-freertos
duplicate the same image, entrypoint, command block, networks and healthcheck;
extract these common fields into a YAML anchor (e.g. x-syslog-ng-base:
&syslog-ng-base) and merge into each service using <<: *syslog-ng-base, leaving
only the differing volumes (bdd-output-<target> and syslog-ng-ctl-<target>)
defined per service; ensure the long multiline command, network alias, and
healthcheck (test: ["CMD-SHELL", "test -S /var/lib/syslog-ng/syslog-ng.ctl"])
are moved into the anchor so future edits only need to touch x-syslog-ng-base.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 5790e7bd-2b0b-4aa9-9ad3-e9ed43a93032
📒 Files selected for processing (20)
.devcontainer/docker-compose.yml.github/workflows/ci.ymlBdd/README.mdBdd/features/buffered.featureBdd/features/environment.pyBdd/features/header_fields.featureBdd/features/message_fields.featureBdd/features/origin.featureBdd/features/prival.featureBdd/features/steps/syslog_steps.pyBdd/features/steps/target_driver.pyBdd/features/structured_data.featureBdd/features/syslog.featureBdd/features/time_quality.featureBdd/features/timestamp.featureBdd/features/udp_mtu.featureCLAUDE.mdDEVLOG.mdci/docker-compose.bdd.ymldocs/containers.md
CodeRabbit flagged that both syslog-ng-linux and syslog-ng-freertos sharing the bare `syslog-ng` alias on the default network gives docker's embedded DNS multiple A records when both pairs run together — behave-linux's wait_for_tcp_port_open(host="syslog-ng") and the example wiring's hardcoded "syslog-ng" host could non-deterministically hit either oracle. CI is currently safe (each job scopes services to its own pair) but a developer running plain `docker compose up` from the host, or a future matrix run, would trigger the collision. Each pair now lives on its own bridge network (linux / freertos); the `syslog-ng` alias is scoped to that network so the same name resolves to the right oracle from inside each pair, and pairs running together cannot see each other's services. Local smoke confirms no regressions: behave-linux 46/46 pass, behave-freertos 1/1 pass (45 @freertoswip skipped).
Establishes the FreeRTOS doc baseline so a reader landing on README can navigate to either build, BDD, or example detail and find current information. Designed to be extended slice-by-slice as more FreeRTOS features land. - README.md: Status section names FreeRTOS Cortex-M3 (mps2-an385) as in-progress (E08 #268); examples list grows to four with the new Example/FreeRtos/SingleTask line; public-headers section lists the FreeRTOS adapter headers (SolidSyslogFreeRtosDatagram.h, SolidSyslogFreeRtosStaticResolver.h). - docs/bdd.md: Architecture section replaces the legacy two-service picture with a per-target table (Linux / FreeRTOS / Windows) and links to Bdd/README.md for the per-target compose details. Tag table gains @freertoswip with the rollout-marker explanation. Runner filter table gains the FreeRTOS row. Local-running commands renamed to behave-linux / syslog-ng-linux. - docs/ci.md: Job table picks up build-freertos-host-tdd, build-freertos-target, bdd-freertos-qemu, plus the pre-existing miss of integration-windows-openssl. Forward-looking sentence about ARM cross-compile / FreeRTOS QEMU oracle now matches reality. - docs/builds.md: New 'FreeRTOS cross — freertos-cross' section pointing at Example/FreeRtos/README.md and Bdd/README.md. BDD section renamed to behave-linux. - docs/containers.md: Top image table corrected to the per-target syslog-ng-linux / syslog-ng-freertos service names and the new behave-linux runner; cpputest-freertos-cross row already covered this PR's earlier doc edits. - Example/FreeRtos/README.md: Top-level table now distinguishes HelloWorld (minimal bring-up smoke for cross-compile / scheduler / UART / newlib regression detection) from SingleTask (canonical syslog example, BDD-driven). Notes that HelloWorld will be retired once SingleTask provides sufficient diagnostic confidence.
CodeRabbit flagged that the previous environment.py treated every non-freertos value as Linux, so a typo or BDD_TARGET=windows silently misrouted execution rather than failing loudly. Replace the implicit fallback with an explicit `linux | windows | freertos` dict, lowercase the input so case differences are tolerated, and raise ValueError on any other value with the allowed set in the message. Adds the Windows default binary path so windows is now a first-class entry. bdd-windows-otel CI job sets BDD_TARGET=windows explicitly so the new validation accepts it; previously it relied on the default-Linux fallback while overriding EXAMPLE_BINARY. Linux and FreeRTOS jobs are already explicit via the compose file's environment block.
…install CodeRabbit flagged the inline `apt-get install python3-pip; pip install` in the behave-freertos compose service as redundant — the image bump that adds python3 + behave to the cross image has now landed (CppUTestFreertosDocker `feat: add python3 + behave to cross image`, SHA 10a14ae, published to GHCR). Bump every reference and drop the inline install along with its `entrypoint: bash -c` wrapper, falling back to the simpler `command: behave ...` form mirroring behave-linux. Files updated: - .devcontainer/docker-compose.yml — freertos-host + freertos-target - .github/workflows/ci.yml — build-freertos-host-tdd + build-freertos-target - ci/docker-compose.bdd.yml — behave-freertos image + simplified command - docs/containers.md — the cpputest-freertos / cross image table rows Local smoke confirms behave-freertos runtime drops from ~45s (apt+pip install on every run) to ~2.4s; same 1 scenario passes, 45 @freertoswip skipped.
- Bdd/features/steps/target_driver.py — drop the redundant `quit\n` write in the FreeRTOS branch of stop_example_process. The docstring said "kills after a short grace period" but the code immediately followed `quit\n` with `process.kill()`, so the write was best-effort and misleading. The BDD scenario has already verified the oracle received the frame; just kill QEMU and move on. Docstring rewritten to match. - DEVLOG.md — blank lines added around the @freertoswip rationale table to satisfy markdownlint MD058. - Bdd/README.md — note added to the FreeRTOS fault-finding tips explaining that syslog-ng-freertos exposes no host ports (unlike syslog-ng-linux) and how to send a probe frame from inside the container.
|
@coderabbitai — thanks for the careful review. All five actionable comments addressed in five stacked commits (replied in-thread above). On the review-level nitpicks:
Local re-smoke across all 5 commits: |
|
Tip For best results, initiate chat on the files or code changes.
Happy to approve these changes. 🎉 [approve] ✏️ Learnings added
|
☀️ Quality Summary 🚦 build-linux-gcc: 100% successful (✔️ 1105 passed, 🙈 3 skipped) Created by Quality Monitor v1.14.0 (#f3859fd). More details are shown in the GitHub Checks Result. |
Purpose
Slice 5 of S08.03 (#268). Establishes the BDD harness that lets the same
Gherkin features run against the FreeRTOS-on-QEMU target alongside the
existing Linux + Windows runs. The slice-4 hand-rolled QEMU smoke (Python
listener + UART heredoc) is replaced by Behave + the existing syslog-ng
oracle, and a new
bdd-freertos-qemuCI job exercises it.Closes #304.
Change Description
target_driver.pyabstracts the example-spawn behind aBDD_TARGETenv var. FreeRTOS spawns
qemu-system-armwith the cross-built ELF;Linux/Windows keep the existing native subprocess flow. Same
SolidSyslog>prompt protocol over stdin/stdout (ExampleInteractiveprints it on every target) so
wait_for_prompt/send_commandareunchanged.
extra_argsraiseNotImplementedErroron FreeRTOS — theexample has no getopt port; cmdline-flag →
set NAME VALUEtranslationis a follow-up.
ci/docker-compose.bdd.ymland.devcontainer/docker-compose.ymlrename the existing services tosyslog-ng-linux/behave-linuxand addsyslog-ng-freertos+behave-freertos. The freertos pair shares a netns(
network_mode: service:syslog-ng-freertos) so QEMU's slirp gateway10.0.2.2NATs to the pair's loopback wheresyslog-ng-freertoslistens on
0.0.0.0:5514. Pairs never run together (CI scopes servicesper job; devcontainer's
depends_ononly starts the active pair). Bothoracles alias as the bare hostname
syslog-ngso existing examplewiring and step helpers keep resolving without per-target overrides.
build-freertos-targetbuilds and uploadsSolidSyslogFreeRtosSingleTask.elfas an artifact; newbdd-freertos-qemujob downloads it and runs the freertos composepair via
--exit-code-from behave-freertos. Branch protection list inCLAUDE.md and
summaryjob's quality monitor pattern list updated.today are tagged
@freertoswip; the FreeRTOS BDD command filters--tags='not @freertoswip and @udp'. Linux filter unchanged. Taggedfor clear reasons documented in the DEVLOG entry — most are because
the FreeRTOS SingleTask example has hardcoded
TEST_*values(hostname, PROCID, timestamp), no
meta/origin/timeQualitySD wiring, or because the scenarios use cmdline args. Removing each
tag is a follow-up slice.
dockerfile.crossinCppUTestFreertosDocker (separate repo) gets
python3 + python3-pip + behave==1.3.3. Until pushed and the new SHA propagates, thebehave-freertoscompose command does an inlineapt-get install python3-pip; pip install; that goes away in a follow-upchore: bump container imagePR.Test Evidence
Local docker-compose runs against both pairs:
docker compose -f ci/docker-compose.bdd.yml up --exit-code-from behave-linux behave-linux syslog-ng-linux):21 features / 46 scenarios pass, 0 failed, 0 skipped — pre-rename
behaviour fully preserved.
docker compose -f ci/docker-compose.bdd.yml up --exit-code-from behave-freertos behave-freertos syslog-ng-freertos):1 feature / 1 scenario pass (
header_fields.feature::App name matches the example program), 0 failed, 45@freertoswipskipped.CI run on this PR exercises the new
bdd-freertos-qemujob end-to-end.Areas Affected
Bdd/features/— environment.py + new target_driver.py + steprefactor in syslog_steps.py + tag annotations across the @udp
feature files.
ci/docker-compose.bdd.ymland.devcontainer/docker-compose.yml— per-target oracle pairs, network_mode, DNS aliases.
.github/workflows/ci.yml— ELF artifact upload frombuild-freertos-target, new bdd-freertos-qemu job, summary needs
list, quality monitor pattern.
CLAUDE.mdbranch-protection list +docs/containers.mdimagetable + new
Bdd/README.mddocumenting the BDD_TARGET contractand FreeRTOS local fault-finding tips.
Out of solid-syslog: prepared but not pushed —
CppUTestFreertosDocker/dockerfile.cross(Python + Behave). Follow-upPR pushes it and bumps the SHA refs in this repo.
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Infrastructure
Documentation