Skip to content

CI: Collect L4 Pod Tests through pytest - #1758

Merged
ChaoWao merged 3 commits into
hw-native-sys:mainfrom
ccyywwen:ci-l4pod-refactor
Aug 10, 2026
Merged

CI: Collect L4 Pod Tests through pytest#1758
ChaoWao merged 3 commits into
hw-native-sys:mainfrom
ccyywwen:ci-l4pod-refactor

Conversation

@ccyywwen

Copy link
Copy Markdown
Contributor

Summary

  • Collect pod CI tests through pytest with -m pod instead of hand-enumerating L4 examples in _st-pod.yml
  • Add pod markers/fixtures and pytest wrappers for the L4 mixed local/remote examples
  • Add a thin tests/st pod wrapper to prove pod tests under tests/st are collected by the pod lane
  • Replace pod-run-example with pod-run-pytest and keep run_parent.sh as a manual entry point
  • Exclude pod tests from ordinary onboard ST lanes while leaving sim lanes unfiltered

Fixes #1740

- Add pod pytest markers, fixtures, and L4 wrappers so pod CI can collect examples and tests/st with one marker expression
- Replace the hand-enumerated pod example action with a pytest action while keeping manual run_parent.sh entry points
- Exclude pod tests from ordinary ST lanes and update docs to match the new CI shape
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d97c23a8-ac92-455e-bb00-55c8fd970826

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The pod CI path now uses one pytest action for marked L4 tests. It adds peer and remote-device fixtures, refactors examples for direct invocation, updates test selection, and replaces per-example workflow execution and documentation.

Changes

Pod pytest execution

Layer / File(s) Summary
Shared daemon lifecycle and pytest sweep
.github/actions/pod-run-pytest/action.yml, .github/actions/pod-teardown/action.yml, .github/workflows/_st-pod.yml
The new action starts and monitors the peer daemon, runs pytest, stops the daemon, and collects logs. The pod workflow uses one serialized pytest sweep.
Pod fixtures and resource allocation
conftest.py
Pytest now provides pod markers, peer configuration, remote-device allocation, and per-test process-log directories.
L4 execution wrappers and tests
examples/workers/l4/*/main.py, examples/workers/l4/*/test_*.py, tests/st/a2a3/.../test_global_tload_mixed_l3_pod.py
L4 examples expose parameterized run() functions. New tests invoke them with local and remote pod settings.
Marker selection and documentation
.github/workflows/_st-npu-a2a3.yml, .github/workflows/_st-npu-a5.yml, docs/*, examples/*
Onboard commands exclude pod tests. CI and example documentation describe pytest-based pod execution.
Removed legacy action
.github/actions/pod-run-example/action.yml
The former example-specific composite action was removed.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Poem

A rabbit hops through pytest’s queue,
With peer logs gathered fresh and new.
Three examples join the run,
Shared daemon work is neatly done.
Pod markers guide each test anew.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.17% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the primary change: collecting L4 pod tests through pytest in CI.
Description check ✅ Passed The description accurately summarizes pytest collection, pod fixtures, wrappers, workflow changes, and lane filtering.
Linked Issues check ✅ Passed The changes address issue #1740 by adding pod fixtures and wrappers, replacing manual enumeration, and excluding pod tests from ordinary onboard lanes.
Out of Scope Changes check ✅ Passed The workflow, fixture, test, action, and documentation changes support the stated pod pytest integration objectives without unrelated code changes.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
examples/workers/README.md (2)

63-72: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

The "What a new L4 example needs" checklist omits the test_*.py wrapper.

Lines 152-155 now state that each L4 example ships a test_*.py wrapper and that CI uses it. The file tree at lines 66-72 still lists only main.py and run_parent.sh. A contributor who copies that tree produces an example the pod job never collects.

📝 Proposed fix
 l4/<your_example>/
   README.md
   kernels/aiv/*.cpp
   kernels/orchestration/*.cpp
   main.py                   # entry point: argparse + main() delegating to run()
+  test_<your_example>.py    # `@pytest.mark.pod` wrapper; this is what the pod job collects
   run_parent.sh             # maps environment variables onto main.py's flags
🤖 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 `@examples/workers/README.md` around lines 63 - 72, Update the “What a new L4
example needs” file tree to include the required test_*.py wrapper alongside
main.py and run_parent.sh, matching the requirement documented later in the
README.

105-112: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

The "Running it in CI" section still tells contributors to edit the pod workflow.

The text says adding an example to st-pod-onboard-a2a3 is "one block plus one line". This PR removes that path. The updated docs/ci.md states that adding an L4 pod example means adding a test_*.py wrapper with @pytest.mark.pod, not editing _st-pod.yml. The warning about "why a step that reports green there may still have failed" also no longer applies, because the per-example continue-on-error steps are gone.

Rewrite this section to describe the marker-based path.

📝 Proposed rewrite
 ### Running it in CI

 The `st-pod-onboard-a2a3` job runs L4 examples across a pair of a2a3 machines.
-Adding yours to it is one block plus one line, and the wiring, the log
-artifact, and the failure semantics are described in
-[`docs/ci.md`](../../docs/ci.md#multi-machine-pod-jobs). Read that before adding the
-block — in particular why a step that reports green there may still have
-failed.
+The job runs one `pytest examples tests/st -m pod` sweep, so adding yours means
+adding a `test_*.py` wrapper carrying `@pytest.mark.pod`. Do not edit
+`_st-pod.yml`. The wiring and the log artifact are described in
+[`docs/ci.md`](../../docs/ci.md#multi-machine-pod-jobs).
🤖 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 `@examples/workers/README.md` around lines 105 - 112, Rewrite the “Running it
in CI” section in examples/workers/README.md to describe adding a test_*.py
wrapper decorated with `@pytest.mark.pod`, referring contributors to the updated
multi-machine pod-job guidance in docs/ci.md. Remove the obsolete instructions
about editing st-pod-onboard-a2a3, adding a workflow block and line, and the
warning about green steps masking failures.
🧹 Nitpick comments (2)
conftest.py (1)

1281-1290: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Remote device allocation always returns the same prefix, so it depends on --max-parallel 1.

st_pod_remote_device_ids returns remote_device_ids[:n] for every test. Local ids come from the framework allocator, but remote ids do not. _st-pod.yml passes --max-parallel 1, so no two pod tests run at once today and no collision occurs. If that value is ever raised, two concurrent pod tests claim the same peer device.

Record the dependency in the fixture docstring, or derive the slice from the allocated local worker index.

♻️ Proposed docstring change
 def st_pod_remote_device_ids(request, st_pod_peer):
-    """Allocate remote device IDs from the pod peer's default device pool."""
+    """Allocate remote device IDs from the pod peer's default device pool.
+
+    Every test receives the same leading slice, so this is only collision-free
+    while the pod job serializes with ``--max-parallel 1``. Raising that value
+    requires deriving the slice from the allocated local worker index.
+    """
🤖 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 `@conftest.py` around lines 1281 - 1290, Update the st_pod_remote_device_ids
fixture docstring to explicitly document that it always allocates the prefix of
the peer’s remote_device_ids and therefore requires --max-parallel 1 to avoid
concurrent test collisions. Do not change allocation behavior unless
implementing it via the existing local worker index.
.github/actions/pod-run-pytest/action.yml (1)

97-110: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

One POD_SMOKE_TIMEOUT_S now covers the whole sweep instead of one example.

Before this change the same budget applied per pod example. Now it bounds the full -m pod collection, which currently holds four tests plus per-test kernel compilation. With the default of 1800 s the last test can be killed by timeout even when every test is healthy.

Consider scaling the value in _st-pod.yml, or replacing the outer timeout with the existing --pto-session-timeout budget so the failure names the test that hung.

🤖 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 @.github/actions/pod-run-pytest/action.yml around lines 97 - 110, The Run pod
pytest step currently applies POD_SMOKE_TIMEOUT_S to the entire pytest sweep;
update the timeout handling around “Run pod pytest” to preserve a per-test
budget or use the existing --pto-session-timeout mechanism, and adjust the
_st-pod.yml configuration if scaling the shared value is the chosen approach.
Ensure healthy multi-test pod runs are not terminated solely because the
aggregate duration exceeds the single-test budget, while hung tests still report
which test timed out.
🤖 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 `@examples/README.md`:
- Line 20: Update the trailing comments for the hardware pytest commands in
examples/README.md lines 20-20 and docs/user/reference/cli.md lines 9-9 to name
both SDMA and pod as quarantined markers and state that pod runs in the
two-machine pod job; keep the command text and comments identical at both sites.

In `@examples/workers/l4/compute_then_tload_mixed_l3/main.py`:
- Around line 248-258: Suppress Ruff S104 for the intentional 0.0.0.0 defaults
and document the peer-callback rationale at both affected sites: update the
session_listen_host parameter in
examples/workers/l4/compute_then_tload_mixed_l3/main.py (lines 248-258) and the
os.environ.get default in conftest.py (lines 1276-1278) with the same noqa
annotation and one-line explanation; both sites require direct changes.
- Around line 267-284: Widen the try/finally cleanup in the run flow to include
local_l3 creation, registration, Worker construction, and add_worker. Ensure the
finally block closes local_l3 when it was created but never successfully
attached to worker, while preserving existing cleanup for attached workers.

In `@examples/workers/l4/compute_then_tload_mixed_l3/README.md`:
- Around line 86-88: Update the CI/manual-entry documentation in
examples/workers/l4/compute_then_tload_mixed_l3/README.md:86-88 and
examples/workers/l4/global_tload_mixed_l3/README.md:84-85 so it no longer claims
pytest uses the same variables as run_parent.sh; name each respective test
wrapper, state that CI supplies POD_REMOTE_ENDPOINT, POD_REMOTE_DEVICES,
POD_L3_SESSION_TIMEOUT_S, POD_L3_SESSION_LISTEN_HOST, and the
--platform/--device options instead of the corresponding SIMPLER_* variables,
and retain run_parent.sh with the existing table as the manual entry point.

In `@examples/workers/l4/global_tload_mixed_l3/main.py`:
- Line 163: Resolve Ruff S104 for session_listen_host in
examples/workers/l4/global_tload_mixed_l3/main.py:163-163 and
examples/workers/l4/vector_add_mixed_l3/main.py:254-254 by using a configured
peer-reachable interface, or, if wildcard binding is required for pod peer
sessions, add a scoped # noqa: S104 with a brief reason at both sites.

---

Outside diff comments:
In `@examples/workers/README.md`:
- Around line 63-72: Update the “What a new L4 example needs” file tree to
include the required test_*.py wrapper alongside main.py and run_parent.sh,
matching the requirement documented later in the README.
- Around line 105-112: Rewrite the “Running it in CI” section in
examples/workers/README.md to describe adding a test_*.py wrapper decorated with
`@pytest.mark.pod`, referring contributors to the updated multi-machine pod-job
guidance in docs/ci.md. Remove the obsolete instructions about editing
st-pod-onboard-a2a3, adding a workflow block and line, and the warning about
green steps masking failures.

---

Nitpick comments:
In @.github/actions/pod-run-pytest/action.yml:
- Around line 97-110: The Run pod pytest step currently applies
POD_SMOKE_TIMEOUT_S to the entire pytest sweep; update the timeout handling
around “Run pod pytest” to preserve a per-test budget or use the existing
--pto-session-timeout mechanism, and adjust the _st-pod.yml configuration if
scaling the shared value is the chosen approach. Ensure healthy multi-test pod
runs are not terminated solely because the aggregate duration exceeds the
single-test budget, while hung tests still report which test timed out.

In `@conftest.py`:
- Around line 1281-1290: Update the st_pod_remote_device_ids fixture docstring
to explicitly document that it always allocates the prefix of the peer’s
remote_device_ids and therefore requires --max-parallel 1 to avoid concurrent
test collisions. Do not change allocation behavior unless implementing it via
the existing local worker index.
🪄 Autofix

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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f5488a2b-01b7-457e-ad76-48c8050b3b40

📥 Commits

Reviewing files that changed from the base of the PR and between 69a73e9 and d030f8d.

📒 Files selected for processing (23)
  • .github/actions/pod-run-example/action.yml
  • .github/actions/pod-run-pytest/action.yml
  • .github/actions/pod-teardown/action.yml
  • .github/workflows/_st-npu-a2a3.yml
  • .github/workflows/_st-npu-a5.yml
  • .github/workflows/_st-pod.yml
  • conftest.py
  • docs/ci.md
  • docs/comm-domain.md
  • docs/testing.md
  • docs/troubleshooting/a2a3-507899-aicpu-shared-so-fault.md
  • docs/user/reference/cli.md
  • examples/README.md
  • examples/workers/README.md
  • examples/workers/l4/compute_then_tload_mixed_l3/README.md
  • examples/workers/l4/compute_then_tload_mixed_l3/main.py
  • examples/workers/l4/compute_then_tload_mixed_l3/test_compute_then_tload_mixed_l3.py
  • examples/workers/l4/global_tload_mixed_l3/README.md
  • examples/workers/l4/global_tload_mixed_l3/main.py
  • examples/workers/l4/global_tload_mixed_l3/test_global_tload_mixed_l3.py
  • examples/workers/l4/vector_add_mixed_l3/main.py
  • examples/workers/l4/vector_add_mixed_l3/test_vector_add_mixed_l3.py
  • tests/st/a2a3/tensormap_and_ringbuffer/l4_pod/test_global_tload_mixed_l3_pod.py
💤 Files with no reviewable changes (1)
  • .github/actions/pod-run-example/action.yml

Comment thread examples/README.md Outdated
Comment thread examples/workers/l4/compute_then_tload_mixed_l3/main.py
Comment thread examples/workers/l4/compute_then_tload_mixed_l3/main.py Outdated
Comment thread examples/workers/l4/compute_then_tload_mixed_l3/README.md Outdated
Comment thread examples/workers/l4/global_tload_mixed_l3/main.py Outdated
- Skip pod tests when the pod runner environment is absent

- Document serialized remote-device allocation and marker-based L4 CI

- Close partially-created L4 local workers on setup failures

- Increase the pod pytest sweep timeout budget
@ChaoWao
ChaoWao merged commit 92eebce into hw-native-sys:main Aug 10, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Code Health] Pod L4 examples are enumerated by hand instead of collected by the ST framework

2 participants