Files
enginex-ascend-910-vllm/docs/source/developer_guide/contribution/nightly_ci_test.md

318 lines
12 KiB
Markdown
Raw Normal View History

# Nightly CI Test
This document explains how to trigger nightly hardware CI tests against your own PR code
on Ascend NPU hardware (A2/A3), without waiting for the scheduled nightly run.
## Background
By default, nightly CI tests run on a fixed schedule using pre-built nightly images.
Contributors can self-service trigger these tests directly against their PR changes
by combining a GitHub label with a comment command.
## How to Trigger
### 1. Post a comment
Post one of the following comments in the PR to specify which tests to run.
The comment itself triggers the workflow — no label is required.
| Comment | Effect |
|---------|--------|
| `/nightly` | Run **all** nightly tests |
| `/nightly all` | Run **all** nightly tests (same as above) |
| `/nightly test1 test2 ...` | Run only the **named** tests |
:::{note}
Only repository **Contributors** (Triage role) and **Maintainers** (Write role) can
trigger the `/nightly` command. If you do not have this permission, ask a maintainer
to post the comment for you. You can find the list of maintainers and contributors in
the project's [Governance](../../community/governance.md) page or by checking the
[CODEOWNERS](https://github.com/vllm-project/vllm-ascend/blob/main/.github/CODEOWNERS)
file.
:::
### 2. Wait for results
GitHub Actions will trigger the `Nightly-A2` or `Nightly-A3` workflow. Only tests
matching the filter will be dispatched, which saves hardware resources.
## Differences Between PR and Scheduled Runs
| | Scheduled / Manual Dispatch | PR-triggered |
|---|----------------------------|---|
| Trigger | Cron (daily) or `workflow_dispatch` | `/nightly` comment |
| Code tested | Pre-built nightly image | Your PR's HEAD commit (source installed fresh) |
| Test scope | All tests | Configurable via `/nightly <names>` |
| vLLM + vllm-ascend | From image | Checked out and installed from source |
| Test matrix | From main branch's matrix YAML | From PR branch's matrix YAML |
When a PR run is detected (`is_pr_test: true`), the workflow additionally:
1. Uninstalls any existing vllm packages in the container.
2. Checks out the specific vllm version and your PR's vllm-ascend commit from source.
3. Installs all dependencies from source.
4. Installs the `aisbench` benchmark suite.
## Test Matrix Data Source
The set of nightly test cases (their names, runners, test paths, model configs) is
declared in a single data file:
```text
.github/workflows/configs/nightly_config.yaml
```
The file is organized as `a2:` and `a3:` top-level keys (one per SoC). Under each
SoC, tests are grouped by execution shape (single-node, multi-node, double-node,
multi-card, accuracy) and each group holds a `test_config` (or `nightly` / `pr_only`
for accuracy) list whose entries carry a `name` plus the fields consumed by the
downstream reusable workflows (`os`, `tests`, `config_file_path`, `size`, etc.).
Both the `Nightly-A2` and `Nightly-A3` workflows dynamically read this file at run
time — there is no hardcoded test matrix in the workflow YAMLs. The
`/nightly <name>` slash command resolves names by walking the same file from the
PR branch, so newly added entries can be exercised on a PR before they land on
main.
## Adding a New Nightly Test Case
To add a new test case (no need to touch the workflow YAMLs):
1. Append an entry under the appropriate section in
`.github/workflows/configs/nightly_config.yaml`. Each entry needs at least:
- `name`: unique identifier used in `/nightly <name>` filters
- `os` (for single-node / multi-card pytest+yaml tests) or `runner` is inferred
- one of `tests:` (pytest directory) or `config_file_path:` (YAML-driven model config)
- `size` (multi-node / double-node only)
2. Add the actual test files (pytest modules under `tests/e2e/nightly/...` or
YAML model configs in `tests/e2e/nightly/.../configs/`).
3. Open a PR. Once CI is green, you can validate the new entry against real NPU
hardware **without** merging the PR — see *Examples* below.
## Available Test Names
The test names you can pass to `/nightly` correspond to the `name` fields under
the matching section in `.github/workflows/configs/nightly_config.yaml`. The
tables below mirror the current contents of that file.
### A2 workflow (`.github/workflows/schedule_nightly_test_a2.yaml`)
**Single-node tests** (`a2.single_node.test_config`):
| Test name | Description |
|-----------|-------------|
| `test_custom_op_multi_card` | Custom operator tests (multi card) |
| `qwen3-vl-32b-instruct-w8a8` | Qwen3-VL-32B-Instruct W8A8 |
| `qwen3-32b-int8` | Qwen3-32B INT8 quantization |
| `Qwen3.5-27B-w8a8-A2` | Qwen3.5-27B W8A8 |
| `Qwen3.5-397B-A17B-w4a8-mtp` | Qwen3.5-397B-A17B W4A8 + MTP |
**Multi-node tests** (`a2.multi_node.test_config`):
| Test name | Description |
|-----------|-------------|
| `multi-node-qwen3-235b-dp` | Qwen3-235B-A22B, 2-node DP |
| `multi-node-GLM-5.1-w8a8-A2` | GLM-5.1 W8A8, 2 nodes |
| `multi-node-Kimi-K2.5-W4A8-A2` | Kimi-K2.5 W4A8, 2 nodes |
**Accuracy tests** (`a2.accuracy.nightly` and `a2.accuracy.pr_only`):
| Test name | Description | Scope |
|-----------|-------------|-------|
| `accuracy-group-1` | Qwen3-VL-8B, Qwen3-8B, Qwen2-Audio-7B, etc. | nightly |
| `accuracy-group-2` | ERNIE-4.5, Molmo-7B, Llama-3.2-3B, etc. | nightly |
| `accuracy-group-3` | Qwen3-30B-A3B, Qwen3-VL-30B-A3B, etc. | nightly |
| `accuracy-group-4` | Qwen3-Next-80B-A3B, Qwen3-Omni-30B-A3B, etc. | nightly |
| `pr-accuracy-group-1` | gemma-3-4b-it, internlm3-8b-instruct, etc. | pr_only |
| `pr-accuracy-group-2` | Qwen2.5-Math-RM-72B, Hunyuan-A13B-Instruct | pr_only |
The `pr-accuracy-group-*` entries only run on `/nightly` (PR-triggered) runs;
`/nightly all` on the schedule skips them.
### A3 workflow (`.github/workflows/schedule_nightly_test_a3.yaml`)
**Multi-node tests** (`a3.multi_node.test_config`, 4-node):
| Test name | Description |
|-----------|-------------|
| `multi-node-deepseek-v3.2-W8A8-EP` | DeepSeek-V3.2-W8A8 with EP, 4-node |
**Double-node tests** (`a3.double_node.test_config`, 2-node, run after multi-node):
| Test name | Description |
|-----------|-------------|
| `multi-node-deepseek-r1-w8a8-longseq` | DeepSeek-R1-W8A8 long sequence, 2-node |
| `multi-node-qwen3-dp` | Qwen3-235B-A22B, 2-node DP |
| `multi-node-qwenw8a8-2node-eplb` | Qwen3-235B-W8A8 with EPLB, 2-node |
| `multi-node-dpsk3.2-2node` | DeepSeek-V3.2-W8A8, 2-node |
| `multi-node-qwenw8a8-2node-longseq` | Qwen3-235B-W8A8 long sequence, 2-node |
| `multi-node-qwen-disagg-pd` | Qwen3-235B disaggregated PD, 2-node |
| `multi-node-qwen-vl-disagg-pd` | Qwen3-VL-235B disaggregated PD, 2-node |
| `multi-node-deepseek-v3.1` | DeepSeek-V3.1-BF16, 2-node |
| `multi-node-deepseek-v3.2-W8A8-EP` | DeepSeek-V3.2-W8A8 with EP, 4-node |
| `multi-node-glm-5.2` | GLM-5.1-W8A8, 2-node |
**Single-node tests** (`a3.single_node.test_config`):
| Test name | Description |
|-----------|-------------|
| `mtpx-deepseek-r1-0528-w8a8` | MTP-X + DeepSeek-R1-0528-W8A8 |
| `deepseek-r1-0528-w8a8` | DeepSeek-R1-0528-W8A8 |
| `kimi-k2-thinking` | Kimi-K2-Thinking |
| `qwen3-vl-235b-a22b-instruct-w8a8` | Qwen3-VL-235B-A22B-Instruct-W8A8 |
| `deepseek-r1-0528-w8a8-prefix-cache` | DeepSeek-R1-0528-W8A8 prefix cache |
| `deepseek-v3-2-w8a8` | DeepSeek-V3.2-W8A8 |
| `glm-4.7-w8a8` | GLM-4.7 W8A8 |
| `kimi-k2.5` | Kimi-K2.5 |
| `qwen3-235b-a22b-w8a8` | Qwen3-235B-A22B-W8A8 |
| `Qwen3.5-397B-A17B-w8a8-mtp` | Qwen3.5-397B-A17B W8A8 + MTP |
| `MiniMax-M2.5-w8a8-QuaRot-A3` | MiniMax-M2.5 W8A8 + QuaRot |
| `Qwen3.5-27B-w8a8-A3` | Qwen3.5-27B W8A8 |
| `Qwen3.5-122B-A10B-W8A8-A3` | Qwen3.5-122B-A10B W8A8 |
| `DeepSeek-V4-Flash-W8A8-A3` | DeepSeek-V4-Flash W8A8 |
**Multi-card tests** (`a3.multi_card.test_config`):
| Test name | Description |
|-----------|-------------|
| `qwen3-30b-acc` | Qwen3-30B accuracy test |
| `qwen3-30b-a3b-w8a8` | Qwen3-30B-A3B-W8A8 |
| `qwen3-32b-int8` | Qwen3-32B-Int8 |
| `qwen3-32b-int8-prefix-cache` | Qwen3-32B-Int8 prefix cache |
| `Qwen3-30B-A3B-W4A8-llm-compressor` | Qwen3-30B-A3B W4A8 via llm-compressor |
| `Qwen3-30B-QuaRot` | Qwen3-30B QuaRot + eagle3 |
| `Qwen3-32B-QuaRot` | Qwen3-32B QuaRot + eagle3 |
:::{warning}
The A3 resource pool has a maximum concurrency of **5×16 NPUs**. Multi-node tests
run with `max-parallel: 2` to avoid resource exhaustion. Running `/nightly all` on
A3 will queue a large number of jobs — prefer targeting specific test names when
possible.
:::
## Examples
Run all available nightly tests against your PR:
```text
/nightly
```
Run only the custom operator multi-card test:
```text
/nightly test_custom_op_multi_card
```
Run two specific tests at once (one per SoC):
```text
/nightly test_custom_op_multi_card mtpx-deepseek-r1-0528-w8a8
```
Run a single accuracy group (with all of its models):
```text
/nightly accuracy-group-1
```
Run a single accuracy model (only that model from a group):
```text
/nightly accuracy-group-1/Qwen3-8B
```
Re-trigger after fixing an issue: just push a new commit. The `synchronize` event
re-runs the workflow and picks up the existing `/nightly` comment automatically — no
need to post a new comment.
## Adding a New Test Case — Worked Example
To add `my-new-test` to the A2 single-node section:
1. Edit `.github/workflows/configs/nightly_config.yaml`, append under
`a2.single_node.test_config`:
```yaml
- name: my-new-test
os: linux-aarch64-a2b3-4
tests: tests/e2e/nightly/single_node/ops/multicard_ops_a2/test_my_new.py
```
2. Commit the new pytest file (`test_my_new.py`) in the same PR.
3. Trigger from the PR:
```text
/nightly my-new-test
```
The workflow will:
- `pr_nightly_command.yml` reads your PR's `nightly_config.yaml` and resolves
`my-new-test` → dispatch A2 only.
- `Nightly-A2` is dispatched at `main`, but `generate-a2-matrix` checks out your
PR commit and reads the new entry from the matrix.
- `single-node-tests` runs one matrix job for `my-new-test`, with
`should_run=true`. The reusable workflow checks out your PR code (via
`vllm_ascend_ref`) and runs your pytest.
## Troubleshooting
**The workflow didn't start after I posted the comment.**
- Check that the comment starts exactly with `/nightly` with no leading spaces or
extra characters before the slash.
- Confirm you have at least Triage permission on the repository; unauthorized
users' comments are ignored.
- To re-trigger after fixing an issue, simply push a new commit — the workflow will
reuse the existing `/nightly` comment automatically.
**Only some tests ran, not the ones I expected.**
- Test names are case-sensitive and must match the `name` field in
`.github/workflows/configs/nightly_config.yaml` exactly (see the tables above).
- For a PR-triggered run, the matrix is loaded from your PR's
`nightly_config.yaml`, not main. If a name isn't in your PR's file, it won't
be recognized and the dispatch will be skipped.
- Check the `parse-trigger` job output in GitHub Actions for the resolved
`test_filter` value.
**The workflow ran with the scheduled image, not my PR code.**
- Confirm the workflow was triggered by `repository_dispatch` (slash command),
not bare `workflow_dispatch`. The `pr_nightly_command.yml` workflow is what
actually dispatches `schedule_nightly_test_a2.yaml` / `_a3.yaml` with
`vllm_ascend_ref` pointing at your PR SHA.
**A new test I added isn't being recognized.**
- Confirm the entry is well-formed YAML under
`.github/workflows/configs/nightly_config.yaml`. The `name` field is required
and must be unique within the SoC's section.
- The matrix is loaded from your PR branch, so make sure the file is committed
to the same branch the `/nightly` comment was posted on.
**How to obtain more detailed logs to pinpoint problems for multi-node tests**
- For most issues, the stdout pop-up logs from GitHub actions are sufficient (this log always represents the logs from the first node).
- If the logs from a first node are no longer sufficient to provide effective logging information, see the summary of your jobs to download log archive for the corresponding test, which includes the framework-side logs and plog information for each node, structured as follows:
```shell
.
├── node0
│ ├── root
│ │ └── ascend
│ │ └── log
│ └── var
│ └── log
│ └── vllm-deepseek-v3-0f233d-0_logs.txt
└── node1
├── root
│ └── ascend
│ └── log
└── var
└── log
└── vllm-deepseek-v3-0f233d-0-1_logs.txt
```