From 5b927b7ceb92d9b1998e22d50cdc4ee400db08d0 Mon Sep 17 00:00:00 2001 From: wangyu <53896905+yenuo26@users.noreply.github.com> Date: Thu, 10 Sep 2026 16:40:01 +0800 Subject: [PATCH] [CI/Build] Diff-aware source_file_dependencies for CUDA/NPU pipelines (#6597) Signed-off-by: wangyu <410167048@qq.com> Co-authored-by: Cursor --- .../common/ci_source_file_dependencies.yml | 438 ++++++++++++++++++ .buildkite/common/scripts/upload_pipeline.py | 263 +++++++++-- .buildkite/cuda/bootstrap-upload-steps.yml | 28 +- .buildkite/cuda/test-merge.yml | 129 +----- .buildkite/cuda/test-nightly.yml | 104 +++-- .buildkite/cuda/test-ready.yml | 146 +----- .buildkite/cuda/test-weekly.yml | 288 +++++++++++- .buildkite/npu/bootstrap-upload-steps.yml | 9 +- .buildkite/npu/pipeline-npu-a3.yml | 8 +- .buildkite/npu/test-npu-nightly.yml | 42 +- .claude/skills/vllm-omni-test/SKILL.md | 8 +- .../vllm-omni-test/references/test-routing.md | 4 +- docs/contributing/ci/ci_settings.md | 54 ++- tests/buildkite/test_upload_pipeline.py | 334 ++++++++++++- tests/e2e/accuracy/test_hidream_o1_image.py | 4 +- .../test_lingbot_world_v2.py | 4 +- .../test_minimax_h3_dlo_dp2_fl2va.py | 2 +- .../test_minimax_h3_dlo_dp2_ref2va.py | 2 +- .../minimax_h3/test_minimax_h3_fasth3_lora.py | 2 +- .../minimax_h3/test_minimax_h3_turbo_lora.py | 2 +- .../e2e/online_serving/test_lingbot_video.py | 6 +- .../online_serving/test_lingbot_video_moe.py | 6 +- tests/e2e/online_serving/test_magi2.py | 5 +- .../test_minimax_h3_dlo_dp2_t2va.py | 1 - tools/pre_commit/check_buildkite.py | 1 + 25 files changed, 1479 insertions(+), 411 deletions(-) create mode 100644 .buildkite/common/ci_source_file_dependencies.yml diff --git a/.buildkite/common/ci_source_file_dependencies.yml b/.buildkite/common/ci_source_file_dependencies.yml new file mode 100644 index 000000000..0455922c8 --- /dev/null +++ b/.buildkite/common/ci_source_file_dependencies.yml @@ -0,0 +1,438 @@ +# Uploader-only path-prefix presets for CUDA L2–L5 and NPU L4 test YAML. +# Referenced as ``source_file_dependencies: omni_qwen3_omni_function`` (or a list of +# keys) on a step; ``upload_pipeline.py`` expands the key(s) only. +# +# YAML anchors above the registry hold model business-code paths. Job keys +# ({model}_function / _perf / _accuracy / _reliability / _doc / _cov) alias +# those anchors and add the scripts the job actually runs. Feature keys below +# are unchanged. ``source_filter_fallback`` is not a job key: when no job-key +# prefix matches, a matching diff keeps every job for that upload. +# +# YAML anchors are nested lists; the loader flattens them. + +x-qwen3-tts: &qwen3_tts + - vllm_omni/worker/gpu_model_runner.py + - vllm_omni/model_executor/models/qwen3_tts/ + - vllm_omni/model_executor/models/common/qwen3_code_predictor.py + - vllm_omni/model_executor/models/common/snake_activation.py + - vllm_omni/model_executor/models/common/alias_free_activation.py + - vllm_omni/model_executor/stage_input_processors/qwen3_tts.py + - vllm_omni/deploy/qwen3_tts.yaml + - vllm_omni/entrypoints/openai/serving_speech.py + - vllm_omni/entrypoints/openai/tts_adapters/ + - vllm_omni/engine/stage_pool.py + +x-minicpmo-4-5: &minicpmo_4_5 + - vllm_omni/model_executor/models/minicpmo_4_5/ + - vllm_omni/model_executor/models/step_audio2/ + - vllm_omni/model_executor/models/cosyvoice3/code2wav_core/ + - vllm_omni/model_executor/models/cosyvoice3/utils.py + - vllm_omni/model_executor/stage_input_processors/minicpmo_4_5_omni.py + - vllm_omni/deploy/minicpmo_4_5.yaml + - vllm_omni/transformers_utils/chat_templates/minicpmo45_native.jinja + +x-minicpmo-4-5-duplex: &minicpmo_4_5_duplex + - vllm_omni/deploy/minicpmo_4_5_duplex.yaml + - vllm_omni/engine/duplex/ + - vllm_omni/entrypoints/duplex/ + - vllm_omni/clients/ + - vllm_omni/entrypoints/duplex_request_client.py + - vllm_omni/outputs/duplex.py + - vllm_omni/model_executor/duplex_sampling.py + - vllm_omni/experimental/fullduplex/ + - vllm_omni/core/sched/ + - vllm_omni/outputs/multimodal_accumulation.py + - vllm_omni/engine/stage_init_utils.py + - vllm_omni/engine/async_omni_engine.py + - vllm_omni/engine/orchestrator.py + - vllm_omni/entrypoints/cli/serve.py + - vllm_omni/entrypoints/openai/api_server.py + - vllm_omni/entrypoints/openai/duplex_capability.py + - vllm_omni/config/stage_config.py + +x-qwen2-5-omni: &qwen2_5_omni + - vllm_omni/model_executor/models/qwen2_5_omni/ + - vllm_omni/model_executor/stage_input_processors/qwen2_5_omni.py + - vllm_omni/deploy/qwen2_5_omni.yaml + +x-qwen3-omni: &qwen3_omni + - vllm_omni/entrypoints/openai/serving_chat.py + - vllm_omni/model_executor/models/qwen3_omni/ + - vllm_omni/model_executor/models/common/qwen3_code_predictor.py + - vllm_omni/model_executor/models/common/snake_activation.py + - vllm_omni/model_executor/models/qwen2_5_omni/qwen2_5_omni_thinker.py + - vllm_omni/model_executor/models/qwen3_tts/cuda_graph_decoder_wrapper.py + - vllm_omni/model_executor/stage_input_processors/qwen3_omni.py + - vllm_omni/deploy/qwen3_omni_moe.yaml + - vllm_omni/deploy/qwen3_omni_moe_thinking.yaml + +x-wan22: &wan22 + - vllm_omni/diffusion/models/wan2_2/ + - vllm_omni/diffusion/models/dmd2/ + +x-cosmos3: &cosmos3 + - vllm_omni/diffusion/models/cosmos3/ + - vllm_omni/diffusion/distributed/autoencoders/autoencoder_kl_wan.py + - vllm_omni/experimental/world_models/ + - vllm_omni/model_extras/cosmos3.py + +x-qwen-image: &qwen_image + - vllm_omni/diffusion/models/qwen_image/ + - vllm_omni/diffusion/models/dmd2/ + - vllm_omni/diffusion/distributed/autoencoders/autoencoder_kl_qwenimage.py + +x-hunyuan-image3: &hunyuan_image3 + - vllm_omni/diffusion/models/hunyuan_image3/ + - vllm_omni/model_executor/models/hunyuan_image3/ + - vllm_omni/deploy/hunyuan_image3_dit.yaml + +x-minimax-h3: &minimax_h3 + - vllm_omni/diffusion/models/minimax_h3/ + +x-hunyuan-video: &hunyuan_video + - vllm_omni/diffusion/models/hunyuan_video/ + - vllm_omni/model_executor/models/hunyuan_video/ + +x-ltx2: <x2 + - vllm_omni/diffusion/models/ltx2/ + - vllm_omni/model_extras/ltx2.py + +x-sana-video: &sana_video + - vllm_omni/diffusion/models/sana_video/ + - vllm_omni/model_extras/sana_video.py + +x-z-image: &z_image + - vllm_omni/diffusion/models/z_image/ + +x-stable-audio: &stable_audio + - vllm_omni/diffusion/models/stable_audio/ + +x-lingbot-video: &lingbot_video + - vllm_omni/diffusion/models/lingbot_video/ + - vllm_omni/model_extras/lingbot_video.py + +x-lingbot-world: &lingbot_world + - vllm_omni/diffusion/models/lingbot_world/ + + +source_file_dependencies: + # Shared uploader/registry paths. Not a job key — do not attach this to a step. + # Used only when no job-key prefix matches: then a hit keeps every job. + source_filter_fallback: + - .buildkite/common/scripts/upload_pipeline.py + - .buildkite/common/ci_source_file_dependencies.yml + - .buildkite/common/ci_mirror_hardwares.yml + - tests/helpers/ + + # --- features --- + diffusion_distributed_attention: + - tests/diffusion/distributed/ + - tests/diffusion/attention/test_attention_sp.py + - vllm_omni/diffusion/distributed/ + - vllm_omni/diffusion/attention/ + - vllm_omni/diffusion/data.py + - vllm_omni/diffusion/models/ + + custom_pipeline: + - tests/e2e/features/custom_pipeline/ + - tests/e2e/features/helpers/custom_pipeline.py + - vllm_omni/diffusion/ + - vllm_omni/engine/ + - vllm_omni/entrypoints/ + - vllm_omni/inputs/ + - vllm_omni/outputs/ + + rlhf_verl_omni: + - tests/e2e/features/rlhf_test/test_verl_omni_e2e.py + - tests/e2e/features/helpers/verl_omni_server.py + - tests/e2e/features/helpers/custom_pipeline.py + - vllm_omni/diffusion/ + - vllm_omni/engine/ + - vllm_omni/entrypoints/ + - vllm_omni/inputs/ + - vllm_omni/outputs/ + + # Tiny-model diffusion jobs (shared across many model trees under models/). + diffusion_tiny_model: + - tests/model_tests/diffusion/ + - vllm_omni/diffusion/models/ + + diffusion_offloader: + - tests/diffusion/offloader/ + - vllm_omni/diffusion/offloader/ + + diffusion_quantization: + - tests/diffusion/quantization/ + - vllm_omni/diffusion/quantization/ + + # --- models --- + # --- omni / tts jobs --- + omni_qwen3_omni_function: + - *qwen3_omni + - tests/e2e/offline_inference/test_qwen3_omni.py + - tests/e2e/offline_inference/test_qwen3_omni_colocate_async.py + - tests/e2e/offline_inference/test_qwen3_omni_autoround_w4a16_expansion.py + - tests/e2e/offline_inference/test_qwen3_omni_modelopt_nvfp4_w4a4.py + - tests/e2e/online_serving/test_qwen3_omni.py + - tests/e2e/online_serving/test_qwen3_omni_expansion.py + - tests/e2e/online_serving/test_qwen3_omni_multi_replicas.py + + omni_qwen3_omni_accuracy: + - *qwen3_omni + - tests/e2e/accuracy/qwen3_omni/ + + omni_qwen3_omni_perf: + - *qwen3_omni + - tests/dfx/perf/scripts/run_benchmark.py + - tests/dfx/perf/tests/test_qwen3_omni_vllm_text.json + - tests/dfx/perf/tests/test_qwen3_omni_async_chunk.json + - tests/dfx/perf/tests/test_qwen3_omni_no_async_chunk.json + - tests/dfx/perf/tests/test_qwen3_omni_multi_replicas.json + + omni_qwen3_omni_reliability: + - *qwen3_omni + - tests/dfx/reliability/test_reliability_qwen3_omni.py + + omni_qwen3_omni_doc: + - *qwen3_omni + - examples/online_serving/qwen3_omni/ + - examples/online_serving/openai_chat_completion_client_for_multimodal_generation.py + - tests/examples/online_serving/test_qwen3_omni.py + + omni_qwen2_5_omni_doc: + - *qwen2_5_omni + - examples/online_serving/qwen2_5_omni/ + - examples/online_serving/openai_chat_completion_client_for_multimodal_generation.py + - tests/examples/online_serving/test_qwen2_5_omni.py + + omni_minicpmo_4_5_function: + - *minicpmo_4_5 + - tests/e2e/offline_inference/test_minicpmo_4_5.py + - tests/e2e/online_serving/test_minicpmo_4_5.py + - tests/e2e/online_serving/test_minicpmo_4_5_expansion.py + + omni_minicpmo_4_5_accuracy: + - *minicpmo_4_5 + - tests/e2e/accuracy/minicpmo_4_5/ + + omni_minicpmo_4_5_perf: + - *minicpmo_4_5 + - tests/dfx/perf/scripts/run_benchmark.py + - tests/dfx/perf/tests/test_minicpmo_4_5_ready.json + - tests/dfx/perf/tests/test_minicpmo_4_5.json + + omni_minicpmo_4_5_doc: + - *minicpmo_4_5 + - examples/online_serving/minicpmo/realtime_web/ + - examples/online_serving/minicpmo/realtime_duplex_demo.py + - tests/examples/test_minicpmo_realtime_web_server.py + - tests/examples/test_minicpmo_realtime_web_static.py + - tests/examples/test_minicpmo_realtime_duplex_simple_demo.py + + omni_minicpmo_4_5_duplex_function: + - *minicpmo_4_5 + - *minicpmo_4_5_duplex + - tests/e2e/online_serving/test_minicpmo_4_5_duplex.py + - tests/e2e/online_serving/test_minicpmo_4_5_duplex_expansion.py + - tests/e2e/online_serving/test_duplex_client_live.py + - tests/e2e/online_serving/test_minicpmo_realtime_duplex_drivers.py + - tests/e2e/online_serving/helpers/minicpmo_realtime_duplex_scenarios.py + - tests/e2e/online_serving/run_minicpmo_realtime_duplex_multi_session.py + - tests/e2e/online_serving/run_minicpmo_realtime_duplex_server_vad.py + - tests/e2e/online_serving/run_minicpmo_realtime_duplex_soft_interrupt.py + - tests/e2e/online_serving/helpers/minicpmo_4_5_duplex.py + - tests/assets/minicpmo_4_5/ + - tests/clients/ + - tests/engine/duplex/ + - tests/entrypoints/duplex/ + - tests/model_executor/models/minicpmo_4_5/duplex/ + + omni_minicpmo_4_5_duplex_perf: + - *minicpmo_4_5 + - *minicpmo_4_5_duplex + - tests/dfx/perf/scripts/run_benchmark.py + - tests/dfx/perf/tests/test_minicpmo_4_5_duplex_seed_tts.json + + tts_qwen3_tts_function: + - *qwen3_tts + - tests/e2e/features/prefill_phase/ + - tests/e2e/offline_inference/test_qwen3_tts_base.py + - tests/e2e/offline_inference/test_qwen3_tts_customvoice.py + - tests/e2e/online_serving/test_qwen3_tts_base.py + - tests/e2e/online_serving/test_qwen3_tts_base_expansion.py + - tests/e2e/online_serving/test_qwen3_tts_customvoice.py + - tests/e2e/online_serving/test_qwen3_tts_customvoice_expansion.py + + tts_qwen3_tts_perf: + - *qwen3_tts + - tests/dfx/perf/scripts/run_benchmark.py + - tests/dfx/perf/tests/test_tts.json + + tts_qwen3_tts_cov: + - *qwen3_tts + - .buildkite/common/scripts/run_cov_split.sh + - pyproject.toml + - tests/e2e/offline_inference/test_qwen3_tts_base.py + - tests/e2e/online_serving/test_qwen3_tts_base.py + + # --- diffusion jobs --- + diffusion_wan22_function: + - *wan22 + - tests/e2e/offline_inference/test_wan22_t2v.py + - tests/e2e/offline_inference/test_wan22_autoround_w4a16_expansion.py + - tests/e2e/online_serving/test_wan22_t2v.py + - tests/e2e/online_serving/test_wan22_expansion.py + + diffusion_wan22_accuracy: + - *wan22 + - tests/e2e/accuracy/wan22_i2v/ + - tests/e2e/accuracy/test_diffusers_backend_similarity.py + + diffusion_wan22_perf: + - *wan22 + - tests/dfx/perf/scripts/run_diffusion_benchmark.py + - tests/dfx/perf/tests/test_wan22_i2v_vllm_omni.json + + diffusion_wan22_reliability: + - *wan22 + - tests/dfx/reliability/test_reliability_wan22.py + + diffusion_image_to_video_doc: + - *wan22 + - *hunyuan_video + - *ltx2 + - *sana_video + - *lingbot_video + - examples/offline_inference/image_to_video/ + - tests/examples/offline_inference/test_image_to_video.py + + diffusion_cosmos3_function: + - *cosmos3 + - tests/e2e/online_serving/test_cosmos3.py + + diffusion_cosmos3_accuracy: + - *cosmos3 + - tests/e2e/accuracy/test_cosmos3_similarity.py + + diffusion_cosmos3_perf: + - *cosmos3 + - tests/dfx/perf/scripts/run_diffusion_benchmark.py + - tests/dfx/perf/tests/test_cosmos3_vllm_omni.json + + diffusion_qwen_image_function: + - *qwen_image + - tests/e2e/online_serving/test_qwen_image.py + - tests/e2e/online_serving/test_qwen_image_expansion.py + + diffusion_qwen_image_accuracy: + - *qwen_image + - tests/e2e/accuracy/test_qwen_image.py + - tests/e2e/accuracy/test_diffusers_backend_similarity.py + + diffusion_qwen_image_perf: + - *qwen_image + - tests/dfx/perf/scripts/run_diffusion_benchmark.py + - tests/dfx/perf/tests/test_qwen_image_vllm_omni.json + + diffusion_text_to_image_doc: + - *qwen_image + - *z_image + - examples/offline_inference/text_to_image/ + - examples/online_serving/text_to_image/ + - tests/examples/offline_inference/test_text_to_image.py + - tests/examples/online_serving/test_text_to_image.py + - vllm_omni/diffusion/models/nextstep_1_1/ + - vllm_omni/diffusion/models/longcat_image/ + - vllm_omni/diffusion/models/ovis_image/ + - vllm_omni/diffusion/models/omnigen2/ + - vllm_omni/diffusion/models/sd3/ + - vllm_omni/diffusion/models/flux/ + - vllm_omni/diffusion/models/flux2/ + - vllm_omni/diffusion/models/flux2_klein/ + - vllm_omni/diffusion/models/hidream_image/ + - vllm_omni/diffusion/models/krea2/ + - vllm_omni/diffusion/models/lingbot_video/ + + diffusion_hunyuan_image3_function: + - *hunyuan_image3 + - tests/e2e/offline_inference/test_hunyuanimage3_i2t_expansion.py + + diffusion_hunyuan_image3_accuracy: + - *hunyuan_image3 + - tests/e2e/accuracy/test_hunyuan_image3_pixel_accuracy.py + + diffusion_hunyuan_image3_perf: + - *hunyuan_image3 + - tests/dfx/perf/scripts/run_diffusion_benchmark.py + - tests/dfx/perf/tests/test_hunyuan_image_tp2_cfgp2.json + - tests/dfx/perf/tests/test_hunyuan_image_tp2_sp2.json + - tests/dfx/perf/tests/test_hunyuan_image_tp4.json + + diffusion_hunyuan_image3_reliability: + - *hunyuan_image3 + - tests/dfx/reliability/test_reliability_hunyuan_image.py + + diffusion_minimax_h3_function: + - *minimax_h3 + - tests/e2e/online_serving/test_minimax_h3_dlo_dp2_t2va.py + - tests/e2e/online_serving/minimax_h3/ + - tests/diffusion/models/minimax_h3/ + - vllm_omni/diffusion/lora/ + - vllm_omni/diffusion/offloader/ + - vllm_omni/diffusion/distributed/ + - vllm_omni/entrypoints/openai/ + + diffusion_minimax_h3_accuracy: + - *minimax_h3 + - tests/e2e/accuracy/minimax_h3/ + + diffusion_minimax_h3_perf: + - *minimax_h3 + - tests/dfx/perf/scripts/run_diffusion_benchmark.py + - tests/dfx/perf/tests/test_minimax_h3_vllm_omni.json + + diffusion_hunyuan_video_function: + - *hunyuan_video + - tests/e2e/online_serving/test_hunyuan_video_15_expansion.py + + diffusion_hunyuan_video_accuracy: + - *hunyuan_video + - tests/e2e/accuracy/hunyuanvideo15_t2v/ + - tests/e2e/accuracy/hunyuanvideo15_i2v/ + + diffusion_hunyuan_video_perf: + - *hunyuan_video + - tests/dfx/perf/scripts/run_diffusion_benchmark.py + - tests/dfx/perf/tests/test_hunyuanvideo15_t2v_vllm_omni.json + - tests/dfx/perf/tests/test_hunyuanvideo15_i2v_vllm_omni.json + + diffusion_z_image_function: + - *z_image + - tests/e2e/online_serving/test_z_image.py + - tests/e2e/online_serving/test_zimage_expansion.py + + diffusion_stable_audio_function: + - *stable_audio + - tests/e2e/offline_inference/test_stable_audio_expansion.py + - tests/e2e/online_serving/test_stable_audio_online_expansion.py + + diffusion_lingbot_function: + - *lingbot_video + - *lingbot_world + - tests/e2e/online_serving/test_lingbot_video.py + - tests/e2e/online_serving/test_lingbot_video_moe.py + - tests/e2e/offline_inference/test_lingbot_world_v2.py + + + # Invalid-param jobs: model business code only, plus the reliability scripts. + reliability_invalid_param_h100: + - *qwen3_omni + - *minicpmo_4_5 + - *qwen_image + - *wan22 + - tests/dfx/reliability/invalid_param_test/ + + reliability_invalid_param_l4: + - *qwen3_tts + - *stable_audio + - tests/dfx/reliability/invalid_param_test/ diff --git a/.buildkite/common/scripts/upload_pipeline.py b/.buildkite/common/scripts/upload_pipeline.py index 749f35f5a..c8587d8c3 100644 --- a/.buildkite/common/scripts/upload_pipeline.py +++ b/.buildkite/common/scripts/upload_pipeline.py @@ -10,8 +10,15 @@ Bootstrap mode (``bootstrap-upload-steps.yml``): - Detect docs-only, pytest skip-mark-only, or combined skip-ci from git diff. - When only CI level YAML changes, enable **L2/L3** upload steps for affected levels only. -Test pipeline mode (e.g. test-merge.yml): - - Drop steps whose ``source_file_dependencies`` do not match changed files. +Test pipeline mode (e.g. test-merge.yml, test-nightly.yml, test-weekly.yml): + - Drop steps whose ``source_file_dependencies`` do not match changed files + (string/list keys from ci_source_file_dependencies.yml, or inline path + prefixes). Filtering applies on **PR label** uploads only; ``main`` + env + schedule (NIGHTLY/WEEKLY/merge push) keeps every job and still strips the field. + If no job-key prefix matches, a change to the pipeline YAML being uploaded + or to a path under the ``source_filter_fallback`` registry key keeps every + job so command, env, and hardware edits can be validated before merge. + When any job-key prefix already matches, normal filtering wins. - Expand uploader-only ``mirror_hardwares`` into ``agents`` (+ optional ``image`` for NPU) + ``plugins`` (see ci_mirror_hardwares.yml). - Omit ``mirror_hardwares`` to compose ``{chip}_{n}`` from pytest ``-m`` SKU @@ -87,6 +94,10 @@ BOOTSTRAP_UPLOAD_IF_KEYS = { } E2E_GROUP_MARKER = "E2E Test" CI_MIRROR_HARDWARES_PATH = ROOT / ".buildkite/common/ci_mirror_hardwares.yml" +CI_SOURCE_FILE_DEPENDENCIES_PATH = ROOT / ".buildkite/common/ci_source_file_dependencies.yml" +# Registry key whose prefixes bypass source filtering. Paths live in +# ci_source_file_dependencies.yml; do not attach this key to a job. +SOURCE_FILTER_FALLBACK_KEY = "source_filter_fallback" CUDA_HF_TOKEN_ENV = "VLLM_CI_HF_TOKEN" CUDA_HF_TOKEN_EXPORT = f'if [ -n "$${{{CUDA_HF_TOKEN_ENV}:-}}" ]; then export HF_TOKEN="$${{{CUDA_HF_TOKEN_ENV}}}"; fi' @@ -95,14 +106,7 @@ CUDA_HF_TOKEN_EXPORT = f'if [ -n "$${{{CUDA_HF_TOKEN_ENV}:-}}" ]; then export HF # ``*_UPLOAD_IF``: full gate for uploading that child pipeline. NIGHTLY_MAIN_IF = 'build.branch == "main" && build.env("NIGHTLY") == "1"' NIGHTLY_LABEL_IF = ( - f"({NIGHTLY_MAIN_IF}) || " - '(build.branch != "main" && (' - 'build.pull_request.labels includes "nightly-test" || ' - 'build.pull_request.labels includes "omni-test" || ' - 'build.pull_request.labels includes "tts-test" || ' - 'build.pull_request.labels includes "diffusion-x2iat-test" || ' - 'build.pull_request.labels includes "diffusion-x2v-test"' - "))" + f'({NIGHTLY_MAIN_IF}) || (build.branch != "main" && build.pull_request.labels includes "nightly-test")' ) WEEKLY_E2E_IF = 'build.branch == "main" && build.env("WEEKLY") == "1"' WEEKLY_MAIN_IF = 'build.branch == "main" && (build.env("WEEKLY") == "1" || build.env("NON_CRITICAL") == "1")' @@ -248,7 +252,7 @@ def _render_bootstrap_pipeline( return yaml.safe_dump(doc, sort_keys=False) -# --- Test pipeline (test-ready.yml, test-merge.yml) --- +# --- Test pipeline (test-ready.yml, test-merge.yml, test-nightly.yml) --- @lru_cache(maxsize=1) @@ -264,6 +268,117 @@ def _load_mirror_hardwares() -> dict[str, dict[str, Any]]: return presets +@lru_cache(maxsize=1) +def _load_source_file_dependencies() -> dict[str, list[str]]: + def flatten(value: Any, *, key: str) -> list[str]: + """Flatten YAML-anchor nested lists into a de-duplicated prefix list.""" + if isinstance(value, str): + if not value.strip(): + raise ValueError(f"empty path in source_file_dependencies[{key!r}]") + return [value] + if isinstance(value, list): + flattened: list[str] = [] + seen: set[str] = set() + for item in value: + for path in flatten(item, key=key): + if path not in seen: + seen.add(path) + flattened.append(path) + return flattened + raise ValueError( + f"source_file_dependencies[{key!r}] must be a list of path prefixes, got {type(value).__name__}", + ) + + if not CI_SOURCE_FILE_DEPENDENCIES_PATH.is_file(): + raise FileNotFoundError( + f"missing CI source_file_dependencies registry: {CI_SOURCE_FILE_DEPENDENCIES_PATH}", + ) + doc = yaml.safe_load(CI_SOURCE_FILE_DEPENDENCIES_PATH.read_text(encoding="utf-8")) + if not isinstance(doc, dict): + raise ValueError(f"invalid CI source_file_dependencies registry: {CI_SOURCE_FILE_DEPENDENCIES_PATH}") + presets = doc.get("source_file_dependencies") + if not isinstance(presets, dict): + raise ValueError(f"source_file_dependencies must be a mapping in {CI_SOURCE_FILE_DEPENDENCIES_PATH}") + loaded: dict[str, list[str]] = {} + for key, value in presets.items(): + if not isinstance(key, str) or not key.strip(): + raise ValueError( + f"source_file_dependencies keys must be non-empty strings in {CI_SOURCE_FILE_DEPENDENCIES_PATH}", + ) + loaded[key] = flatten(value, key=key) + return loaded + + +_REGISTRY_KEY_RE = re.compile(r"^[a-z][a-z0-9_]*$") + + +def _parse_command_text(step: dict[str, Any]) -> str: + """Parse step ``commands`` / ``command`` into a single string.""" + raw = step.get("commands", step.get("command")) + if raw is None: + return "" + if isinstance(raw, str): + return raw + if isinstance(raw, list): + return "\n".join(str(item) for item in raw if item is not None) + return str(raw) + + +def _resolve_source_file_dependencies(step: dict[str, Any]) -> list[str] | None: + """Expand a registry key (or list of keys / inline path prefixes).""" + deps = step.get("source_file_dependencies") + if deps is None: + return None + + def dedupe(*groups: list[str]) -> list[str]: + merged: list[str] = [] + seen: set[str] = set() + for group in groups: + for path in group: + if path not in seen: + seen.add(path) + merged.append(path) + return merged + + def lookup(key: str) -> list[str]: + if key == SOURCE_FILTER_FALLBACK_KEY: + raise ValueError( + f"source_file_dependencies {key!r} bypasses filtering and cannot be attached to a step " + f"({_get_step_label(step)!r})", + ) + registry = _load_source_file_dependencies() + paths = registry.get(key) + if paths is None: + known = ", ".join(sorted(registry)) + raise ValueError( + f"unknown source_file_dependencies {key!r} in step {_get_step_label(step)!r}; known: {known}", + ) + return list(paths) + + prefixes: list[str] + if isinstance(deps, str): + prefixes = lookup(deps) if _REGISTRY_KEY_RE.fullmatch(deps) else [deps] + elif isinstance(deps, list): + if not all(isinstance(item, str) for item in deps): + raise ValueError( + f"source_file_dependencies must be a string key or list of strings in step {_get_step_label(step)!r}", + ) + keyish = [bool(_REGISTRY_KEY_RE.fullmatch(item)) for item in deps] + if deps and all(keyish): + prefixes = dedupe(*(lookup(key) for key in deps)) + elif any(keyish): + raise ValueError( + f"source_file_dependencies in step {_get_step_label(step)!r} mixes registry keys and path prefixes", + ) + else: + prefixes = list(deps) + else: + raise ValueError( + f"source_file_dependencies must be a string key or list in step {_get_step_label(step)!r}", + ) + return prefixes + + @lru_cache(maxsize=1) def _cuda_mirror_chips() -> tuple[str, ...]: """Lowercase CUDA SKUs that have at least one ``{chip}_{n}`` preset. @@ -278,7 +393,7 @@ def _cuda_mirror_chips() -> tuple[str, ...]: return tuple(sorted(chips, key=lambda chip: (-len(chip), chip))) -def _read_cards_marks(expr: str) -> tuple[set[int], bool]: +def _parse_cards_marks(expr: str) -> tuple[set[int], bool]: """Parse registered ``cards_n`` / ``not cards_n`` from a pytest ``-m`` expr. Returns positive card counts and whether any ``not cards_*`` is present. @@ -295,8 +410,8 @@ def _read_cards_marks(expr: str) -> tuple[set[int], bool]: return positives, has_not_cards -def _read_hardware_marks(expr: str) -> set[str]: - """Return lowercase positive CUDA SKUs that have a mirror preset. +def _parse_hardware_marks(expr: str) -> set[str]: + """Parse lowercase positive CUDA SKUs that have a mirror preset. ``not H100`` is ignored. SKUs with no ``{chip}_*`` preset (e.g. H200) are dropped. """ @@ -338,36 +453,22 @@ def _get_mirror_hw_selector() -> str: return selector -def _read_pytest_marks(commands: Any) -> tuple[set[str], int | Literal["max"] | None]: - """Read pytest ``-m`` from step commands: CUDA SKU chips and cards count. +def _parse_pytest_marks(step: dict[str, Any]) -> tuple[set[str], int | Literal["max"] | None]: + """Parse pytest ``-m`` from step commands: CUDA SKU chips and cards count. *chips* are lowercase SKUs from positive markers (``not H100`` is ignored). *cards* is the max positive ``cards_n``, ``"max"`` when only ``not cards_*`` is present, or ``None``. """ - chunks: list[str] = [] - - def _collect(value: Any) -> None: - if value is None: - return - if isinstance(value, str): - chunks.append(value) - elif isinstance(value, list): - for part in value: - _collect(part) - else: - chunks.append(str(value)) - - _collect(commands) - text = "\n".join(chunks) + text = _parse_command_text(step) chips: set[str] = set() positives: set[int] = set() has_not_cards = False for match in _PYTEST_MARKER_ARG.finditer(text): expr = match.group(1) or match.group(2) or match.group(3) or "" - chips |= _read_hardware_marks(expr) - card_counts, not_cards = _read_cards_marks(expr) + chips |= _parse_hardware_marks(expr) + card_counts, not_cards = _parse_cards_marks(expr) positives.update(card_counts) has_not_cards = has_not_cards or not_cards @@ -484,7 +585,7 @@ def _expand_mirror_hardwares(step: dict[str, Any]) -> dict[str, Any] | None: if "mirror_hardwares" not in step: if has_pool: return step - chips, cards = _read_pytest_marks(step.get("commands")) + chips, cards = _parse_pytest_marks(step) if not chips and cards is None: return step preset_name = _compose_mirror_hardware_name(chips, cards, step_label=step_label) @@ -552,11 +653,7 @@ def _process_test_steps( processed.append(step) continue - deps = step.get("source_file_dependencies") - if deps is not None and not isinstance(deps, list): - raise ValueError( - f"source_file_dependencies must be a list in step {_get_step_label(step)!r}", - ) + deps = _resolve_source_file_dependencies(step) if changed_files is not None and deps is not None and not _match_source_file(changed_files, deps): _log(f"skip {_get_step_label(step)!r} (no changes under {deps})") continue @@ -595,10 +692,25 @@ def _select_e2e_group_steps(steps: list[Any]) -> list[Any]: return selected +def _any_source_dependency_match(steps: list[Any], changed_files: list[str]) -> bool: + """True when any step with ``source_file_dependencies`` matches *changed_files*.""" + for step in steps: + if not isinstance(step, dict): + continue + deps = _resolve_source_file_dependencies(step) + if deps is not None and _match_source_file(changed_files, deps): + return True + nested = step.get("steps") + if isinstance(nested, list) and _any_source_dependency_match(nested, changed_files): + return True + return False + + def _render_test_pipeline( doc: dict[str, Any], changed_files: list[str] | None, *, + pipeline_path: Path | None = None, e2e_only: bool = False, ) -> dict[str, Any]: """Filter steps by PR diff and strip uploader-only ``source_file_dependencies`` metadata.""" @@ -611,6 +723,13 @@ def _render_test_pipeline( return doc if e2e_only: steps = _select_e2e_group_steps(steps) + # Bypass is a fallback: only when no job-key prefix matched. + if changed_files is not None and pipeline_path is not None: + if not _any_source_dependency_match(steps, changed_files): + bypass = _source_filter_fallback_reason(changed_files, pipeline_path) + if bypass is not None: + _log(f"keep all jobs (no source_file_dependencies match; bypassed by {bypass})") + changed_files = None steps = _process_test_steps(steps, changed_files) return {**doc, "steps": steps} @@ -618,6 +737,63 @@ def _render_test_pipeline( # --- Entry (read file → bootstrap or test render → YAML string) --- +def _repo_relative_posix(path: Path) -> str: + resolved = path.resolve() + try: + return resolved.relative_to(ROOT).as_posix() + except ValueError: + return path.as_posix().replace("\\", "/") + + +def _source_filter_fallback_prefixes() -> list[str]: + """Shared uploader/registry prefixes from ``source_filter_fallback``. Not a job key.""" + registry = _load_source_file_dependencies() + prefixes = registry.get(SOURCE_FILTER_FALLBACK_KEY) + if not prefixes: + raise ValueError( + f"source_file_dependencies[{SOURCE_FILTER_FALLBACK_KEY!r}] must list shared uploader paths " + f"in {CI_SOURCE_FILE_DEPENDENCIES_PATH}", + ) + return prefixes + + +def _source_filter_fallback_reason(changed_files: list[str] | None, pipeline_path: Path) -> str | None: + """Return the changed path that should disable source filtering, if any.""" + if not changed_files: + return None + changed = set(changed_files) + pipeline_rel = _repo_relative_posix(pipeline_path) + if pipeline_rel in changed: + return pipeline_rel + prefixes = _source_filter_fallback_prefixes() + for path in changed_files: + if _match_source_file([path], prefixes): + return path + return None + + +def _changed_files_for_source_filter( + ctx, + *, + force_all: bool, + e2e_only: bool, +) -> list[str] | None: + """Return the diff to filter against, or None to keep every step. + + ``source_file_dependencies`` is label-only: scheduled ``main`` uploads + (NIGHTLY/WEEKLY/post-merge) run the full pipeline. ``--all`` / ``--e2e`` + also disable filtering. Pipeline YAML / ``source_filter_fallback`` matches + are applied later in ``_render_test_pipeline`` only when no job-key prefix + already matched. + """ + if force_all or e2e_only: + return None + if os.environ.get("BUILDKITE_BRANCH", "") == "main": + _log("main branch: keep all jobs (source_file_dependencies is label-only)") + return None + return ctx.changed_files + + def _render_pipeline( path: Path, *, @@ -635,13 +811,18 @@ def _render_pipeline( text = path.read_text(encoding="utf-8") ctx = resolve_ci_context_from_git() - changed_files = None if force_all or e2e_only else ctx.changed_files + changed_files = _changed_files_for_source_filter(ctx, force_all=force_all, e2e_only=e2e_only) doc = yaml.safe_load(text) if not isinstance(doc, dict): raise ValueError(f"invalid pipeline YAML: {path}") - doc = _render_test_pipeline(doc, changed_files, e2e_only=e2e_only) + doc = _render_test_pipeline( + doc, + changed_files, + pipeline_path=path, + e2e_only=e2e_only, + ) return yaml.safe_dump(doc, sort_keys=False) diff --git a/.buildkite/cuda/bootstrap-upload-steps.yml b/.buildkite/cuda/bootstrap-upload-steps.yml index ab4254feb..502a506e6 100644 --- a/.buildkite/cuda/bootstrap-upload-steps.yml +++ b/.buildkite/cuda/bootstrap-upload-steps.yml @@ -22,34 +22,48 @@ steps: agents: queue: "cpu_queue_premerge" - # L3 Test — PR merge-test label (diff-aware) or main+WEEKLY=1 (--e2e, full E2E group) + # L3 Test — PR merge-test label (diff-aware) or main (full pipeline / WEEKLY --e2e) - label: "Upload Merge Pipeline" depends_on: image-build key: upload-merge-pipeline commands: - | EXTRA="" - if [ "${WEEKLY:-}" = "1" ] && [ "${BUILDKITE_BRANCH}" = "main" ]; then - EXTRA="--e2e" + if [ "${BUILDKITE_BRANCH}" = "main" ]; then + if [ "${WEEKLY:-}" = "1" ]; then + EXTRA="--e2e" + else + EXTRA="--all" + fi fi python3 .buildkite/common/scripts/upload_pipeline.py --upload $$EXTRA .buildkite/cuda/test-merge.yml agents: queue: "cpu_queue_premerge" - # L4 Test — main+NIGHTLY=1 (scheduled), or PR with specific label (e.g. add label then Rebuild) + # L4 Test — main+NIGHTLY=1 (full pipeline), or PR nightly-test label (diff-aware) - label: "Upload Nightly Pipeline" depends_on: image-build key: upload-nightly-pipeline commands: - - python3 .buildkite/common/scripts/upload_pipeline.py --upload .buildkite/cuda/test-nightly.yml + - | + EXTRA="" + if [ "${NIGHTLY:-}" = "1" ] && [ "${BUILDKITE_BRANCH}" = "main" ]; then + EXTRA="--all" + fi + python3 .buildkite/common/scripts/upload_pipeline.py --upload $$EXTRA .buildkite/cuda/test-nightly.yml agents: queue: "cpu_queue_premerge" - # L5 Test — main+WEEKLY=1 / NON_CRITICAL=1 (scheduled), or PR with weekly-test label + # L5 Test — main+WEEKLY=1 / NON_CRITICAL=1 (full pipeline), or PR weekly-test label (diff-aware) - label: "Upload Weekly Pipeline" depends_on: image-build key: upload-weekly-pipeline commands: - - python3 .buildkite/common/scripts/upload_pipeline.py --upload .buildkite/cuda/test-weekly.yml + - | + EXTRA="" + if [ "${BUILDKITE_BRANCH}" = "main" ]; then + EXTRA="--all" + fi + python3 .buildkite/common/scripts/upload_pipeline.py --upload $$EXTRA .buildkite/cuda/test-weekly.yml agents: queue: "cpu_queue_premerge" diff --git a/.buildkite/cuda/test-merge.yml b/.buildkite/cuda/test-merge.yml index 5aa49ea6c..1a458bccf 100644 --- a/.buildkite/cuda/test-merge.yml +++ b/.buildkite/cuda/test-merge.yml @@ -78,21 +78,7 @@ steps: depends_on: upload-merge-pipeline steps: - label: "TTS · Qwen3-TTS CustomVoice Test" - source_file_dependencies: - - tests/e2e/features/prefill_phase/ - - vllm_omni/worker/gpu_model_runner.py - - tests/helpers/media.py - - tests/e2e/online_serving/test_qwen3_tts_customvoice.py - - tests/e2e/offline_inference/test_qwen3_tts_customvoice.py - - vllm_omni/model_executor/models/qwen3_tts/ - - vllm_omni/model_executor/models/common/qwen3_code_predictor.py - - vllm_omni/model_executor/models/common/snake_activation.py - - vllm_omni/model_executor/models/common/alias_free_activation.py - - vllm_omni/model_executor/stage_input_processors/qwen3_tts.py - - vllm_omni/deploy/qwen3_tts.yaml - - vllm_omni/entrypoints/openai/serving_speech.py - - vllm_omni/entrypoints/openai/tts_adapters/ - - vllm_omni/engine/stage_pool.py + source_file_dependencies: tts_qwen3_tts_function commands: - | timeout 40m bash -c " @@ -103,21 +89,7 @@ steps: mirror_hardwares: l4_1 - label: "TTS · Qwen3-TTS Base Test" - source_file_dependencies: - - tests/helpers/media.py - - tests/e2e/online_serving/test_qwen3_tts_base.py - - tests/e2e/offline_inference/test_qwen3_tts_base.py - - vllm_omni/model_executor/models/qwen3_tts/ - - vllm_omni/model_executor/models/common/qwen3_code_predictor.py - - vllm_omni/model_executor/models/common/snake_activation.py - - vllm_omni/model_executor/models/common/alias_free_activation.py - - vllm_omni/model_executor/stage_input_processors/qwen3_tts.py - - vllm_omni/deploy/qwen3_tts.yaml - - vllm_omni/entrypoints/openai/serving_speech.py - - vllm_omni/entrypoints/openai/tts_adapters/ - - vllm_omni/engine/stage_pool.py - - .buildkite/common/scripts/run_cov_split.sh - - pyproject.toml + source_file_dependencies: tts_qwen3_tts_cov # 40 -> 60: the coverage split runs the model twice. timeout_in_minutes: 60 commands: @@ -132,36 +104,14 @@ steps: mirror_hardwares: l4_1 - label: "Omni · Qwen3-Omni Test" - source_file_dependencies: - - tests/e2e/offline_inference/test_qwen3_omni.py - - tests/e2e/offline_inference/test_qwen3_omni_colocate_async.py - - tests/e2e/online_serving/test_qwen3_omni.py - - tests/helpers/runtime.py - - vllm_omni/entrypoints/openai/serving_chat.py - - vllm_omni/model_executor/models/qwen3_omni/ - - vllm_omni/model_executor/models/common/qwen3_code_predictor.py - - vllm_omni/model_executor/models/common/snake_activation.py - - vllm_omni/model_executor/models/qwen2_5_omni/qwen2_5_omni_thinker.py - - vllm_omni/model_executor/models/qwen3_tts/cuda_graph_decoder_wrapper.py - - vllm_omni/model_executor/stage_input_processors/qwen3_omni.py - - vllm_omni/deploy/qwen3_omni_moe.yaml - - vllm_omni/deploy/qwen3_omni_moe_thinking.yaml + source_file_dependencies: omni_qwen3_omni_function timeout_in_minutes: 50 commands: - pytest -s -v tests/e2e/offline_inference/test_qwen3_omni.py tests/e2e/online_serving/test_qwen3_omni.py tests/e2e/offline_inference/test_qwen3_omni_colocate_async.py -m 'advanced_model and cuda' --run-level 'advanced_model' mirror_hardwares: h100_2 - label: "Omni · MiniCPM-o 4.5 Test" - source_file_dependencies: - - tests/e2e/offline_inference/test_minicpmo_4_5.py - - tests/e2e/online_serving/test_minicpmo_4_5.py - - vllm_omni/transformers_utils/chat_templates/minicpmo45_native.jinja - - vllm_omni/model_executor/models/minicpmo_4_5/ - - vllm_omni/model_executor/models/step_audio2/ - - vllm_omni/model_executor/models/cosyvoice3/code2wav_core/ - - vllm_omni/model_executor/models/cosyvoice3/utils.py - - vllm_omni/model_executor/stage_input_processors/minicpmo_4_5_omni.py - - vllm_omni/deploy/minicpmo_4_5.yaml + source_file_dependencies: omni_minicpmo_4_5_function timeout_in_minutes: 50 commands: - pytest -s -v tests/e2e/offline_inference/test_minicpmo_4_5.py tests/e2e/online_serving/test_minicpmo_4_5.py -m 'advanced_model and cuda' --run-level 'advanced_model' @@ -174,59 +124,14 @@ steps: mirror_hardwares: h100_2 - label: "Omni · MiniCPM-o 4.5 Duplex Test" - source_file_dependencies: - - tests/assets/minicpmo_4_5/response_required_16k.wav - - tests/assets/minicpmo_4_5/soft_interrupt_16k.wav - - tests/e2e/online_serving/test_minicpmo_4_5_duplex.py - - tests/e2e/online_serving/test_minicpmo_4_5_duplex_expansion.py - - tests/e2e/online_serving/test_minicpmo_realtime_duplex_drivers.py - - tests/e2e/online_serving/helpers/minicpmo_realtime_duplex_scenarios.py - - tests/e2e/online_serving/run_minicpmo_realtime_duplex_multi_session.py - - tests/e2e/online_serving/run_minicpmo_realtime_duplex_server_vad.py - - tests/e2e/online_serving/run_minicpmo_realtime_duplex_soft_interrupt.py - - vllm_omni/deploy/minicpmo_4_5.yaml - - tests/e2e/online_serving/helpers/minicpmo_4_5_duplex.py - - vllm_omni/engine/duplex/ - - vllm_omni/entrypoints/duplex/ - # Public duplex client library + its unit suites: client-side - # changes must re-run the duplex e2e group. The live client probe - # (test_duplex_client_live.py, single GPU, core tier) runs in the - # ready pipeline's duplex group. - - vllm_omni/clients/ - - tests/clients/ - - vllm_omni/entrypoints/duplex_request_client.py - - vllm_omni/outputs/duplex.py - - vllm_omni/model_executor/duplex_sampling.py - - tests/engine/duplex/ - - tests/entrypoints/duplex/ - - tests/model_executor/models/minicpmo_4_5/duplex/ - # Legacy Realtime probe client + video stacking used by the e2e drivers. - - vllm_omni/experimental/fullduplex/ - - vllm_omni/model_executor/models/minicpmo_4_5/ - - vllm_omni/model_executor/models/step_audio2/ - - vllm_omni/model_executor/models/cosyvoice3/code2wav_core/ - - vllm_omni/model_executor/models/cosyvoice3/utils.py - - vllm_omni/model_executor/stage_input_processors/minicpmo_4_5_omni.py - - vllm_omni/core/sched/ - - vllm_omni/outputs/multimodal_accumulation.py - - vllm_omni/engine/stage_init_utils.py - - vllm_omni/engine/async_omni_engine.py - - vllm_omni/engine/orchestrator.py - - vllm_omni/entrypoints/cli/serve.py - - vllm_omni/entrypoints/openai/api_server.py - - vllm_omni/entrypoints/openai/duplex_capability.py - - vllm_omni/config/stage_config.py + source_file_dependencies: omni_minicpmo_4_5_duplex_function timeout_in_minutes: 50 commands: - pytest -s -v tests/e2e/online_serving/test_minicpmo_4_5_duplex.py -m 'advanced_model and cuda' --run-level 'advanced_model' mirror_hardwares: h100_1 - label: "Diffusion · Qwen Image Test" - source_file_dependencies: - - tests/e2e/online_serving/test_qwen_image.py - - vllm_omni/diffusion/models/qwen_image/ - - vllm_omni/diffusion/models/dmd2/ - - vllm_omni/diffusion/distributed/autoencoders/autoencoder_kl_qwenimage.py + source_file_dependencies: diffusion_qwen_image_function commands: - | timeout 40m bash -c ' @@ -236,11 +141,7 @@ steps: mirror_hardwares: h100_1 - label: "Diffusion · Wan22 Test" - source_file_dependencies: - - tests/e2e/offline_inference/test_wan22_t2v.py - - tests/e2e/online_serving/test_wan22_t2v.py - - vllm_omni/diffusion/models/wan2_2/ - - vllm_omni/diffusion/models/dmd2/ + source_file_dependencies: diffusion_wan22_function commands: - | timeout 40m bash -c " @@ -250,9 +151,7 @@ steps: mirror_hardwares: h100_1 - label: "Diffusion · HunyuanVideo-1.5 Test" - source_file_dependencies: - - tests/e2e/online_serving/test_hunyuan_video_15_expansion.py - - vllm_omni/diffusion/models/hunyuan_video/ + source_file_dependencies: diffusion_hunyuan_video_function commands: - | timeout 40m bash -c " @@ -262,17 +161,7 @@ steps: mirror_hardwares: h100_1 - label: "Diffusion · MiniMax-H3 L3 DLO DP2 and FastH3" - source_file_dependencies: - - tests/e2e/online_serving/minimax_h3/ - - tests/helpers/assertions.py - - tests/helpers/mark.py - - tests/helpers/media.py - - tests/helpers/runtime.py - - vllm_omni/diffusion/models/minimax_h3/ - - vllm_omni/diffusion/lora/ - - vllm_omni/diffusion/offloader/ - - vllm_omni/diffusion/distributed/ - - vllm_omni/entrypoints/openai/ + source_file_dependencies: diffusion_minimax_h3_function # Keep four server lifecycles in one Buildkite job, but never in one # pytest process. DLO uses multiprocessing shared-memory queues; the # parent's resource_tracker can retain a stale /psm_* entry during diff --git a/.buildkite/cuda/test-nightly.yml b/.buildkite/cuda/test-nightly.yml index c85e9abc1..ee4fc6f3e 100644 --- a/.buildkite/cuda/test-nightly.yml +++ b/.buildkite/cuda/test-nightly.yml @@ -12,26 +12,34 @@ steps: - group: ":card_index_dividers: Omni Model Test" key: nightly-omni-test-group depends_on: upload-nightly-pipeline - if: build.env("NIGHTLY") == "1" || build.pull_request.labels includes "nightly-test" || build.pull_request.labels includes "omni-test" + if: build.env("NIGHTLY") == "1" || build.pull_request.labels includes "nightly-test" steps: - label: ":full_moon: Omni · Function Test with H100 · Single-GPU" + source_file_dependencies: + - omni_qwen3_omni_function + - omni_minicpmo_4_5_function timeout_in_minutes: 120 commands: - pytest -sv tests/e2e --run-level "full_model" -m "full_model and H100 and B200 and omni and cards_1" --ignore=tests/e2e/accuracy --ignore=tests/e2e/online_serving/test_minicpmo_4_5_duplex_expansion.py - label: ":full_moon: Omni · Function Test with H100 · 2-GPU" + source_file_dependencies: + - omni_qwen3_omni_function + - omni_minicpmo_4_5_function timeout_in_minutes: 90 commands: - pytest -sv tests/e2e --run-level "full_model" -m "full_model and H100 and B200 and omni and cards_2" --ignore=tests/e2e/accuracy --ignore=tests/e2e/online_serving/test_qwen3_omni_multi_replicas.py - label: ":full_moon: Omni · MiniCPM-o 4.5 Duplex Test" + source_file_dependencies: omni_minicpmo_4_5_duplex_function timeout_in_minutes: 50 commands: - pytest -s -v tests/e2e/online_serving/test_minicpmo_4_5_duplex_expansion.py -m "full_model and cuda and H100 and omni and cards_1" --run-level "full_model" mirror_hardwares: h100_1 - label: ":full_moon: Omni · Doc Test with L4 · 4-GPU" + source_file_dependencies: omni_qwen2_5_omni_doc timeout_in_minutes: 90 commands: - export VLLM_ALLOW_LONG_MAX_MODEL_LEN="1" @@ -39,12 +47,14 @@ steps: mirror_hardwares: l4_4 - label: ":full_moon: Omni · Doc Test with H100 · 2-GPU" + source_file_dependencies: omni_qwen3_omni_doc timeout_in_minutes: 90 commands: - pytest -s -v tests/examples/ -m "full_model and omni and H100 and cards_2" --run-level "full_model" mirror_hardwares: h100_2 - label: ":full_moon: Omni · Accuracy Test" + source_file_dependencies: omni_qwen3_omni_accuracy timeout_in_minutes: 180 commands: - export SEED_TTS_WER_EVAL=1 @@ -58,6 +68,7 @@ steps: mirror_hardwares: h100_2 - label: ":full_moon: Omni · MiniCPM-o 4.5 · Accuracy Test" + source_file_dependencies: omni_minicpmo_4_5_accuracy timeout_in_minutes: 180 commands: - export SEED_TTS_WER_EVAL=1 @@ -71,6 +82,7 @@ steps: mirror_hardwares: h100_2 - label: ":full_moon: Omni · Perf Test · No Async Chunk" + source_file_dependencies: omni_qwen3_omni_perf key: nightly-omni-performance-no-async-chunk timeout_in_minutes: 300 commands: @@ -84,6 +96,7 @@ steps: mirror_hardwares: h100_2 - label: ":full_moon: Omni · Perf Test · Async Chunk" + source_file_dependencies: omni_qwen3_omni_perf key: nightly-omni-performance-async-chunk timeout_in_minutes: 180 commands: @@ -97,19 +110,21 @@ steps: mirror_hardwares: h100_2 - label: ":full_moon: Omni · MiniCPM-o 4.5 · Perf Test" + source_file_dependencies: omni_minicpmo_4_5_perf key: nightly-omni-performance-minicpmo-4-5 timeout_in_minutes: 180 commands: - export BENCHMARK_DIR=tests/dfx/perf/results - | set +e - pytest -s -v tests/dfx/perf/scripts/run_benchmark.py --test-config-file tests/dfx/perf/tests/test_minicpmo_4_5.json + pytest -s -v tests/dfx/perf/scripts/run_benchmark.py --test-config-file tests/dfx/perf/tests/test_minicpmo_4_5.json -m "H100 and cards_1" EXIT=$$? buildkite-agent artifact upload "tests/dfx/perf/results/*.json" exit $$EXIT mirror_hardwares: h100_1 - label: ":full_moon: Omni · MiniCPM-o 4.5 · Duplex Seed-TTS Perf Test" + source_file_dependencies: omni_minicpmo_4_5_duplex_perf key: nightly-omni-performance-minicpmo-4-5-duplex-seed-tts timeout_in_minutes: 180 commands: @@ -123,6 +138,7 @@ steps: mirror_hardwares: h100_1 - label: ":full_moon: Omni · Multi-Replica Startup Test with 4x H100" + source_file_dependencies: omni_qwen3_omni_function timeout_in_minutes: 45 commands: - pytest -s -v tests/e2e/online_serving/test_qwen3_omni_multi_replicas.py -m "full_model" --run-level "core_model" @@ -131,10 +147,11 @@ steps: - group: ":card_index_dividers: TTS Model Test" key: nightly-tts-test-group depends_on: upload-nightly-pipeline - if: build.env("NIGHTLY") == "1" || build.pull_request.labels includes "nightly-test" || build.pull_request.labels includes "tts-test" + if: build.env("NIGHTLY") == "1" || build.pull_request.labels includes "nightly-test" steps: - label: ":full_moon: TTS · Function Test with L4" + source_file_dependencies: tts_qwen3_tts_function timeout_in_minutes: 120 commands: - export VLLM_ALLOW_LONG_MAX_MODEL_LEN="1" @@ -144,6 +161,7 @@ steps: mirror_hardwares: l4_1 - label: ":full_moon: TTS · Perf Test · Single-GPU" + source_file_dependencies: tts_qwen3_tts_perf key: nightly-tts-performance-single timeout_in_minutes: 180 commands: @@ -158,6 +176,7 @@ steps: mirror_hardwares: h100_1 - label: ":full_moon: TTS · Perf Test · 2-GPU" + source_file_dependencies: tts_qwen3_tts_perf key: nightly-tts-performance-2gpu timeout_in_minutes: 180 commands: @@ -180,6 +199,7 @@ steps: steps: - label: ":full_moon: Tiny Model Tests · Diffusion (Multi-GPU accelerations) · 2-GPU" + source_file_dependencies: diffusion_tiny_model timeout_in_minutes: 30 # NOTE: Single-GPU (core_model) tiny model tests run on the ready label, # so nightly only adds the multi-GPU parallelism configurations. @@ -193,6 +213,7 @@ steps: mirror_hardwares: l4_2 - label: ":full_moon: Tiny Model Tests · Diffusion (Multi-GPU accelerations) · 4-GPU" + source_file_dependencies: diffusion_tiny_model timeout_in_minutes: 30 # CFG+TP extra_test_groups request 2×2=4 devices (see get_required_device_count). commands: @@ -204,11 +225,11 @@ steps: depends_on: upload-nightly-pipeline if: >- build.env("NIGHTLY") == "1" || - build.pull_request.labels includes "nightly-test" || - build.pull_request.labels includes "diffusion-x2iat-test" + build.pull_request.labels includes "nightly-test" steps: - label: ":full_moon: Diffusion X2I(&A&T) · Function Test with H100 · Single-GPU" + source_file_dependencies: diffusion_qwen_image_function timeout_in_minutes: 120 commands: - >- @@ -219,6 +240,7 @@ steps: mirror_hardwares: h100_1 - label: ":full_moon: Diffusion X2I(&A&T) · Function Test with H100 · 2-GPU" + source_file_dependencies: diffusion_qwen_image_function timeout_in_minutes: 120 commands: - >- @@ -228,30 +250,26 @@ steps: --run-level "full_model" mirror_hardwares: h100_2 - - label: ":full_moon: Diffusion X2I(&A&T) · Boogu Edit CFG · 3-GPU" + - label: ":full_moon: Diffusion X2I(&A&T) · Z-Image Function Test · L4 · 4-GPU" + source_file_dependencies: diffusion_z_image_function timeout_in_minutes: 120 commands: - >- pytest -sv - tests/e2e/online_serving/test_boogu_image_edit_expansion.py - -k "test_double_guidance_cfg_parallel and cfg_parallel_3_full" - -m "slow and diffusion and cuda and H100 and cards_3" + tests/e2e/online_serving/test_zimage_expansion.py + -m "full_model and diffusion and L4 and cards_4" --run-level "full_model" - mirror_hardwares: h100_3 - - - label: ":full_moon: Diffusion X2I(&A&T) · Function Test with L4 · 4-GPU" - timeout_in_minutes: 120 - commands: - - pytest -sv tests/e2e/ -k "not test_wan and not hunyuan" -m "full_model and diffusion and L4 and cards_4" --run-level "full_model" --ignore=tests/e2e/accuracy mirror_hardwares: l4_4 - label: ":full_moon: Diffusion X2I(&A&T) · Doc Test" + source_file_dependencies: diffusion_text_to_image_doc timeout_in_minutes: 60 commands: - pytest -s -v tests/examples/*/test_text_to_image.py -m "full_model and example and H100" --run-level "full_model" mirror_hardwares: h100_2 - label: ":full_moon: Diffusion X2I(&A&T) · Accuracy Test" + source_file_dependencies: diffusion_qwen_image_accuracy timeout_in_minutes: 180 commands: - export VLLM_HTTP_TIMEOUT_KEEP_ALIVE=120 @@ -260,6 +278,7 @@ steps: mirror_hardwares: h100_1 - label: ":full_moon: HunyuanImage3-DIT · Accuracy Test" + source_file_dependencies: diffusion_hunyuan_image3_accuracy timeout_in_minutes: 180 commands: - export HUNYUAN_IMAGE3_MODEL="tencent/HunyuanImage-3.0-Instruct" @@ -267,13 +286,8 @@ steps: - pytest -s -v tests/e2e/accuracy/test_hunyuan_image3_pixel_accuracy.py -m full_model --run-level full_model mirror_hardwares: h100_4 - - label: ":full_moon: HiDream-O1-Image · Accuracy Test" - timeout_in_minutes: 180 - commands: - - pytest -s -v tests/e2e/accuracy/test_hidream_o1_image.py -m full_model --run-level full_model - mirror_hardwares: h100_2 - - label: ":full_moon: Diffusion X2I(&A&T) · Perf Test · Qwen-Image · Single-GPU" + source_file_dependencies: diffusion_qwen_image_perf key: nightly-diffusion-x2iat-performance-qwen-image-single timeout_in_minutes: 180 commands: @@ -289,6 +303,7 @@ steps: mirror_hardwares: h100_1 - label: ":full_moon: Diffusion X2I(&A&T) · Perf Test · Qwen-Image · 4-GPU" + source_file_dependencies: diffusion_qwen_image_perf key: nightly-diffusion-x2iat-performance-qwen-image-4gpu timeout_in_minutes: 180 commands: @@ -309,59 +324,73 @@ steps: depends_on: upload-nightly-pipeline if: >- build.env("NIGHTLY") == "1" || - build.pull_request.labels includes "nightly-test" || - build.pull_request.labels includes "diffusion-x2v-test" + build.pull_request.labels includes "nightly-test" steps: - label: ":full_moon: Diffusion X2V · Wan2.2 T2V Function Test · Single-GPU" + source_file_dependencies: diffusion_wan22_function timeout_in_minutes: 90 commands: - pytest -s -v tests/e2e/online_serving/test_wan22_expansion.py -k "t2v" -m "full_model and cuda and H100 and cards_1" --run-level "full_model" mirror_hardwares: h100_1 - label: ":full_moon: Diffusion X2V · Wan2.2 T2V Function Test · 2-GPU" + source_file_dependencies: diffusion_wan22_function timeout_in_minutes: 90 commands: - pytest -s -v tests/e2e/online_serving/test_wan22_expansion.py -k "t2v" -m "full_model and cuda and H100 and cards_2" --run-level "full_model" mirror_hardwares: h100_2 - label: ":full_moon: Diffusion X2V · Wan2.2 I2V/TI2V Function Test · Single-GPU" + source_file_dependencies: diffusion_wan22_function timeout_in_minutes: 90 commands: - pytest -s -v tests/e2e/online_serving/test_wan22_expansion.py -k "i2v" -m "full_model and cuda and H100 and cards_1" --run-level "full_model" mirror_hardwares: h100_1 - label: ":full_moon: Diffusion X2V · Wan2.2 I2V/TI2V Function Test · 2-GPU" + source_file_dependencies: diffusion_wan22_function timeout_in_minutes: 90 commands: - pytest -s -v tests/e2e/online_serving/test_wan22_expansion.py -k "i2v" -m "full_model and cuda and H100 and cards_2" --run-level "full_model" mirror_hardwares: h100_2 - label: ":full_moon: Diffusion X2V · HunyuanVideo-1.5 Function Test" + source_file_dependencies: diffusion_hunyuan_video_function timeout_in_minutes: 90 commands: - pytest -s -v tests/e2e/online_serving/test_hunyuan_video_15_expansion.py -m "full_model and cuda" --run-level "full_model" mirror_hardwares: h100_2 - - label: ":full_moon: Diffusion X2V · MAGI-2 Preview Serving Smoke" - timeout_in_minutes: 180 + - label: ":full_moon: Diffusion X2V · LingBot Function Test" + source_file_dependencies: diffusion_lingbot_function + timeout_in_minutes: 120 commands: - - pytest -s -v tests/e2e/online_serving/test_magi2.py -m "advanced_model and diffusion and cuda and H100 and cards_4" --run-level "advanced_model" - mirror_hardwares: h100_4 + - >- + pytest -s -v + tests/e2e/online_serving/test_lingbot_video.py + tests/e2e/online_serving/test_lingbot_video_moe.py + tests/e2e/offline_inference/test_lingbot_world_v2.py + -m "full_model and diffusion and H100 and cards_1" + --run-level "full_model" + mirror_hardwares: h100_1 - label: ":full_moon: Diffusion X2V · Doc Test" + source_file_dependencies: diffusion_image_to_video_doc timeout_in_minutes: 60 commands: - pytest -s -v tests/examples/offline_inference/test_image_to_video.py -m "full_model and example and H100" --run-level "full_model" mirror_hardwares: h100_1 - - label: ":full_moon: Diffusion X2V · Other Function Test" + - label: ":full_moon: Diffusion X2V · Wan2.2 Autoround Function Test" + source_file_dependencies: diffusion_wan22_function timeout_in_minutes: 90 commands: - pytest -s -v tests/e2e/offline_inference/test_wan22_autoround_w4a16_expansion.py -m "full_model and cuda" --run-level "full_model" mirror_hardwares: h100_2 - label: ":full_moon: Diffusion X2V · Wan2.2 Accuracy Test" + source_file_dependencies: diffusion_wan22_accuracy timeout_in_minutes: 180 commands: - pytest -s -v tests/e2e/accuracy/wan22_i2v/test_wan22_i2v_video_similarity.py -m full_model --run-level full_model @@ -369,12 +398,14 @@ steps: mirror_hardwares: h100_2 - label: ":full_moon: Diffusion X2V · MiniMax H3 I2VA/Ref2VA Accuracy Test" + source_file_dependencies: diffusion_minimax_h3_accuracy timeout_in_minutes: 180 commands: - pytest -s -v tests/e2e/accuracy/minimax_h3/test_minimax_h3_i2va_ref2va_similarity.py -m full_model --run-level full_model mirror_hardwares: h100_4 - - label: ":full_moon: Diffusion X2V · Other Accuracy Test" + - label: ":full_moon: Diffusion X2V · HunyuanVideo-1.5 Accuracy Test" + source_file_dependencies: diffusion_hunyuan_video_accuracy timeout_in_minutes: 180 commands: - pytest -s -v tests/e2e/accuracy/hunyuanvideo15_t2v/test_hunyuanvideo15_t2v_video_similarity.py -m full_model --run-level full_model @@ -382,6 +413,7 @@ steps: mirror_hardwares: h100_2 - label: ":full_moon: Diffusion X2V · Perf Test · Single-GPU" + source_file_dependencies: diffusion_wan22_perf key: nightly-diffusion-x2v-performance-single timeout_in_minutes: 180 commands: @@ -396,6 +428,9 @@ steps: mirror_hardwares: h100_1 - label: ":full_moon: Diffusion X2V · Perf Test · 2-GPU" + source_file_dependencies: + - diffusion_wan22_perf + - diffusion_cosmos3_perf key: nightly-diffusion-x2v-performance-2gpu timeout_in_minutes: 180 commands: @@ -414,6 +449,7 @@ steps: mirror_hardwares: h100_2 - label: ":full_moon: Diffusion X2V · Perf Test · HunyuanVideo-1.5" + source_file_dependencies: diffusion_hunyuan_video_perf key: nightly-diffusion-x2v-performance-hunyuanvideo15 timeout_in_minutes: 180 commands: @@ -431,6 +467,7 @@ steps: mirror_hardwares: h100_2 - label: ":full_moon: Diffusion X2V · Perf Test · MiniMax-H3" + source_file_dependencies: diffusion_minimax_h3_perf key: nightly-diffusion-x2v-performance-minimax-h3 timeout_in_minutes: 180 commands: @@ -450,54 +487,63 @@ steps: if: build.env("NIGHTLY") == "1" || build.pull_request.labels includes "nightly-test" steps: - label: ":full_moon: Diffusion · Distributed Test with L4 · 2-GPU" + source_file_dependencies: diffusion_distributed_attention timeout_in_minutes: 60 commands: - pytest -sv tests/diffusion/distributed/ -m 'full_model and cuda and L4 and cards_2' --run-level "full_model" mirror_hardwares: l4_2 - label: ":full_moon: Diffusion · Distributed Test with L4 · 3-GPU" + source_file_dependencies: diffusion_distributed_attention timeout_in_minutes: 60 commands: - pytest -sv tests/diffusion/distributed/ -m 'full_model and cuda and L4 and cards_3' --run-level "full_model" mirror_hardwares: l4_3 - label: ":full_moon: Diffusion · Distributed Test with L4 · 4-GPU" + source_file_dependencies: diffusion_distributed_attention timeout_in_minutes: 60 commands: - pytest -sv tests/diffusion/distributed/ -m 'full_model and cuda and L4 and cards_4' --run-level "full_model" mirror_hardwares: l4_4 - label: ":full_moon: Diffusion · Distributed Test with H100 · 2-GPU" + source_file_dependencies: diffusion_distributed_attention timeout_in_minutes: 60 commands: - pytest -sv tests/diffusion/distributed/ -m 'full_model and cuda and H100 and cards_2' --run-level "full_model" mirror_hardwares: h100_2 - label: ":full_moon: Diffusion · Distributed Test with H100 · 4-GPU" + source_file_dependencies: diffusion_distributed_attention timeout_in_minutes: 60 commands: - pytest -sv tests/diffusion/distributed/ -m 'full_model and cuda and H100 and cards_4' --run-level "full_model" mirror_hardwares: h100_4 - label: ":full_moon: Diffusion · Offloader Test" + source_file_dependencies: diffusion_offloader timeout_in_minutes: 60 commands: - pytest -sv tests/diffusion/offloader -m "full_model and cuda" mirror_hardwares: l4_1 - label: ":full_moon: Diffusion · Quantization Test with H100 · Single-GPU" + source_file_dependencies: diffusion_quantization timeout_in_minutes: 60 commands: - pytest -sv tests/diffusion/quantization -m 'full_model and cuda and H100' --run-level "full_model" mirror_hardwares: h100_1 - label: ":full_moon: Diffusion · MiniMax H3 FP8 Quality Test with H100 · 2-GPU" + source_file_dependencies: diffusion_minimax_h3_function timeout_in_minutes: 60 commands: - pytest -sv tests/diffusion/models/minimax_h3/test_minimax_h3_quantization_quality.py -m 'full_model and cuda and H100' --run-level "full_model" mirror_hardwares: h100_2 - label: ":full_moon: Diffusion · Quantization Test with L4" + source_file_dependencies: diffusion_quantization timeout_in_minutes: 60 commands: - pip install "vllm-gguf-plugin==0.0.4" diff --git a/.buildkite/cuda/test-ready.yml b/.buildkite/cuda/test-ready.yml index 6d8d1e8b9..67f03dbb6 100644 --- a/.buildkite/cuda/test-ready.yml +++ b/.buildkite/cuda/test-ready.yml @@ -54,16 +54,19 @@ steps: mirror_hardwares: l4_1 - label: "Diffusion · Distributed Test · Single-GPU" + source_file_dependencies: diffusion_distributed_attention commands: - timeout 20m pytest -sv tests/diffusion/distributed -m 'core_model and cuda and L4 and cards_1' --run-level "core_model" mirror_hardwares: l4_1 - label: "Diffusion · Distributed Test · 2-GPU" + source_file_dependencies: diffusion_distributed_attention commands: - timeout 20m pytest -sv tests/diffusion/distributed -m 'core_model and cuda and L4 and cards_2' --run-level "core_model" mirror_hardwares: l4_2 - label: "Diffusion · Distributed & Attention Test · 4-GPU" + source_file_dependencies: diffusion_distributed_attention commands: - timeout 20m pytest -sv tests/diffusion/distributed -m 'core_model and cuda and L4 and cards_4' --run-level "core_model" - timeout 20m pytest -sv tests/diffusion/attention/test_attention_sp.py -m 'core_model and cuda and L4 and cards_4' --run-level "core_model" @@ -120,29 +123,14 @@ steps: depends_on: upload-ready-pipeline steps: - label: "Custom Pipeline Test" - source_file_dependencies: - - tests/e2e/features/custom_pipeline/ - - tests/e2e/features/helpers/custom_pipeline.py - - vllm_omni/diffusion/ - - vllm_omni/engine/ - - vllm_omni/entrypoints/ - - vllm_omni/inputs/ - - vllm_omni/outputs/ + source_file_dependencies: custom_pipeline commands: - timeout 20m pytest -s -v tests/e2e/features/custom_pipeline/ -m "core_model" mirror_hardwares: l4_1 - label: "RLHF · VeRL-Omni E2E Test" - source_file_dependencies: - - tests/e2e/features/rlhf_test/test_verl_omni_e2e.py - - tests/e2e/features/helpers/verl_omni_server.py - - tests/e2e/features/helpers/custom_pipeline.py - - vllm_omni/diffusion/ - - vllm_omni/engine/ - - vllm_omni/entrypoints/ - - vllm_omni/inputs/ - - vllm_omni/outputs/ + source_file_dependencies: rlhf_verl_omni commands: - | timeout 20m bash -c " @@ -151,17 +139,7 @@ steps: mirror_hardwares: l4_1 - label: "Omni · Qwen3-Omni Test" - source_file_dependencies: - - tests/e2e/online_serving/test_qwen3_omni.py - - tests/helpers/runtime.py - - vllm_omni/entrypoints/openai/serving_chat.py - - vllm_omni/model_executor/models/qwen3_omni/ - - vllm_omni/model_executor/models/common/qwen3_code_predictor.py - - vllm_omni/model_executor/models/common/snake_activation.py - - vllm_omni/model_executor/models/qwen2_5_omni/qwen2_5_omni_thinker.py - - vllm_omni/model_executor/models/qwen3_tts/cuda_graph_decoder_wrapper.py - - vllm_omni/model_executor/stage_input_processors/qwen3_omni.py - - vllm_omni/deploy/qwen3_omni_moe.yaml + source_file_dependencies: omni_qwen3_omni_function commands: - | timeout 20m bash -c " @@ -170,14 +148,7 @@ steps: mirror_hardwares: h100_2 - label: "Omni · MiniCPM-o 4.5 Offline Test" - source_file_dependencies: - - tests/e2e/offline_inference/test_minicpmo_4_5.py - - vllm_omni/model_executor/models/minicpmo_4_5/ - - vllm_omni/model_executor/models/step_audio2/ - - vllm_omni/model_executor/models/cosyvoice3/code2wav_core/ - - vllm_omni/model_executor/models/cosyvoice3/utils.py - - vllm_omni/model_executor/stage_input_processors/minicpmo_4_5_omni.py - - vllm_omni/deploy/minicpmo_4_5.yaml + source_file_dependencies: omni_minicpmo_4_5_function commands: - | timeout 20m bash -c " @@ -186,15 +157,7 @@ steps: mirror_hardwares: h100_1 - label: "Omni · MiniCPM-o 4.5 Online Test" - source_file_dependencies: - - tests/e2e/online_serving/test_minicpmo_4_5.py - - vllm_omni/transformers_utils/chat_templates/minicpmo45_native.jinja - - vllm_omni/model_executor/models/minicpmo_4_5/ - - vllm_omni/model_executor/models/step_audio2/ - - vllm_omni/model_executor/models/cosyvoice3/code2wav_core/ - - vllm_omni/model_executor/models/cosyvoice3/utils.py - - vllm_omni/model_executor/stage_input_processors/minicpmo_4_5_omni.py - - vllm_omni/deploy/minicpmo_4_5.yaml + source_file_dependencies: omni_minicpmo_4_5_function commands: - | timeout 20m bash -c " @@ -203,48 +166,7 @@ steps: mirror_hardwares: h100_1 - label: "Omni · MiniCPM-o 4.5 Duplex Test" - source_file_dependencies: - - tests/assets/minicpmo_4_5/response_required_16k.wav - - tests/assets/minicpmo_4_5/soft_interrupt_16k.wav - - tests/e2e/online_serving/test_minicpmo_4_5_duplex.py - - tests/e2e/online_serving/test_minicpmo_4_5_duplex_expansion.py - - tests/e2e/online_serving/test_minicpmo_realtime_duplex_drivers.py - - tests/e2e/online_serving/helpers/minicpmo_realtime_duplex_scenarios.py - - tests/e2e/online_serving/run_minicpmo_realtime_duplex_multi_session.py - - tests/e2e/online_serving/run_minicpmo_realtime_duplex_server_vad.py - - tests/e2e/online_serving/run_minicpmo_realtime_duplex_soft_interrupt.py - - vllm_omni/deploy/minicpmo_4_5.yaml - - tests/e2e/online_serving/helpers/minicpmo_4_5_duplex.py - - vllm_omni/engine/duplex/ - - vllm_omni/entrypoints/duplex/ - # Public duplex client library + its unit suites: client-side - # changes must re-run the duplex e2e group, which includes the - # live client probe (test_duplex_client_live.py, single GPU). - - vllm_omni/clients/ - - tests/clients/ - - tests/e2e/online_serving/test_duplex_client_live.py - - vllm_omni/entrypoints/duplex_request_client.py - - vllm_omni/outputs/duplex.py - - vllm_omni/model_executor/duplex_sampling.py - - tests/engine/duplex/ - - tests/entrypoints/duplex/ - - tests/model_executor/models/minicpmo_4_5/duplex/ - # Legacy Realtime probe client + video stacking used by the e2e drivers. - - vllm_omni/experimental/fullduplex/ - - vllm_omni/model_executor/models/minicpmo_4_5/ - - vllm_omni/model_executor/models/step_audio2/ - - vllm_omni/model_executor/models/cosyvoice3/code2wav_core/ - - vllm_omni/model_executor/models/cosyvoice3/utils.py - - vllm_omni/model_executor/stage_input_processors/minicpmo_4_5_omni.py - - vllm_omni/core/sched/ - - vllm_omni/outputs/multimodal_accumulation.py - - vllm_omni/engine/stage_init_utils.py - - vllm_omni/engine/async_omni_engine.py - - vllm_omni/engine/orchestrator.py - - vllm_omni/entrypoints/cli/serve.py - - vllm_omni/entrypoints/openai/api_server.py - - vllm_omni/entrypoints/openai/duplex_capability.py - - vllm_omni/config/stage_config.py + source_file_dependencies: omni_minicpmo_4_5_duplex_function commands: - | timeout 35m bash -c " @@ -254,29 +176,14 @@ steps: - label: "Omni · MiniCPM-o 4.5 Perf Test" timeout_in_minutes: 60 - source_file_dependencies: - - tests/dfx/perf/tests/test_minicpmo_4_5_ready.json - - vllm_omni/deploy/minicpmo_4_5.yaml - - vllm_omni/model_executor/models/minicpmo_4_5/ - - vllm_omni/model_executor/stage_input_processors/minicpmo_4_5_omni.py + source_file_dependencies: omni_minicpmo_4_5_perf commands: - export BENCHMARK_DIR=tests/dfx/perf/results - pytest -s -v tests/dfx/perf/scripts/run_benchmark.py --test-config-file tests/dfx/perf/tests/test_minicpmo_4_5_ready.json -m 'core_model and cuda' mirror_hardwares: h100_1 - label: "TTS · Qwen3-TTS CustomVoice Test" - source_file_dependencies: - - tests/helpers/media.py - - tests/e2e/online_serving/test_qwen3_tts_customvoice.py - - vllm_omni/model_executor/models/qwen3_tts/ - - vllm_omni/model_executor/models/common/qwen3_code_predictor.py - - vllm_omni/model_executor/models/common/snake_activation.py - - vllm_omni/model_executor/models/common/alias_free_activation.py - - vllm_omni/model_executor/stage_input_processors/qwen3_tts.py - - vllm_omni/deploy/qwen3_tts.yaml - - vllm_omni/entrypoints/openai/serving_speech.py - - vllm_omni/entrypoints/openai/tts_adapters/ - - vllm_omni/engine/stage_pool.py + source_file_dependencies: tts_qwen3_tts_function commands: - | timeout 20m bash -c " @@ -286,10 +193,7 @@ steps: mirror_hardwares: l4_1 - label: "Diffusion · Wan22 Test" - source_file_dependencies: - - tests/e2e/online_serving/test_wan22_t2v.py - - vllm_omni/diffusion/models/wan2_2/ - - vllm_omni/diffusion/models/dmd2/ + source_file_dependencies: diffusion_wan22_function commands: - | timeout 40m bash -c " @@ -299,12 +203,7 @@ steps: mirror_hardwares: h100_1 - label: "Diffusion · Cosmos3 Test" - source_file_dependencies: - - tests/e2e/online_serving/test_cosmos3.py - - vllm_omni/diffusion/models/cosmos3/ - - vllm_omni/diffusion/distributed/autoencoders/autoencoder_kl_wan.py - - vllm_omni/experimental/world_models/ - - vllm_omni/model_extras/cosmos3.py + source_file_dependencies: diffusion_cosmos3_function commands: - | timeout 40m bash -c " @@ -315,14 +214,7 @@ steps: - label: "Diffusion · MiniMax-H3 DLO DP2 T2VA Test" timeout_in_minutes: 90 - source_file_dependencies: - - tests/e2e/online_serving/test_minimax_h3_dlo_dp2_t2va.py - - tests/helpers/assertions.py - - tests/helpers/runtime.py - - vllm_omni/diffusion/models/minimax_h3/ - - vllm_omni/diffusion/offloader/ - - vllm_omni/diffusion/distributed/ - - vllm_omni/entrypoints/openai/ + source_file_dependencies: diffusion_minimax_h3_function commands: - | timeout 80m bash -c " @@ -332,11 +224,7 @@ steps: mirror_hardwares: h100_2 - label: "Diffusion · Qwen Image Test" - source_file_dependencies: - - tests/e2e/online_serving/test_qwen_image.py - - vllm_omni/diffusion/models/qwen_image/ - - vllm_omni/diffusion/models/dmd2/ - - vllm_omni/diffusion/distributed/autoencoders/autoencoder_kl_qwenimage.py + source_file_dependencies: diffusion_qwen_image_function commands: - | timeout 40m bash -c " @@ -346,9 +234,7 @@ steps: mirror_hardwares: h100_1 - label: "Diffusion · HunyuanVideo-1.5 Test" - source_file_dependencies: - - tests/e2e/online_serving/test_hunyuan_video_15_expansion.py - - vllm_omni/diffusion/models/hunyuan_video/ + source_file_dependencies: diffusion_hunyuan_video_function commands: - | timeout 40m bash -c " diff --git a/.buildkite/cuda/test-weekly.yml b/.buildkite/cuda/test-weekly.yml index 614af9572..d53bc56e4 100644 --- a/.buildkite/cuda/test-weekly.yml +++ b/.buildkite/cuda/test-weekly.yml @@ -29,36 +29,42 @@ steps: steps: - label: "Reliability Test · qwen3-omni" + source_file_dependencies: omni_qwen3_omni_reliability timeout_in_minutes: 180 commands: - pytest -s -v tests/dfx/reliability/test_reliability_qwen3_omni.py -m "slow" mirror_hardwares: h100_2 - label: "Reliability Test · wan22" + source_file_dependencies: diffusion_wan22_reliability timeout_in_minutes: 180 commands: - pytest -s -v tests/dfx/reliability/test_reliability_wan22.py -m "slow" mirror_hardwares: h100_2 - label: "Reliability Test · hunyuan-image" + source_file_dependencies: diffusion_hunyuan_image3_reliability timeout_in_minutes: 180 commands: - pytest -s -v tests/dfx/reliability/test_reliability_hunyuan_image.py -m "slow" mirror_hardwares: h100_4 - label: "Reliability Test · Invalid parameters · H100 · Single-GPU" + source_file_dependencies: reliability_invalid_param_h100 timeout_in_minutes: 90 commands: - pytest -s -v tests/dfx/reliability/invalid_param_test/ -m "slow and H100 and cards_1" mirror_hardwares: h100_1 - label: "Reliability Test · Invalid parameters · H100 · 2-GPU" + source_file_dependencies: reliability_invalid_param_h100 timeout_in_minutes: 90 commands: - pytest -s -v tests/dfx/reliability/invalid_param_test/ -m "slow and H100 and cards_2" mirror_hardwares: h100_2 - label: "Reliability Test · Invalid parameters · L4" + source_file_dependencies: reliability_invalid_param_l4 timeout_in_minutes: 120 commands: - pytest -s -v tests/dfx/reliability/invalid_param_test/ -m "slow and L4" @@ -70,6 +76,7 @@ steps: steps: - label: ":full_moon: Omni · Perf Test · vLLM Text" + source_file_dependencies: omni_qwen3_omni_perf key: weekly-omni-performance-vllm-text timeout_in_minutes: 180 commands: @@ -96,6 +103,7 @@ steps: mirror_hardwares: h100_2 - label: ":full_moon: Omni · Perf Test · Multi-Replica" + source_file_dependencies: omni_qwen3_omni_perf key: weekly-omni-performance-multi-replicas timeout_in_minutes: 180 commands: @@ -221,21 +229,262 @@ steps: --run-level "full_model" mirror_hardwares: l4_4 - - label: "Diffusion · H100 · Single-GPU" - timeout_in_minutes: 150 + # Split the old shared H100 Single-GPU sweep: one pytest process collected + # every slow+cards_1 diffusion file and exceeded 150 minutes. + - label: "Diffusion · Qwen-Image · H100 · Single-GPU" + timeout_in_minutes: 120 commands: - >- pytest -sv - tests/e2e/ -m "slow and diffusion and H100 and cards_1" + tests/e2e/online_serving/test_qwen_image_edit.py + tests/e2e/online_serving/test_qwen_image_edit_expansion.py + tests/e2e/online_serving/test_qwen_image_layered.py + tests/e2e/online_serving/test_qwen_image_layered_expansion.py + tests/e2e/accuracy/test_qwen_image_edit.py + tests/e2e/accuracy/test_qwen_image_layered.py + -m "slow and diffusion and H100 and cards_1" --run-level "full_model" mirror_hardwares: h100_1 - - label: "Diffusion · H100 · 2-GPU" + - label: "Diffusion · Wan2.1 VACE · H100 · Single-GPU" timeout_in_minutes: 90 commands: - >- pytest -sv - tests/e2e/ -m "slow and diffusion and H100 and cards_2" + tests/e2e/online_serving/test_wan_2_1_vace_expansion.py + -m "slow and diffusion and H100 and cards_1" + --run-level "full_model" + mirror_hardwares: h100_1 + + - label: "Diffusion · LongCat · H100 · Single-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_longcat_image_expansion.py + tests/e2e/online_serving/test_longcat_image_edit_expansion.py + -m "slow and diffusion and H100 and cards_1" + --run-level "full_model" + mirror_hardwares: h100_1 + + - label: "Diffusion · Bagel · H100 · Single-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_bagel.py + tests/e2e/online_serving/test_bagel_expansion.py + tests/e2e/offline_inference/test_bagel.py + tests/e2e/offline_inference/test_bagel_expansion.py + -m "slow and diffusion and H100 and cards_1" + --run-level "full_model" + mirror_hardwares: h100_1 + + - label: "Diffusion · Boogu · H100 · Single-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_boogu_image.py + tests/e2e/online_serving/test_boogu_image_edit.py + tests/e2e/online_serving/test_boogu_image_expansion.py + tests/e2e/online_serving/test_boogu_image_edit_expansion.py + -m "slow and diffusion and H100 and cards_1" + --run-level "full_model" + mirror_hardwares: h100_1 + + - label: "Diffusion · Flux · H100 · Single-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_flux_2_dev_expansion.py + tests/e2e/offline_inference/test_flux1_schnell_expansion.py + -m "slow and diffusion and H100 and cards_1" + --run-level "full_model" + mirror_hardwares: h100_1 + + - label: "Diffusion · LTX · H100 · Single-GPU" + timeout_in_minutes: 120 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_ltx.py + tests/e2e/online_serving/test_ltx25.py + tests/e2e/accuracy/ltx/test_ltx_official_similarity.py + tests/e2e/accuracy/ltx/test_ltx25_official_similarity.py + -m "slow and diffusion and H100 and cards_1" + --run-level "full_model" + mirror_hardwares: h100_1 + + - label: "Diffusion · Krea2 · H100 · Single-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_krea2_expansion.py + tests/e2e/offline_inference/test_krea2_expansion.py + -m "slow and diffusion and H100 and cards_1" + --run-level "full_model" + mirror_hardwares: h100_1 + + - label: "Diffusion · HiDream-I1 · H100 · Single-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_hidream_i1_full_expansion.py + -m "slow and diffusion and H100 and cards_1" + --run-level "full_model" + mirror_hardwares: h100_1 + + - label: "Diffusion · SANA-Video · H100 · Single-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_sana_video_expansion.py + -m "slow and diffusion and H100 and cards_1" + --run-level "full_model" + mirror_hardwares: h100_1 + + - label: "Diffusion · SenseNova-U1 · H100 · Single-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/offline_inference/test_sensenova_u1_expansion.py + tests/e2e/offline_inference/test_sensenova_u1_text2img_expansion.py + tests/e2e/offline_inference/test_sensenova_u1_img2img_expansion.py + -m "slow and diffusion and H100 and cards_1" + --run-level "full_model" + mirror_hardwares: h100_1 + + - label: "Diffusion · MammothModa2 · H100 · Single-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/offline_inference/test_mammoth_moda2_expansion.py + -m "slow and diffusion and H100 and cards_1" + --run-level "full_model" + mirror_hardwares: h100_1 + + - label: "Diffusion · Helios · H100 · Single-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/accuracy/test_video_streaming_output_similarity.py + -m "slow and diffusion and H100 and cards_1" + --run-level "full_model" + mirror_hardwares: h100_1 + + # Split the old shared H100 2-GPU sweep: one pytest process collected every + # slow+cards_2 diffusion file and exceeded 90 minutes. + - label: "Diffusion · Qwen-Image · H100 · 2-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_qwen_image_edit_expansion.py + tests/e2e/online_serving/test_qwen_image_layered_expansion.py + -m "slow and diffusion and H100 and cards_2" + --run-level "full_model" + mirror_hardwares: h100_2 + + - label: "Diffusion · Wan2.1 VACE · H100 · 2-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_wan_2_1_vace_expansion.py + -m "slow and diffusion and H100 and cards_2" + --run-level "full_model" + mirror_hardwares: h100_2 + + - label: "Diffusion · LongCat · H100 · 2-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_longcat_image_expansion.py + tests/e2e/online_serving/test_longcat_image_edit_expansion.py + -m "slow and diffusion and H100 and cards_2" + --run-level "full_model" + mirror_hardwares: h100_2 + + - label: "Diffusion · Bagel · H100 · 2-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_bagel_expansion.py + -m "slow and diffusion and H100 and cards_2" + --run-level "full_model" + mirror_hardwares: h100_2 + + - label: "Diffusion · Boogu · H100 · 2-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_boogu_image_expansion.py + tests/e2e/online_serving/test_boogu_image_edit_expansion.py + -m "slow and diffusion and H100 and cards_2" + --run-level "full_model" + mirror_hardwares: h100_2 + + - label: "Diffusion · Flux · H100 · 2-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_flux_2_dev_expansion.py + tests/e2e/offline_inference/test_flux1_kontext_expansion.py + -m "slow and diffusion and H100 and cards_2" + --run-level "full_model" + mirror_hardwares: h100_2 + + - label: "Diffusion · GLM-Image · H100 · 2-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_glm_image_expansion.py + tests/e2e/offline_inference/test_glm_image_autoround_w4a16_expansion.py + -m "slow and diffusion and H100 and cards_2" + --run-level "full_model" + mirror_hardwares: h100_2 + + - label: "Diffusion · LTX · H100 · 2-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_ltx.py + -m "slow and diffusion and H100 and cards_2" + --run-level "full_model" + mirror_hardwares: h100_2 + + - label: "Diffusion · Krea2 · H100 · 2-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/offline_inference/test_krea2_expansion.py + -m "slow and diffusion and H100 and cards_2" + --run-level "full_model" + mirror_hardwares: h100_2 + + - label: "Diffusion · DreamZero · H100 · 2-GPU" + timeout_in_minutes: 90 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_dreamzero_expansion.py + tests/e2e/accuracy/test_dreamzero.py + -m "slow and diffusion and H100 and cards_2" --run-level "full_model" mirror_hardwares: h100_2 @@ -246,4 +495,33 @@ steps: pytest -sv tests/e2e/ -m "slow and diffusion and H100 and cards_4" --run-level "full_model" + --ignore=tests/e2e/online_serving/test_magi2.py + mirror_hardwares: h100_4 + + # Dedicated: HiDream-O1 accuracy needs a long TP2 run; the shared H100 + # 2-GPU sweep is only 90 minutes. + - label: "Diffusion · HiDream-O1-Image Accuracy · H100 · 2-GPU" + timeout_in_minutes: 180 + commands: + - pytest -s -v tests/e2e/accuracy/test_hidream_o1_image.py -m "slow and diffusion and cuda and H100 and cards_2" --run-level "full_model" + mirror_hardwares: h100_2 + + # Dedicated: Boogu CFG-parallel size 3 needs 3 GPUs; weekly has no H100 3-GPU sweep. + - label: "Diffusion · Boogu Edit CFG · H100 · 3-GPU" + timeout_in_minutes: 120 + commands: + - >- + pytest -sv + tests/e2e/online_serving/test_boogu_image_edit_expansion.py + -k "test_double_guidance_cfg_parallel and cfg_parallel_3_full" + -m "slow and diffusion and cuda and H100 and cards_3" + --run-level "full_model" + mirror_hardwares: h100_3 + + # Dedicated: MAGI-2 Preview serving smoke needs ~30 min server init; the + # shared H100 4-GPU sweep is only 90 minutes. + - label: "Diffusion · MAGI-2 Preview Serving Smoke · H100 · 4-GPU" + timeout_in_minutes: 180 + commands: + - pytest -s -v tests/e2e/online_serving/test_magi2.py -m "slow and diffusion and cuda and H100 and cards_4" --run-level "full_model" mirror_hardwares: h100_4 diff --git a/.buildkite/npu/bootstrap-upload-steps.yml b/.buildkite/npu/bootstrap-upload-steps.yml index 398fbc6dc..d88fcc70b 100644 --- a/.buildkite/npu/bootstrap-upload-steps.yml +++ b/.buildkite/npu/bootstrap-upload-steps.yml @@ -93,7 +93,7 @@ steps: command: | python3 .buildkite/common/scripts/upload_pipeline.py --upload .buildkite/npu/test-npu-ready.yml - # L4 Test — main+NIGHTLY=1 (scheduled), or PR with specific label (e.g. add label then Rebuild) + # L4 Test — main+NIGHTLY=1 (scheduled), or PR nightly-test label - label: "Upload Nightly Pipeline" depends_on: - image-build-a2 @@ -102,6 +102,11 @@ steps: - image-build-310p key: upload-nightly-pipeline commands: - - python3 .buildkite/common/scripts/upload_pipeline.py --upload .buildkite/npu/test-npu-nightly.yml + - | + EXTRA="" + if [ "${NIGHTLY:-}" = "1" ] && [ "${BUILDKITE_BRANCH}" = "main" ]; then + EXTRA="--all" + fi + python3 .buildkite/common/scripts/upload_pipeline.py --upload $$EXTRA .buildkite/npu/test-npu-nightly.yml agents: queue: "cpu_queue_premerge" diff --git a/.buildkite/npu/pipeline-npu-a3.yml b/.buildkite/npu/pipeline-npu-a3.yml index a57f5f8e5..3544b384d 100644 --- a/.buildkite/npu/pipeline-npu-a3.yml +++ b/.buildkite/npu/pipeline-npu-a3.yml @@ -96,13 +96,7 @@ # key: upload-nightly-pipeline # if: >- # (build.branch == "main" && build.env("NIGHTLY") == "1") || - # (build.branch != "main" && ( - # build.pull_request.labels includes "nightly-test" || - # build.pull_request.labels includes "omni-test" || - # build.pull_request.labels includes "tts-test" || - # build.pull_request.labels includes "diffusion-x2iat-test" || - # build.pull_request.labels includes "diffusion-x2v-test" - # )) + # (build.branch != "main" && build.pull_request.labels includes "nightly-test") # commands: # - buildkite-agent pipeline upload .buildkite/npu/test-npu-nightly.yml # agents: diff --git a/.buildkite/npu/test-npu-nightly.yml b/.buildkite/npu/test-npu-nightly.yml index e049783ce..f64fa711f 100644 --- a/.buildkite/npu/test-npu-nightly.yml +++ b/.buildkite/npu/test-npu-nightly.yml @@ -4,10 +4,10 @@ steps: depends_on: upload-nightly-pipeline if: >- build.env("NIGHTLY") == "1" || - build.pull_request.labels includes "nightly-test" || - build.pull_request.labels includes "omni-test" + build.pull_request.labels includes "nightly-test" steps: - label: ":full_moon: Omni · Perf Test · No Async Chunk" + source_file_dependencies: omni_qwen3_omni_perf key: nightly-omni-performance-no-async-chunk timeout_in_minutes: 180 mirror_hardwares: a3_npu_4 @@ -24,6 +24,7 @@ steps: buildkite-agent artifact upload "tests/dfx/perf/results/*.json" exit $$EXIT - label: ":full_moon: Omni · Perf Test · Async Chunk" + source_file_dependencies: omni_qwen3_omni_perf key: nightly-omni-performance-async-chunk timeout_in_minutes: 180 mirror_hardwares: a3_npu_4 @@ -40,6 +41,7 @@ steps: buildkite-agent artifact upload "tests/dfx/perf/results/*.json" exit $$EXIT - label: ":full_moon: Omni · MiniCPM-o 4.5 Test" + source_file_dependencies: omni_minicpmo_4_5_function mirror_hardwares: a3_npu_2 env: VLLM_WORKER_MULTIPROC_METHOD: spawn @@ -48,6 +50,7 @@ steps: commands: - pytest -s -v tests/e2e/offline_inference/test_minicpmo_4_5.py tests/e2e/online_serving/test_minicpmo_4_5.py tests/e2e/online_serving/test_minicpmo_4_5_expansion.py -m 'full_model' --run-level 'full_model' - label: ":full_moon: Omni · MiniCPM-o 4.5 · Duplex Test" + source_file_dependencies: omni_minicpmo_4_5_duplex_function timeout_in_minutes: 180 mirror_hardwares: a3_npu_2 env: @@ -62,6 +65,7 @@ steps: -m "npu and A3 and omni" --run-level full_model - label: ":full_moon: Omni · MiniCPM-o 4.5 · Accuracy Test" + source_file_dependencies: omni_minicpmo_4_5_accuracy timeout_in_minutes: 180 mirror_hardwares: a3_npu_2 env: @@ -82,6 +86,7 @@ steps: buildkite-agent artifact upload "tests/e2e/accuracy/minicpmo_4_5/results/*.json" exit $$EXIT - label: ":full_moon: Omni · MiniCPM-o 4.5 · Perf Test" + source_file_dependencies: omni_minicpmo_4_5_perf key: nightly-omni-performance-minicpmo-4-5-npu timeout_in_minutes: 180 mirror_hardwares: a3_npu_2 @@ -98,6 +103,7 @@ steps: buildkite-agent artifact upload "tests/dfx/perf/results/*.json" exit $$EXIT - label: ":full_moon: Omni · MiniCPM-o 4.5 · Perf Test (A2)" + source_file_dependencies: omni_minicpmo_4_5_perf key: nightly-omni-performance-minicpmo-4-5-npu-a2 timeout_in_minutes: 180 mirror_hardwares: a2b3_npu_1 @@ -115,6 +121,7 @@ steps: buildkite-agent artifact upload "tests/dfx/perf/results/*.json" exit $$EXIT - label: ":full_moon: Omni · MiniCPM-o 4.5 · Duplex Seed-TTS Perf Test" + source_file_dependencies: omni_minicpmo_4_5_duplex_perf key: nightly-omni-performance-minicpmo-4-5-duplex-seed-tts-npu timeout_in_minutes: 180 mirror_hardwares: a3_npu_2 @@ -133,9 +140,10 @@ steps: - group: ":card_index_dividers: TTS Model Test" key: nightly-tts-test-group depends_on: upload-nightly-pipeline - if: build.env("NIGHTLY") == "1" || build.pull_request.labels includes "nightly-test" || build.pull_request.labels includes "tts-test" + if: build.env("NIGHTLY") == "1" || build.pull_request.labels includes "nightly-test" steps: - label: ":full_moon: TTS · Perf Test" + source_file_dependencies: tts_qwen3_tts_perf timeout_in_minutes: 180 mirror_hardwares: a3_npu_2 env: @@ -151,15 +159,15 @@ steps: EXIT=$$? buildkite-agent artifact upload "tests/dfx/perf/results/*.json" exit $$EXIT - - group: ":card_index_dividers: Diffusion I2I Model Test" - key: nightly-HunyuanImage3-x2i-test-group + - group: ":card_index_dividers: Diffusion X2I(&A&T) Model Test" + key: nightly-diffusion-x2iat-group depends_on: upload-nightly-pipeline if: >- build.env("NIGHTLY") == "1" || - build.pull_request.labels includes "nightly-test" || - build.pull_request.labels includes "diffusion-x2iat-test" + build.pull_request.labels includes "nightly-test" steps: - label: ":full_moon: HunyuanImage3-DIT · Accuracy Test" + source_file_dependencies: diffusion_hunyuan_image3_accuracy timeout_in_minutes: 180 mirror_hardwares: a3_npu_4 env: @@ -169,15 +177,8 @@ steps: DIFFUSION_ATTENTION_BACKEND: TORCH_SDPA commands: - pytest -s -v tests/e2e/accuracy/test_hunyuan_image3_pixel_accuracy.py -m "full_model and A3" --run-level full_model - - group: ":card_index_dividers: Diffusion Benchmark Perf Test" - key: nightly-diffusion-benchmark-group - depends_on: upload-nightly-pipeline - if: >- - build.env("NIGHTLY") == "1" || - build.pull_request.labels includes "nightly-test" || - build.pull_request.labels includes "diffusion-x2iat-test" - steps: - label: ":full_moon: Diffusion Perf · HunyuanImage3 TP=2 CFGP=2" + source_file_dependencies: diffusion_hunyuan_image3_perf timeout_in_minutes: 180 mirror_hardwares: a3_npu_4 env: @@ -194,6 +195,7 @@ steps: buildkite-agent artifact upload "tests/dfx/perf/results/logs/*.log" exit $$EXIT - label: ":full_moon: Diffusion Perf · HunyuanImage3 TP=2 SP=2" + source_file_dependencies: diffusion_hunyuan_image3_perf timeout_in_minutes: 180 mirror_hardwares: a3_npu_4 env: @@ -210,6 +212,7 @@ steps: buildkite-agent artifact upload "tests/dfx/perf/results/logs/*.log" exit $$EXIT - label: ":full_moon: Diffusion Perf · HunyuanImage3 TP=4" + source_file_dependencies: diffusion_hunyuan_image3_perf timeout_in_minutes: 180 mirror_hardwares: a3_npu_4 env: @@ -230,10 +233,10 @@ steps: depends_on: upload-nightly-pipeline if: >- build.env("NIGHTLY") == "1" || - build.pull_request.labels includes "nightly-test" || - build.pull_request.labels includes "diffusion-x2v-test" + build.pull_request.labels includes "nightly-test" steps: - - label: ":full_moon: Diffusion X2V · Function Test" + - label: ":full_moon: Diffusion X2V · Wan 2.2 Function Test" + source_file_dependencies: diffusion_wan22_function mirror_hardwares: a2b3_npu_4 env: VLLM_WORKER_MULTIPROC_METHOD: spawn @@ -241,7 +244,8 @@ steps: HF_TOKEN: "${HF_TOKEN}" commands: - pytest -s -v tests/e2e/online_serving/test_wan22_expansion.py -k npu_i2v --run-level "full_model" - - label: ":full_moon: Diffusion X2V · Perf Test" + - label: ":full_moon: Diffusion X2V · Wan 2.2 Perf Test" + source_file_dependencies: diffusion_wan22_perf key: nightly-diffusion-x2v-performance timeout_in_minutes: 180 mirror_hardwares: a3_npu_4 diff --git a/.claude/skills/vllm-omni-test/SKILL.md b/.claude/skills/vllm-omni-test/SKILL.md index 2d4226788..f0fb009d5 100644 --- a/.claude/skills/vllm-omni-test/SKILL.md +++ b/.claude/skills/vllm-omni-test/SKILL.md @@ -468,10 +468,10 @@ When the user asks for **invalid parameter validation**, **invalid request bodie | **Invalid parameters Test · H100** | `pytest -s -v tests/dfx/reliability/invalid_param_test/ -m "slow and H100"` | Diffusion / omni / video invalid-param tests with `H100` hardware mark | | **Invalid parameters Test · L4** | `pytest -s -v tests/dfx/reliability/invalid_param_test/ -m "slow and L4"` | TTS / lighter models marked `L4` | -- **Trigger:** `build.env("WEEKLY") == "1"` or PR label `weekly-test`. +- **Trigger:** `build.env("WEEKLY") == "1"` (all weekly jobs) or PR label `weekly-test` (Reliability / Perf, then filtered by `source_file_dependencies`). - **Default:** extending an existing `invalid_param_test` script needs **no YAML edit** — the weekly steps already sweep the whole directory. - **Edit YAML only** when adding a **new hardware queue**, a **new top-level script** that must run in isolation, or a **model-specific weekly shard** (mirror neighboring reliability steps). -- Weekly steps **do not** use `source_file_dependencies`. +- Weekly Reliability / Perf jobs declare `source_file_dependencies`. Filtering applies only on the `weekly-test` label; `WEEKLY=1` on `main` keeps every job in those groups. CPU coverage (`WEEKLY=1` only) and the E2E Tests group (`NON_CRITICAL=1` only) do **not** use this field. **Example — append to `test_invalid_image_generation.py`:** @@ -644,7 +644,7 @@ If the test is not already collected by an existing pipeline command (for exampl | **L2** | `test-ready.yml` with `core_model` + `source_file_dependencies` | merge / nightly pipelines | | **Invalid param** | `test-weekly.yml` — **Invalid parameters Test** group (`-m "slow and H100"` / `-m "slow and L4"`). Usually **no YAML edit** when appending cases to existing `invalid_param_test` scripts | `test-ready.yml`, `test-merge.yml`, `test-nightly.yml` | -`test-nightly.yml` shards use **explicit pytest file paths** in `commands` (and PR labels like `diffusion-x2iat-test`); they generally **do not** use `source_file_dependencies`. Only suggest merge/ready YAML when the requested level is L3/L2 (or the user explicitly asks for multi-level CI). +`test-nightly.yml` shards use **explicit pytest file paths** in `commands` plus `source_file_dependencies`; PR trigger is `nightly-test` (path filter), or `NIGHTLY=1` on `main` (all jobs). Only suggest merge/ready YAML when the requested level is L3/L2 (or the user explicitly asks for multi-level CI). **`test-nightly.yml` top-level groups** (each uses `full_model` + type marker in pytest `-m`): @@ -653,7 +653,7 @@ If the test is not already collected by an existing pipeline command (for exampl | **Omni Model Test** | `omni` | Function / doc / accuracy / **perf** for Qwen-Omni family | | **TTS Model Test** | `tts` | `-m "full_model and L4 and tts"` (and H100 variants when enabled); **Perf Test** uses `run_benchmark.py` + `test_tts.json` | | **Diffusion X2I(&A&T) Model Test** | `diffusion` | Image/audio/text diffusion; explicit file shards for **Function**; **Perf Test · <Model>** uses `run_diffusion_benchmark.py` + JSON config | -| **Diffusion X2V Model Test** | `diffusion` | Video-only (Wan, HunyuanVideo, …); PR label `diffusion-x2v-test`; separate **Perf** steps when in-tree | +| **Diffusion X2V Model Test** | `diffusion` | Video-only (Wan, HunyuanVideo, …); separate **Perf** steps when in-tree | Guidelines when editing YAML: diff --git a/.claude/skills/vllm-omni-test/references/test-routing.md b/.claude/skills/vllm-omni-test/references/test-routing.md index 5b90957d6..a61324e6d 100644 --- a/.claude/skills/vllm-omni-test/references/test-routing.md +++ b/.claude/skills/vllm-omni-test/references/test-routing.md @@ -37,7 +37,7 @@ Every model-centric e2e test must declare **exactly one** type marker: | **Diffusion X2I(&A&T) Model Test** | x2**i** / x2**a** / x2**t** — image, audio, text (non-video) | Qwen-Image*, BAGEL, FLUX, SD3, Z-Image, LongCat, DreamZero | | **Diffusion X2V Model Test** | x2**v** — video only | Wan2.2, HunyuanVideo 1.5, Wan VACE | -PR labels for selective nightly runs: `diffusion-x2iat-test`, `diffusion-x2v-test` (plus `nightly-test` / `NIGHTLY=1`). +PR label for L4 on a branch: `nightly-test` (jobs then filtered by `source_file_dependencies`). Scheduled `main` uses `NIGHTLY=1` and runs every nightly job. L5 Reliability / Perf use `weekly-test` with the same path filter; CPU coverage and the weekly E2E group are env-only (`WEEKLY=1` / `NON_CRITICAL=1`) and are not source-filtered. ## Level and Marker Mapping @@ -238,7 +238,7 @@ pytest -s -v dfx/reliability/invalid_param_test/ -m "slow and L4" pytest -s -v dfx/reliability/invalid_param_test/test_invalid_image_generation.py::test_images_generations_invalid_requests -m "slow and H100" ``` -**Trigger:** `WEEKLY=1` or PR label `weekly-test`. Appending cases to existing scripts usually needs **no YAML edit** (directory sweep). No `source_file_dependencies` on weekly steps. +**Trigger:** `WEEKLY=1` (all jobs) or PR label `weekly-test` (Reliability / Perf, filtered by `source_file_dependencies`). Appending cases to existing scripts usually needs **no YAML edit** (directory sweep). ### Platform-targeted examples diff --git a/docs/contributing/ci/ci_settings.md b/docs/contributing/ci/ci_settings.md index 885ebd528..fb3af0ed3 100644 --- a/docs/contributing/ci/ci_settings.md +++ b/docs/contributing/ci/ci_settings.md @@ -15,7 +15,8 @@ Canonical layout (prefer these paths for new changes): │ │ ├── skip_ci.py # skip-ci decision (docs / skip-mark / CI YAML paths) │ │ ├── upload_pipeline.py # Bootstrap + test-pipeline uploader (CUDA/NPU) │ │ └── resolve_skip_ci.sh # Shell helpers for AMD/Intel bootstrap -│ └── ci_mirror_hardwares.yml # CUDA uploader presets (referenced by name only) +│ ├── ci_mirror_hardwares.yml # CUDA/NPU hardware presets (referenced by name only) +│ └── ci_source_file_dependencies.yml # L2–L5 path-prefix presets (referenced by name only) ├── cuda/ # Primary NVIDIA CUDA CI │ ├── pipeline.yml # Bootstrap entry (hook upload) │ ├── bootstrap-upload-steps.yml # Bootstrap child steps (upload_pipeline --upload) @@ -108,19 +109,21 @@ Canonical layout (prefer these paths for new changes): Inferred form: unset/`empty` `MIRROR_HW` matches `H100` or `L4` in `-m` (both present → H100); no match skips the step. `MIRROR_HW=b200` must appear in `-m` or the step is skipped. The uploader does **not** rewrite pytest `-m`; B200 collection comes from the YAML expression and from tests that declare `B200` in `hardware_test` / `hardware_marks` (for example `res={"cuda": ["H100", "B200"]}`). `MIRROR_HW` must be empty or `b200` (case-insensitive); unknown values (for example `b20o`) **fail the upload**. A CUDA preset string such as `mirror_hardwares: h100_4` is skipped when `MIRROR_HW=b200`. Unset `MIRROR_HW` keeps string presets. NPU presets ignore `MIRROR_HW`. A `mirror_hardwares` name that is not a key in `ci_mirror_hardwares.yml` **fails the upload**. + **Path filter in YAML:** `source_file_dependencies: ` (string, or a list of preset names)—preset names in [`common/ci_source_file_dependencies.yml`](https://github.com/vllm-project/vllm-omni/blob/main/.buildkite/common/ci_source_file_dependencies.yml). Required on **E2E Test** leaf jobs in L2/L3, and on L4/L5 leaf jobs that should be diff-gated on PR labels; see [Step filtering](#step-filtering). + **Conventions** - **`depends_on`:** leaf jobs depend on `upload-ready-pipeline`, `upload-merge-pipeline`, etc. - **`group` / `label`:** `:card_index_dividers:` groups; labels like `Diffusion · Qwen Image Test`. - **`commands`:** `timeout … pytest …` with markers and `--run-level` for the pipeline level. - - **`source_file_dependencies`:** required on **E2E Test** leaf jobs in L2/L3; see [Step filtering](#step-filtering). + - **`source_file_dependencies`:** required on **E2E Test** leaf jobs in L2/L3, and on L4/L5 leaf jobs that should be diff-gated on PR labels; name a job key from `ci_source_file_dependencies.yml` (see [Step filtering](#step-filtering)). The key must list every script the step runs; `commands` is not scanned. **Adding a job** 1. Pick the level file (`test-ready.yml` / `test-merge.yml` / `test-nightly.yml` / `test-weekly.yml`). 2. Add a step under the right **group** (usually **E2E Test** for model pytest). - 3. Set `label`, `commands`, `mirror_hardwares`, `depends_on: upload-ready-pipeline` (or `upload-merge-pipeline` / `upload-nightly-pipeline` / `upload-weekly-pipeline`). - 4. For L2/L3 E2E, add `source_file_dependencies` (pytest + model + deploy YAML prefixes). + 3. Set `label`, `commands`, `mirror_hardwares`, `depends_on: upload--pipeline`. + 4. For L2–L5 jobs that should be diff-gated, add a job key in `common/ci_source_file_dependencies.yml` and set `source_file_dependencies: ` on the step. YAML anchors hold model business-code paths only. The job key (`{model}_function` / `_perf` / `_accuracy` / `_reliability` / `_doc` / `_cov`) aliases that anchor and lists the pytest / example / benchmark scripts the step actually runs. The uploader does **not** parse `commands` for path filters—omitting a script from the key means editing that script will not select the job. 5. Dry-run: ```bash @@ -144,6 +147,8 @@ Canonical layout (prefer these paths for new changes): - A5: `a5_npu_2`, `a5_npu_4`, `a5_npu_8`, `a5_npu_16` - 310P: `310p_npu_1`, `310p_npu_2`, `310p_npu_4` + **Path filter in YAML:** same `source_file_dependencies` presets as CUDA, on **L4** leaf jobs in `test-npu-nightly.yml`. Filtering applies on the PR `nightly-test` label; `main` + `NIGHTLY=1` keeps every job. If no job-key prefix matches, a change to the pipeline YAML being uploaded, or to any path under `source_filter_fallback`, keeps every job in that upload. See [Step filtering](#step-filtering). + **Conventions** - **`depends_on: upload-ready-pipeline`** (or `upload-nightly-pipeline`) ties jobs to bootstrap upload keys. @@ -153,7 +158,7 @@ Canonical layout (prefer these paths for new changes): 1. Edit `test-npu-ready.yml` (L2) or `test-npu-nightly.yml` (L4). 2. Add a step with `mirror_hardwares` (add a new preset in `ci_mirror_hardwares.yml` first if needed). - 3. Set `commands` to your pytest file and markers. + 3. Set `commands` to your pytest file and markers. For L4, set `source_file_dependencies` to a job key from `ci_source_file_dependencies.yml` that aliases the model anchor and lists that pytest file. 4. Dry-run: ```bash @@ -213,7 +218,7 @@ PR diffs drive **two independent skip layers**. Both read changed files from git | Layer | Script | When | What is skipped | Where you configure | | ----- | ------ | ---- | --------------- | ------------------- | | **Bootstrap** | [`skip_ci.py`](https://github.com/vllm-project/vllm-omni/blob/main/.buildkite/common/scripts/skip_ci.py) + [`upload_pipeline.py`](https://github.com/vllm-project/vllm-omni/blob/main/.buildkite/common/scripts/upload_pipeline.py) | Before child test pipelines upload (`cuda/pipeline.yml`, `npu/pipeline-npu.yml`, AMD/Intel bootstraps) | Entire default CI, or whole L2/L3 upload for a platform | Whitelists in `skip_ci.py`; bootstrap `if` injected by step `key` in `upload_pipeline.py` | -| **Step filter** | [`upload_pipeline.py`](https://github.com/vllm-project/vllm-omni/blob/main/.buildkite/common/scripts/upload_pipeline.py) | While uploading CUDA L2/L3 YAML | Individual Buildkite steps inside `test-ready.yml` / `test-merge.yml` | `source_file_dependencies` on each step or group | +| **Step filter** | [`upload_pipeline.py`](https://github.com/vllm-project/vllm-omni/blob/main/.buildkite/common/scripts/upload_pipeline.py) | While uploading CUDA L2–L5 YAML | Individual Buildkite steps inside `test-ready.yml` / `test-merge.yml` / `test-nightly.yml` / `test-weekly.yml` | `source_file_dependencies` key on each step (presets in `ci_source_file_dependencies.yml`) | **Changed files** (both layers): @@ -306,40 +311,38 @@ Unit coverage: `tests/buildkite/test_skip_ci.py`. #### Step filtering {#step-filtering} -CUDA **L2** (`.buildkite/cuda/test-ready.yml`) and **L3** (`.buildkite/cuda/test-merge.yml`) only. Bootstrap upload entry: `upload_pipeline.py --upload .buildkite/cuda/bootstrap-upload-steps.yml`. +CUDA **L2** (`.buildkite/cuda/test-ready.yml`), **L3** (`.buildkite/cuda/test-merge.yml`), **L4** (`.buildkite/cuda/test-nightly.yml`), **L5** (`.buildkite/cuda/test-weekly.yml`), and NPU **L4** (`.buildkite/npu/test-npu-nightly.yml`). Bootstrap upload entry: `upload_pipeline.py --upload .buildkite/cuda/bootstrap-upload-steps.yml` (or `npu/bootstrap-upload-steps.yml`). + +**When filtering applies:** only **PR label** uploads (`ready`, `merge-test`, `nightly-test`, `weekly-test`). On **`main` + env** (`NIGHTLY=1`, post-merge L3, `WEEKLY=1` / `NON_CRITICAL=1`, `WEEKLY=1 --e2e`) the uploader keeps every job and still strips the key. If **no** job-key prefix matches the diff, a change to the pipeline YAML being uploaded, or any path under the `source_filter_fallback` key in `ci_source_file_dependencies.yml`, keeps every job in that upload. `source_filter_fallback` is not a job key — do not attach it to a step. When any job-key prefix already matches, normal filtering wins (the fallback does not expand the selection). Without this fallback, command / env / hardware-only edits would match nothing (NPU drops every step; CUDA nightly keeps only the email aggregator). A different pipeline YAML does not trigger the fallback for this upload. **Uploader-only keys** — removed before Buildkite sees the YAML; never used at runtime on agents: | Key | Purpose | | --- | ------- | -| `source_file_dependencies` | List of path **prefixes**. If any changed file equals a prefix or starts with `prefix/`, keep the step (or group); otherwise omit it. | +| `source_file_dependencies` | Named preset (or list of presets) from [`ci_source_file_dependencies.yml`](https://github.com/vllm-project/vllm-omni/blob/main/.buildkite/common/ci_source_file_dependencies.yml). The uploader expands only that key; it does **not** scan `commands`. If any changed file equals a listed prefix or starts with `prefix/`, keep the step (or group); otherwise omit it. Inline path-prefix lists are still accepted. | | `mirror_hardwares` | Expand to `agents` + `plugins` (+ optional `image`) from `ci_mirror_hardwares.yml`. | ### Policy -- **Always uploaded** (no key): groups outside **E2E Test**—Simple Test, Diffusion unit tests, Engine/Model Executor, Distributed, Custom Pipeline, Entrypoints (L2), LoRA / Entrypoints (L3). -- **Diff-gated**: every **E2E Test** leaf job. List the smallest prefix set per step—pytest file(s), model code under `vllm_omni/model_executor/models/` or `vllm_omni/diffusion/models/`, plus `stage_input_processors/` and `vllm_omni/deploy/*.yaml` when applicable. A **group** may define the key instead; the whole group drops if no prefix matches. +- **Always uploaded** (no key): L2/L3 groups outside **E2E Test**—Simple Test, Diffusion unit tests, Engine/Model Executor, Distributed, Custom Pipeline, Entrypoints (L2), LoRA / Entrypoints (L3). +- **Diff-gated**: every **E2E Test** leaf job in L2/L3, L4 nightly leaf jobs (CUDA and NPU), and L5 weekly jobs whose `if` includes the `weekly-test` label (Reliability / Perf). Jobs gated only by `WEEKLY=1` or `NON_CRITICAL=1` have no `source_file_dependencies`. Registry layout: YAML anchors are model business code only (`vllm_omni/model_executor/models/`, `vllm_omni/diffusion/models/`, plus `stage_input_processors/` and `vllm_omni/deploy/*.yaml` when applicable). Job keys alias the anchor and **also** list the scripts that job runs (pytest files, `run_cov_split.sh --offline` / `--online` targets, example README runners). Feature keys stay cross-cutting. A **group** may define the key instead; the whole group drops if no prefix matches. ### YAML examples ```yaml - label: "Diffusion · Qwen Image Test" - source_file_dependencies: - - tests/e2e/online_serving/test_qwen_image.py - - vllm_omni/diffusion/models/qwen_image/ + source_file_dependencies: diffusion_qwen_image_function + # diffusion_qwen_image_function: *qwen_image + tests/e2e/online_serving/test_qwen_image.py commands: - pytest -s -v tests/e2e/online_serving/test_qwen_image.py -m 'core_model' ... mirror_hardwares: h100_1 - label: "TTS · Qwen3-TTS CustomVoice Test" - source_file_dependencies: - - tests/e2e/online_serving/test_qwen3_tts_customvoice.py - - vllm_omni/model_executor/models/qwen3_tts/ - - vllm_omni/model_executor/stage_input_processors/qwen3_tts.py - - vllm_omni/deploy/qwen3_tts.yaml + source_file_dependencies: tts_qwen3_tts_function + # tts_qwen3_tts_function: *qwen3_tts + tests/e2e/online_serving/test_qwen3_tts_customvoice.py commands: - pytest -s -v tests/e2e/online_serving/test_qwen3_tts_customvoice.py ... - mirror_hardwares: l4_4 + mirror_hardwares: l4_1 ``` ### Local dry-run @@ -443,15 +446,16 @@ plugin, which provides the agent. `l4_*` jobs run on the EKS `l4-k8s` queue still needs `mount-buildkite-agent: true`. List both `run_cov_split.sh` and `pyproject.toml` in every opted-in job's -`source_file_dependencies` — both change what the job measures, so without them a +`source_file_dependencies` preset — both change what the job measures, so without them a change there is filtered out of normal PR builds and only surfaces in a later nightly. `tests/buildkite/test_upload_pipeline.py` covers the filter behavior with a synthetic job (it does not pin real merge labels). -Editing only the surrounding CI YAML still does not schedule them, so a PR that -touches just the wiring needs a full E2E run (or the commands run on a GPU host) -to produce artifacts. When checking a new model's -artifacts, compare `lines-covered` between the online and offline XML rather than -just confirming both files exist. +If no job-key prefix matches, editing the pipeline YAML being uploaded, or any +path under the `source_filter_fallback` registry key, keeps every job in that +upload (including coverage jobs) so the wiring can be validated before merge. +When a job-key prefix already matches, bypass does not expand the selection. A +change to a different pipeline YAML still does not schedule them. When checking a new model's artifacts, compare `lines-covered` +between the online and offline XML rather than just confirming both files exist. ### Validation checklist diff --git a/tests/buildkite/test_upload_pipeline.py b/tests/buildkite/test_upload_pipeline.py index 7492a4b82..06e2b975c 100644 --- a/tests/buildkite/test_upload_pipeline.py +++ b/tests/buildkite/test_upload_pipeline.py @@ -13,11 +13,15 @@ sys.path.insert(0, str(Path(__file__).resolve().parents[2] / ".buildkite" / "com from skip_ci import resolve_ci_decision # noqa: E402 from upload_pipeline import ( # noqa: E402 CUDA_HF_TOKEN_EXPORT, + NIGHTLY_LABEL_IF, + _changed_files_for_source_filter, _expand_mirror_hardwares, _get_mirror_hw_selector, _load_bootstrap_steps, + _load_source_file_dependencies, _render_bootstrap_pipeline, _render_test_pipeline, + _resolve_source_file_dependencies, ) pytestmark = [pytest.mark.core_model, pytest.mark.cpu] @@ -101,6 +105,26 @@ def test_npu_docs_only_does_not_upload_ready_on_nightly() -> None: assert 'build.env("NIGHTLY") == "1"' in by_key["upload-nightly-pipeline"]["if"] +def test_nightly_label_if_is_only_nightly_test() -> None: + assert 'labels includes "nightly-test"' in NIGHTLY_LABEL_IF + forbidden = ( + 'includes "omni-test"', + 'includes "tts-test"', + 'includes "diffusion-x2iat-test"', + 'includes "diffusion-x2v-test"', + ) + for needle in forbidden: + assert needle not in NIGHTLY_LABEL_IF + for path in ( + Path(".buildkite/cuda/test-nightly.yml"), + Path(".buildkite/npu/test-npu-nightly.yml"), + Path(".buildkite/common/scripts/upload_pipeline.py"), + ): + text = path.read_text(encoding="utf-8") + for needle in forbidden: + assert needle not in text, f"{path} still references {needle}" + + def test_yaml_gated_l45_only_does_not_unconditionally_build_image() -> None: rendered = _render([".buildkite/cuda/test-nightly.yml"]) assert "if: true" not in rendered @@ -366,8 +390,17 @@ def test_mirror_hw_typo_fails_closed(monkeypatch: pytest.MonkeyPatch) -> None: ) -def _surviving_labels(doc: dict, changed_files: list[str]) -> set[str]: - rendered = _render_test_pipeline(doc, changed_files=changed_files) +def _surviving_labels( + doc: dict, + changed_files: list[str], + *, + pipeline_path: Path | None = None, +) -> set[str]: + rendered = _render_test_pipeline( + doc, + changed_files=changed_files, + pipeline_path=pipeline_path, + ) labels: set[str] = set() def walk(steps: list | None) -> None: @@ -382,6 +415,17 @@ def _surviving_labels(doc: dict, changed_files: list[str]) -> set[str]: return labels +def _iter_steps(doc: dict): + def walk(steps: list | None): + for step in steps or []: + if not isinstance(step, dict): + continue + yield step + yield from walk(step.get("steps")) + + yield from walk(doc.get("steps")) + + # Synthetic coverage-style job: shared inputs that change what the split measures. _COVERAGE_SHARED_INPUTS_DOC = { "steps": [ @@ -426,3 +470,289 @@ def test_coverage_shared_inputs_ignored_for_unrelated_change() -> None: ) assert "Coverage Pilot" not in labels assert "Unrelated Model Test" not in labels + + +def _pipeline_dep_keys(path: Path) -> set[str]: + doc = yaml.safe_load(path.read_text(encoding="utf-8")) + keys: set[str] = set() + + def walk(steps: list | None) -> None: + for step in steps or []: + if not isinstance(step, dict): + continue + deps = step.get("source_file_dependencies") + if isinstance(deps, str) and "/" not in deps: + keys.add(deps) + elif isinstance(deps, list) and deps and all("/" not in item for item in deps): + keys.update(deps) + walk(step.get("steps")) + + walk((doc or {}).get("steps")) + return keys + + +def test_pipeline_source_file_dependency_keys_are_registered() -> None: + _load_source_file_dependencies.cache_clear() + registry = _load_source_file_dependencies() + used = ( + _pipeline_dep_keys(Path(".buildkite/cuda/test-ready.yml")) + | _pipeline_dep_keys(Path(".buildkite/cuda/test-merge.yml")) + | _pipeline_dep_keys(Path(".buildkite/cuda/test-nightly.yml")) + | _pipeline_dep_keys(Path(".buildkite/cuda/test-weekly.yml")) + | _pipeline_dep_keys(Path(".buildkite/npu/test-npu-nightly.yml")) + ) + missing = used - set(registry) + assert not missing, f"unregistered source_file_dependencies keys: {sorted(missing)}" + + +def test_source_file_dependencies_key_expands_from_registry() -> None: + doc = { + "steps": [ + { + "label": "Diffusion · Qwen Image Test", + "source_file_dependencies": "diffusion_qwen_image_function", + "commands": ["pytest"], + }, + ], + } + assert "Diffusion · Qwen Image Test" in _surviving_labels( + doc, + ["vllm_omni/diffusion/models/qwen_image/transformer.py"], + ) + assert "Diffusion · Qwen Image Test" not in _surviving_labels(doc, ["vllm_omni/unrelated.py"]) + + +def test_registry_lists_pytest_targets() -> None: + _load_source_file_dependencies.cache_clear() + resolved = _resolve_source_file_dependencies( + { + "label": "Diffusion · Wan22 Test", + "source_file_dependencies": "diffusion_wan22_function", + "commands": [ + "pytest -s -v tests/e2e/offline_inference/test_wan22_t2v.py " + "tests/e2e/online_serving/test_wan22_t2v.py -m 'advanced_model'", + ], + }, + ) + assert resolved is not None + assert "tests/e2e/offline_inference/test_wan22_t2v.py" in resolved + assert "tests/e2e/online_serving/test_wan22_t2v.py" in resolved + assert "vllm_omni/diffusion/models/wan2_2/" in resolved + + +def test_coverage_key_lists_offline_online_scripts() -> None: + resolved = _resolve_source_file_dependencies( + { + "label": "TTS · Qwen3-TTS Base Test", + "source_file_dependencies": "tts_qwen3_tts_cov", + "commands": [ + ".buildkite/common/scripts/run_cov_split.sh \\\n" + " --offline tests/e2e/offline_inference/test_qwen3_tts_base.py \\\n" + " --online tests/e2e/online_serving/test_qwen3_tts_base.py", + ], + }, + ) + assert resolved is not None + assert "tests/e2e/offline_inference/test_qwen3_tts_base.py" in resolved + assert "tests/e2e/online_serving/test_qwen3_tts_base.py" in resolved + assert ".buildkite/common/scripts/run_cov_split.sh" in resolved + assert "pyproject.toml" in resolved + + +def test_source_file_dependencies_list_of_keys_concatenates() -> None: + resolved = _resolve_source_file_dependencies( + { + "label": "composed", + "source_file_dependencies": ["omni_qwen3_omni_function", "tts_qwen3_tts_function"], + }, + ) + assert resolved is not None + assert "vllm_omni/model_executor/models/qwen3_omni/" in resolved + assert "vllm_omni/model_executor/models/qwen3_tts/" in resolved + assert resolved.count("vllm_omni/model_executor/models/common/snake_activation.py") == 1 + + +def test_unknown_source_file_dependencies_key() -> None: + with pytest.raises(ValueError, match="unknown source_file_dependencies"): + _render_test_pipeline( + {"steps": [{"label": "bad", "source_file_dependencies": "not_a_real_key"}]}, + changed_files=None, + ) + + +def test_source_file_dependencies_rejects_mixed_keys_and_paths() -> None: + with pytest.raises(ValueError, match="mixes registry keys and path prefixes"): + _resolve_source_file_dependencies( + { + "label": "bad", + "source_file_dependencies": ["omni_qwen3_omni_function", "tests/e2e/online_serving/test_qwen3_omni.py"], + }, + ) + + +# Synthetic pipeline: selection depends only on listed deps, not on live job names. +_SOURCE_FILTER_DOC = { + "steps": [ + { + "group": "E2E Tests", + "if": 'build.env("NON_CRITICAL") == "1"', + "steps": [ + { + "label": "Dedicated E2E", + "commands": ["pytest -sv tests/e2e/online_serving/test_magi2.py"], + }, + ], + }, + { + "label": "Omni Sweep", + "source_file_dependencies": ["tests/e2e/online_serving/test_qwen3_omni.py"], + "commands": ["pytest -sv tests/e2e/ -m omni"], + }, + { + "label": "Z-Image Function", + "source_file_dependencies": [ + "tests/e2e/online_serving/test_zimage_expansion.py", + "vllm_omni/diffusion/models/z_image/", + ], + "mirror_hardwares": "l4_4", + "commands": ["pytest -sv tests/e2e/online_serving/test_zimage_expansion.py"], + }, + { + "label": "Tiny Model", + "source_file_dependencies": ["tests/e2e/online_serving/test_tiny.py"], + "commands": ["pytest -sv tests/e2e/ -m tiny"], + }, + { + "label": "Wan Function", + "source_file_dependencies": [ + "tests/e2e/offline_inference/test_wan22_t2v.py", + "tests/e2e/online_serving/test_wan22_t2v.py", + "vllm_omni/diffusion/models/wan2_2/", + ], + "commands": ["pytest -sv tests/e2e/offline_inference/test_wan22_t2v.py"], + }, + { + "label": "Wan Perf", + "source_file_dependencies": ["vllm_omni/diffusion/models/wan2_2/"], + "commands": ["pytest -sv tests/dfx/perf/scripts/run_benchmark.py"], + }, + { + "label": "Doc Test", + "source_file_dependencies": [ + "tests/examples/offline_inference/test_text_to_image.py", + "tests/examples/online_serving/test_text_to_image.py", + "vllm_omni/diffusion/models/qwen_image/", + "vllm_omni/diffusion/models/z_image/", + ], + "commands": ["pytest -sv tests/examples/*/test_text_to_image.py"], + }, + ], +} + + +def test_source_filter_ignores_unrelated_e2e_file() -> None: + """A sweep command is not a dependency; only listed paths select a keyed job.""" + labels = _surviving_labels(_SOURCE_FILTER_DOC, ["tests/e2e/online_serving/test_magi2.py"]) + assert labels == {"Dedicated E2E"} + + +def test_source_filter_selects_job_by_listed_script_not_sibling() -> None: + labels = _surviving_labels(_SOURCE_FILTER_DOC, ["tests/e2e/online_serving/test_zimage_expansion.py"]) + assert labels == {"Dedicated E2E", "Z-Image Function"} + + +def test_source_filter_selects_every_job_sharing_a_path() -> None: + labels = _surviving_labels(_SOURCE_FILTER_DOC, ["vllm_omni/diffusion/models/wan2_2/transformer.py"]) + assert labels == {"Dedicated E2E", "Wan Function", "Wan Perf"} + + +def test_source_filter_selects_composed_doc_job_by_example_or_model() -> None: + for changed in ( + "tests/examples/online_serving/test_text_to_image.py", + "vllm_omni/diffusion/models/z_image/transformer.py", + "vllm_omni/diffusion/models/qwen_image/foo.py", + ): + labels = _surviving_labels(_SOURCE_FILTER_DOC, [changed]) + assert "Doc Test" in labels, changed + assert "Tiny Model" not in labels + assert "Omni Sweep" not in labels + assert "Doc Test" not in _surviving_labels(_SOURCE_FILTER_DOC, ["tests/e2e/online_serving/test_magi2.py"]) + + +def test_source_filter_strips_deps_and_expands_hardware(monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setattr("upload_pipeline._get_mirror_hw_selector", lambda: "") + rendered = _render_test_pipeline( + _SOURCE_FILTER_DOC, + changed_files=["tests/e2e/online_serving/test_zimage_expansion.py"], + ) + dumped = yaml.safe_dump(rendered) + assert "source_file_dependencies" not in dumped + assert "mirror_hardwares" not in dumped + z_image = next(step for step in _iter_steps(rendered) if step.get("label") == "Z-Image Function") + assert z_image["agents"]["queue"] == "l4-k8s" + + +def test_source_filter_disabled_on_main_branch(monkeypatch: pytest.MonkeyPatch) -> None: + class _Ctx: + changed_files = ["vllm_omni/unrelated.py"] + + monkeypatch.setenv("BUILDKITE_BRANCH", "main") + assert _changed_files_for_source_filter(_Ctx(), force_all=False, e2e_only=False) is None + + monkeypatch.setenv("BUILDKITE_BRANCH", "feat/source-filter") + assert _changed_files_for_source_filter(_Ctx(), force_all=False, e2e_only=False) == [ + "vllm_omni/unrelated.py", + ] + monkeypatch.setenv("BUILDKITE_BRANCH", "main") + assert _changed_files_for_source_filter(_Ctx(), force_all=True, e2e_only=False) is None + + +def test_source_filter_fallback_is_fallback_when_no_job_key_matches( + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Fallback only when no listed prefix matched; a matching prefix still wins.""" + monkeypatch.setattr("upload_pipeline._get_mirror_hw_selector", lambda: "") + monkeypatch.setenv("BUILDKITE_BRANCH", "feat/nightly-yaml") + pipeline_yaml = Path(".buildkite/npu/test-npu-nightly.yml") + shared_paths = _load_source_file_dependencies()["source_filter_fallback"] + assert ".buildkite/common/scripts/upload_pipeline.py" in shared_paths + + # Synthetic steps only — do not pin live Buildkite job labels. + doc = { + "steps": [ + {"key": "ungated", "commands": ["true"]}, + { + "key": "gated_a", + "source_file_dependencies": ["pkg/model_a/"], + "commands": ["true"], + }, + { + "key": "gated_b", + "source_file_dependencies": ["pkg/model_b/"], + "commands": ["true"], + }, + ], + } + + def surviving_keys(changed_files: list[str]) -> set[str]: + rendered = _render_test_pipeline( + doc, + changed_files=changed_files, + pipeline_path=pipeline_yaml, + ) + return {step["key"] for step in _iter_steps(rendered) if isinstance(step.get("key"), str)} + + # Only pipeline YAML / shared uploader → no listed prefix match → keep every step. + for changed in [pipeline_yaml.as_posix(), *shared_paths]: + assert surviving_keys([changed]) == {"ungated", "gated_a", "gated_b"}, changed + + # A different pipeline YAML is not a fallback for this upload. + assert surviving_keys([".buildkite/cuda/test-nightly.yml"]) == {"ungated"} + + # A matching source prefix wins over fallback files in the same diff. + assert surviving_keys( + [ + "pkg/model_a/transformer.py", + ".buildkite/common/scripts/upload_pipeline.py", + ], + ) == {"ungated", "gated_a"} diff --git a/tests/e2e/accuracy/test_hidream_o1_image.py b/tests/e2e/accuracy/test_hidream_o1_image.py index 923e53a47..440050be1 100644 --- a/tests/e2e/accuracy/test_hidream_o1_image.py +++ b/tests/e2e/accuracy/test_hidream_o1_image.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project from __future__ import annotations @@ -16,7 +16,7 @@ from vllm_omni.diffusion.data import DiffusionParallelConfig from vllm_omni.diffusion.utils.image_output import extract_images_from_outputs from vllm_omni.inputs.data import OmniDiffusionSamplingParams -pytestmark = [pytest.mark.full_model, pytest.mark.diffusion] +pytestmark = [pytest.mark.slow, pytest.mark.diffusion] MODEL_ID = "HiDream-ai/HiDream-O1-Image" PROMPT = "A cat is sitting next to a sign that says 'HiDream-O1 vLLM-Omni'" diff --git a/tests/e2e/offline_inference/test_lingbot_world_v2.py b/tests/e2e/offline_inference/test_lingbot_world_v2.py index 64578af01..88e5979dc 100644 --- a/tests/e2e/offline_inference/test_lingbot_world_v2.py +++ b/tests/e2e/offline_inference/test_lingbot_world_v2.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """End-to-end smoke test for LingBot-World v2 generation.""" from __future__ import annotations @@ -37,7 +37,7 @@ _OMNI_RUNNER_PARAM = ( ) pytestmark = [ - pytest.mark.slow, + pytest.mark.full_model, pytest.mark.diffusion, pytest.mark.skipif( not _HAS_INPUT_ASSETS, diff --git a/tests/e2e/online_serving/minimax_h3/test_minimax_h3_dlo_dp2_fl2va.py b/tests/e2e/online_serving/minimax_h3/test_minimax_h3_dlo_dp2_fl2va.py index 24cc2f7e9..7f14e403d 100644 --- a/tests/e2e/online_serving/minimax_h3/test_minimax_h3_dlo_dp2_fl2va.py +++ b/tests/e2e/online_serving/minimax_h3/test_minimax_h3_dlo_dp2_fl2va.py @@ -12,7 +12,7 @@ from tests.helpers.runtime import OmniServer, OpenAIClientHandler from ._common import assert_h3_video, dlo_params, run_dlo_wave, run_fl2va -pytestmark = [pytest.mark.core_model, pytest.mark.advanced_model, pytest.mark.diffusion, pytest.mark.slow] +pytestmark = [pytest.mark.advanced_model, pytest.mark.diffusion] H100_TWO_CARD_MARKS = hardware_marks(res={"cuda": "H100"}, num_cards=2) diff --git a/tests/e2e/online_serving/minimax_h3/test_minimax_h3_dlo_dp2_ref2va.py b/tests/e2e/online_serving/minimax_h3/test_minimax_h3_dlo_dp2_ref2va.py index f988a4431..2c61d2a3c 100644 --- a/tests/e2e/online_serving/minimax_h3/test_minimax_h3_dlo_dp2_ref2va.py +++ b/tests/e2e/online_serving/minimax_h3/test_minimax_h3_dlo_dp2_ref2va.py @@ -12,7 +12,7 @@ from tests.helpers.runtime import OmniServer, OpenAIClientHandler from ._common import assert_h3_video, dlo_params, run_dlo_wave, run_ref2va -pytestmark = [pytest.mark.core_model, pytest.mark.advanced_model, pytest.mark.diffusion, pytest.mark.slow] +pytestmark = [pytest.mark.advanced_model, pytest.mark.diffusion] H100_TWO_CARD_MARKS = hardware_marks(res={"cuda": "H100"}, num_cards=2) diff --git a/tests/e2e/online_serving/minimax_h3/test_minimax_h3_fasth3_lora.py b/tests/e2e/online_serving/minimax_h3/test_minimax_h3_fasth3_lora.py index 9fc3e8e31..1fd80454b 100644 --- a/tests/e2e/online_serving/minimax_h3/test_minimax_h3_fasth3_lora.py +++ b/tests/e2e/online_serving/minimax_h3/test_minimax_h3_fasth3_lora.py @@ -21,7 +21,7 @@ from ._common import ( post_sync, ) -pytestmark = [pytest.mark.core_model, pytest.mark.advanced_model, pytest.mark.diffusion, pytest.mark.slow] +pytestmark = [pytest.mark.advanced_model, pytest.mark.diffusion] H100_TWO_CARD_MARKS = hardware_marks(res={"cuda": "H100"}, num_cards=2) diff --git a/tests/e2e/online_serving/minimax_h3/test_minimax_h3_turbo_lora.py b/tests/e2e/online_serving/minimax_h3/test_minimax_h3_turbo_lora.py index 0190598d5..8a1a6542a 100644 --- a/tests/e2e/online_serving/minimax_h3/test_minimax_h3_turbo_lora.py +++ b/tests/e2e/online_serving/minimax_h3/test_minimax_h3_turbo_lora.py @@ -20,7 +20,7 @@ from ._common import ( turbo_params, ) -pytestmark = [pytest.mark.core_model, pytest.mark.advanced_model, pytest.mark.diffusion, pytest.mark.slow] +pytestmark = [pytest.mark.advanced_model, pytest.mark.diffusion] H100_TWO_CARD_MARKS = hardware_marks(res={"cuda": "H100"}, num_cards=2) diff --git a/tests/e2e/online_serving/test_lingbot_video.py b/tests/e2e/online_serving/test_lingbot_video.py index 8f0f45639..6ada319f5 100644 --- a/tests/e2e/online_serving/test_lingbot_video.py +++ b/tests/e2e/online_serving/test_lingbot_video.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """Online serving smoke coverage for the dense LingBot-Video checkpoint.""" @@ -41,7 +41,7 @@ def _get_diffusion_feature_cases(model: str): ] -@pytest.mark.slow +@pytest.mark.full_model @pytest.mark.diffusion @pytest.mark.parametrize("omni_server", _get_diffusion_feature_cases(MODEL), indirect=True) def test_text_to_image_001(omni_server: OmniServer, openai_client: OpenAIClientHandler) -> None: @@ -63,7 +63,7 @@ def test_text_to_image_001(omni_server: OmniServer, openai_client: OpenAIClientH ) -@pytest.mark.slow +@pytest.mark.full_model @pytest.mark.diffusion @pytest.mark.parametrize("omni_server", _get_diffusion_feature_cases(MODEL), indirect=True) def test_video_generation_modes_001(omni_server: OmniServer, openai_client: OpenAIClientHandler) -> None: diff --git a/tests/e2e/online_serving/test_lingbot_video_moe.py b/tests/e2e/online_serving/test_lingbot_video_moe.py index 7e4d16568..a75fa78e0 100644 --- a/tests/e2e/online_serving/test_lingbot_video_moe.py +++ b/tests/e2e/online_serving/test_lingbot_video_moe.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """Single-GPU serving smoke for ``robbyant/lingbot-video-moe-30b-a3b``.""" @@ -41,7 +41,7 @@ def _get_server_cases(model: str): ] -@pytest.mark.slow +@pytest.mark.full_model @pytest.mark.diffusion @pytest.mark.parametrize("omni_server", _get_server_cases(MODEL), indirect=True) def test_text_to_image_moe(omni_server: OmniServer, openai_client: OpenAIClientHandler) -> None: @@ -63,7 +63,7 @@ def test_text_to_image_moe(omni_server: OmniServer, openai_client: OpenAIClientH ) -@pytest.mark.slow +@pytest.mark.full_model @pytest.mark.diffusion @pytest.mark.parametrize("omni_server", _get_server_cases(MODEL), indirect=True) def test_video_generation_modes_moe(omni_server: OmniServer, openai_client: OpenAIClientHandler) -> None: diff --git a/tests/e2e/online_serving/test_magi2.py b/tests/e2e/online_serving/test_magi2.py index 22a30b495..d713abab9 100644 --- a/tests/e2e/online_serving/test_magi2.py +++ b/tests/e2e/online_serving/test_magi2.py @@ -8,7 +8,7 @@ It exercises the recommended resident SP4 topology through ``/v1/videos``. From ``tests/``:: - pytest -s -v e2e/online_serving/test_magi2.py -m "advanced_model and diffusion" --run-level=advanced_model + pytest -s -v e2e/online_serving/test_magi2.py -m "slow and diffusion" --run-level=full_model """ import json @@ -27,8 +27,7 @@ PROMPT = "A red fox walks through fresh snow while wind moves the pine branches. FOUR_CARD_MARKS = hardware_marks(res={"cuda": "H100"}, num_cards=4) -@pytest.mark.core_model -@pytest.mark.advanced_model +@pytest.mark.slow @pytest.mark.diffusion @pytest.mark.parametrize( "omni_server", diff --git a/tests/e2e/online_serving/test_minimax_h3_dlo_dp2_t2va.py b/tests/e2e/online_serving/test_minimax_h3_dlo_dp2_t2va.py index 0bf546683..4fa71aead 100644 --- a/tests/e2e/online_serving/test_minimax_h3_dlo_dp2_t2va.py +++ b/tests/e2e/online_serving/test_minimax_h3_dlo_dp2_t2va.py @@ -111,7 +111,6 @@ def _run_t2va_request(client: OpenAIClientHandler, seed: int) -> bytes: @pytest.mark.core_model @pytest.mark.advanced_model @pytest.mark.diffusion -@pytest.mark.slow @pytest.mark.parametrize( "omni_server", [ diff --git a/tools/pre_commit/check_buildkite.py b/tools/pre_commit/check_buildkite.py index 362253494..f470f09f9 100644 --- a/tools/pre_commit/check_buildkite.py +++ b/tools/pre_commit/check_buildkite.py @@ -27,6 +27,7 @@ from upload_pipeline import _render_test_pipeline # noqa: E402 SKIP_FILES = { ".buildkite/common/ci_mirror_hardwares.yml", + ".buildkite/common/ci_source_file_dependencies.yml", ".buildkite/npu/pipeline-npu-a3.yml", }