From 625367ddc107f95ca0fe87d8e35dac9e684b80a8 Mon Sep 17 00:00:00 2001 From: Shmuel Kallner Date: Tue, 21 Jul 2026 12:52:22 +0300 Subject: [PATCH 1/4] Filtering end to end tests is no longer needed Signed-off-by: Shmuel Kallner --- Makefile | 2 +- test/e2e/disruption_test.go | 2 +- test/e2e/e2e_test.go | 20 ++++++++++---------- test/e2e/generate_endpoint_test.go | 6 +++--- test/scripts/e2e-common.sh | 11 ++--------- 5 files changed, 17 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index 175cd2261f..0419b5936a 100644 --- a/Makefile +++ b/Makefile @@ -126,7 +126,7 @@ E2E_NUM_PROCS ?= 5 # Should we pass ALL env vars here? E2E_ENV_VARS = EPP_IMAGE VLLM_IMAGE SIDECAR_IMAGE VLLM_RENDER_IMAGE \ E2E_KEEP_CLUSTER_ON_FAILURE E2E_PORT E2E_METRICS_PORT K8S_CONTEXT READY_TIMEOUT \ - E2E_NUM_PROCS E2E_LABEL_FILTER LOAD_VLLM_RENDER_IMAGE HF_TOKEN + E2E_NUM_PROCS LOAD_VLLM_RENDER_IMAGE HF_TOKEN BUILDER_E2E_ENV_FLAGS = $(foreach v,$(E2E_ENV_VARS),$(if $($(v)),-e '$(v)=$($(v))')) ifneq ($(filter command line environment,$(origin NAMESPACE)),) BUILDER_E2E_ENV_FLAGS += -e NAMESPACE=$(NAMESPACE) diff --git a/test/e2e/disruption_test.go b/test/e2e/disruption_test.go index 718126e825..2f1f3b1d86 100644 --- a/test/e2e/disruption_test.go +++ b/test/e2e/disruption_test.go @@ -96,7 +96,7 @@ func completionRoutedToNamespace(nsName string) error { return nil } -var _ = ginkgo.Describe("Disruption tests", ginkgo.Label(disruptiveTestLabel), func() { +var _ = ginkgo.Describe("Disruption tests", func() { ginkgo.When("A decode pod is killed mid-request", ginkgo.Ordered, testWrapper(func() { ginkgo.It("should recover and route to surviving pods", func() { nsName := getNamespace() diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index b5871d30ac..2b38039069 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -161,7 +161,7 @@ var _ = ginkgo.Describe("Run end to end tests", func() { }) })) - ginkgo.When("Running a PD configuration with nixlv2 connector(deprecated pd-profile-handler)", ginkgo.Label(metricsTestLabel, deprecatedPDTestLabel), ginkgo.Ordered, testWrapper(func() { + ginkgo.When("Running a PD configuration with nixlv2 connector(deprecated pd-profile-handler)", ginkgo.Ordered, testWrapper(func() { ginkgo.It("should run successfully", func() { infPoolObjects := createInferencePool(1) @@ -240,7 +240,7 @@ var _ = ginkgo.Describe("Run end to end tests", func() { } { config := tc.config // capture for closure label := tc.label - ginkgo.When("Running a PD configuration with shared-storage connector using "+tc.name, ginkgo.Label(sharedStorageTestLabel, label), ginkgo.Ordered, testWrapper(func() { + ginkgo.When("Running a PD configuration with shared-storage connector using "+tc.name, ginkgo.Ordered, testWrapper(func() { ginkgo.It("should run regular (non-streaming) requests successfully", func() { infPoolObjects := createInferencePool(1) @@ -475,7 +475,7 @@ var _ = ginkgo.Describe("Run end to end tests", func() { }) })) - ginkgo.When("Running a PD configuration with disagg-profile-handler and metrics validation", ginkgo.Label(metricsTestLabel, disaggTestLabel), ginkgo.Ordered, testWrapper(func() { + ginkgo.When("Running a PD configuration with disagg-profile-handler and metrics validation", ginkgo.Ordered, testWrapper(func() { ginkgo.It("should run successfully", func() { infPoolObjects := createInferencePool(1) @@ -572,7 +572,7 @@ var _ = ginkgo.Describe("Run end to end tests", func() { }) })) - ginkgo.When("Running an E/PD (Encode/Prefill-Decode) configuration", ginkgo.Label(extendedTestLabel), ginkgo.Ordered, testWrapper(func() { + ginkgo.When("Running an E/PD (Encode/Prefill-Decode) configuration", ginkgo.Ordered, testWrapper(func() { ginkgo.It("should route multimodal requests through encode and decode pods", func() { infPoolObjects := createInferencePool(1) @@ -647,7 +647,7 @@ var _ = ginkgo.Describe("Run end to end tests", func() { }) })) - ginkgo.When("Running an E/P/D (encode/prefill/decode) configuration", ginkgo.Label(extendedTestLabel), ginkgo.Ordered, testWrapper(func() { + ginkgo.When("Running an E/P/D (encode/prefill/decode) configuration", ginkgo.Ordered, testWrapper(func() { ginkgo.It("should route multimodal requests through encode, prefill, and decode pods", func() { infPoolObjects := createInferencePool(1) @@ -732,7 +732,7 @@ var _ = ginkgo.Describe("Run end to end tests", func() { }) })) - ginkgo.When("Running an EPD (no disaggregation) configuration", ginkgo.Label(extendedTestLabel), ginkgo.Ordered, testWrapper(func() { + ginkgo.When("Running an EPD (no disaggregation) configuration", ginkgo.Ordered, testWrapper(func() { ginkgo.It("should route text and multimodal requests to the single deployment", func() { infPoolObjects := createInferencePool(1) @@ -800,7 +800,7 @@ var _ = ginkgo.Describe("Run end to end tests", func() { }) })) - ginkgo.When("Running simple non-PD KV enabled configuration", ginkgo.Label(extendedTestLabel), ginkgo.Ordered, testWrapper(func() { + ginkgo.When("Running simple non-PD KV enabled configuration", ginkgo.Ordered, testWrapper(func() { ginkgo.It("should run successfully", func() { infPoolObjects := createInferencePool(1) @@ -824,7 +824,7 @@ var _ = ginkgo.Describe("Run end to end tests", func() { }) })) - ginkgo.When("Running KV configuration with external tokenizer DataProducer plugin", ginkgo.Label(extendedTestLabel), ginkgo.Ordered, testWrapper(func() { + ginkgo.When("Running KV configuration with external tokenizer DataProducer plugin", ginkgo.Ordered, testWrapper(func() { ginkgo.It("should run successfully", func() { infPoolObjects := createInferencePool(1) @@ -859,7 +859,7 @@ var _ = ginkgo.Describe("Run end to end tests", func() { }) })) - ginkgo.When("Scaling up and down the model servers", ginkgo.Label(extendedTestLabel), ginkgo.Ordered, testWrapper(func() { + ginkgo.When("Scaling up and down the model servers", ginkgo.Ordered, testWrapper(func() { ginkgo.It("should distribute inference requests across all model servers", func() { infPoolObjects := createInferencePool(1) @@ -917,7 +917,7 @@ var _ = ginkgo.Describe("Run end to end tests", func() { }) })) - ginkgo.When("Running a vLLM Data Parallel configuration", ginkgo.Label(extendedTestLabel), ginkgo.Ordered, testWrapper(func() { + ginkgo.When("Running a vLLM Data Parallel configuration", ginkgo.Ordered, testWrapper(func() { ginkgo.It("should schedule inference on all ranks", func() { infPoolObjects := createInferencePool(2) diff --git a/test/e2e/generate_endpoint_test.go b/test/e2e/generate_endpoint_test.go index 5e6d8a4ad6..737307c04c 100644 --- a/test/e2e/generate_endpoint_test.go +++ b/test/e2e/generate_endpoint_test.go @@ -43,7 +43,7 @@ var twoImages = []imageSpec{ {Hash: "e2e-image-hash-1", Offset: 4, Length: 5}, } -var _ = ginkgo.Describe("Direct gateway /inference/v1/generate encode against encode-only", ginkgo.Label(extendedTestLabel), ginkgo.Ordered, testWrapper(func() { +var _ = ginkgo.Describe("Direct gateway /inference/v1/generate encode against encode-only", ginkgo.Ordered, testWrapper(func() { // Uses single-profile-handler (generateEncodeConfig) so the EPP routes // directly to encode pods without requiring a decode stage first. ginkgo.It("returns ec_transfer_params for encode bodies", func() { @@ -77,7 +77,7 @@ var _ = ginkgo.Describe("Direct gateway /inference/v1/generate encode against en }) })) -var _ = ginkgo.Describe("Direct gateway /inference/v1/generate prefill against prefill-only", ginkgo.Label(extendedTestLabel), ginkgo.Ordered, testWrapper(func() { +var _ = ginkgo.Describe("Direct gateway /inference/v1/generate prefill against prefill-only", ginkgo.Ordered, testWrapper(func() { // Uses single-profile-handler (generatePrefillConfig) so the EPP routes // directly to prefill pods without requiring a decode stage first. ginkgo.It("returns kv_transfer_params for prefill bodies", func() { @@ -237,7 +237,7 @@ func expectKVTransferParams(parsed map[string]any, raw []byte) { "kv_transfer_params is empty: %s", string(raw)) } -var _ = ginkgo.Describe("P/D gateway /inference/v1/generate disaggregates via sidecar", ginkgo.Label(sharedStorageTestLabel, disaggTestLabel), ginkgo.Ordered, testWrapper(func() { +var _ = ginkgo.Describe("P/D gateway /inference/v1/generate disaggregates via sidecar", ginkgo.Ordered, testWrapper(func() { // Regression test for https://github.com/llm-d/llm-d-router/issues/1461: // the pd-sidecar previously had no route for /inference/v1/generate, so // token-in P/D requests silently fell through to decode-only. This test diff --git a/test/scripts/e2e-common.sh b/test/scripts/e2e-common.sh index 3fed999fb6..6d0e170b91 100644 --- a/test/scripts/e2e-common.sh +++ b/test/scripts/e2e-common.sh @@ -29,15 +29,8 @@ e2e_handle_interrupt() { exit 130 # SIGINT (Ctrl+C) } -# run_ginkgo_suite runs the Ginkgo e2e suite in the given package directory, -# applying E2E_LABEL_FILTER when set. +# run_ginkgo_suite runs the Ginkgo e2e suite in the given package directory. run_ginkgo_suite() { local pkg="$1" - if [ -n "${E2E_LABEL_FILTER:-}" ]; then - echo "Label filter: ${E2E_LABEL_FILTER}" - # Tests not being run in parallel using Ginkgo - E2E_NUM_PROCS=1 go test -v -timeout 45m "${pkg}" -ginkgo.v -ginkgo.fail-fast "-ginkgo.label-filter=${E2E_LABEL_FILTER}" - else - ginkgo run --procs="${E2E_NUM_PROCS}" --timeout 45m -v --fail-fast "${pkg}" - fi + ginkgo run --procs="${E2E_NUM_PROCS}" --timeout 45m -v --fail-fast "${pkg}" } From 78a3e031d0d6fcfc7ae4a9d146a038a40b7068fe Mon Sep 17 00:00:00 2001 From: Shmuel Kallner Date: Tue, 21 Jul 2026 12:52:57 +0300 Subject: [PATCH 2/4] Run end to end tests in parallel using Ginkgo Signed-off-by: Shmuel Kallner --- .github/workflows/ci-pr-checks.yaml | 43 ++--------------------------- 1 file changed, 2 insertions(+), 41 deletions(-) diff --git a/.github/workflows/ci-pr-checks.yaml b/.github/workflows/ci-pr-checks.yaml index e76a43a5d2..fa8f7b33d2 100644 --- a/.github/workflows/ci-pr-checks.yaml +++ b/.github/workflows/ci-pr-checks.yaml @@ -1,4 +1,4 @@ -# Matrix jobs (e2e-image-common, e2e-image-router, e2e-router) are each +# Matrix jobs (e2e-image-common, e2e-image-router) are each # followed by a *-status job that aggregates their result, since GitHub # required status checks cannot reference individual matrix legs. name: CI - Test @@ -348,29 +348,6 @@ jobs: if: ${{ needs.check-changes.outputs.src == 'true' }} runs-on: ubuntu-latest timeout-minutes: 45 - strategy: - fail-fast: false - matrix: - suite: - - name: pd - label-filter: "!Disruptive && !Extended && !SharedStorage && !Metrics" - needs-renderer: "false" - - name: pd-shared-storage-deprecated - label-filter: "SharedStorage && DeprecatedPD" - needs-renderer: "false" - - name: pd-shared-storage-disagg - label-filter: "SharedStorage && Disagg" - needs-renderer: "false" - - name: pd-metrics - label-filter: "Metrics" - needs-renderer: "false" - - name: extended - label-filter: "Extended" - needs-renderer: "true" - - name: disruption - label-filter: "Disruptive" - needs-renderer: "false" - name: e2e-router (${{ matrix.suite.name }}) steps: - name: Checkout source uses: actions/checkout@v7 @@ -404,7 +381,6 @@ jobs: path: ${{ runner.temp }}/e2e-images - name: Download renderer image - if: ${{ matrix.suite.needs-renderer == 'true' }} uses: actions/download-artifact@v8 with: name: e2e-image-renderer @@ -417,26 +393,11 @@ jobs: docker load --input "$image" done - - name: Run e2e-router (${{ matrix.suite.name }}) + - name: Run e2e-router shell: bash env: GO_MOD_CACHE_VOL: ${{ steps.e2e-setup.outputs.go-mod-cache }} GO_BUILD_CACHE_VOL: ${{ steps.e2e-setup.outputs.go-build-cache }} - E2E_LABEL_FILTER: ${{ matrix.suite.label-filter }} - LOAD_VLLM_RENDER_IMAGE: ${{ matrix.suite.needs-renderer }} PULL_VLLM_RENDER_IMAGE: "false" HF_TOKEN: ${{ secrets.HF_TOKEN }} run: make test-e2e-run - - e2e-router-status: - needs: e2e-router - if: always() - runs-on: ubuntu-latest - steps: - - name: Check e2e-router result - run: | - result="${{ needs.e2e-router.result }}" - if [[ "$result" != "success" && "$result" != "skipped" ]]; then - echo "::error::e2e-router failed for at least one matrix suite" - exit 1 - fi From 7552fc2163a108535edb271a573edb0bbeb3b471 Mon Sep 17 00:00:00 2001 From: Shmuel Kallner Date: Tue, 21 Jul 2026 13:03:11 +0300 Subject: [PATCH 3/4] Removed extraneous label setup Signed-off-by: Shmuel Kallner --- test/e2e/e2e_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index 2b38039069..f52ed1137f 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -233,13 +233,11 @@ var _ = ginkgo.Describe("Run end to end tests", func() { for _, tc := range []struct { name string config string - label string }{ - {"deprecated pd-profile-handler", deprecatedPdConfig, deprecatedPDTestLabel}, - {"disagg-profile-handler", pdConfig, disaggTestLabel}, + {"deprecated pd-profile-handler", deprecatedPdConfig}, + {"disagg-profile-handler", pdConfig}, } { config := tc.config // capture for closure - label := tc.label ginkgo.When("Running a PD configuration with shared-storage connector using "+tc.name, ginkgo.Ordered, testWrapper(func() { ginkgo.It("should run regular (non-streaming) requests successfully", func() { infPoolObjects := createInferencePool(1) From c6584299eb4c647f51bb9d5e2b71eab855111945 Mon Sep 17 00:00:00 2001 From: Shmuel Kallner Date: Tue, 21 Jul 2026 13:56:59 +0300 Subject: [PATCH 4/4] Removed CI shard name constants Signed-off-by: Shmuel Kallner --- test/e2e/e2e_suite_test.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index ea0eceac95..a827991b6f 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -60,14 +60,6 @@ const ( // defaultPort is the envoy gateway's NodePort. defaultPort = 30080 defaultMetricsPort = 32090 - - // CI shards scheduler e2e specs with label filters. - extendedTestLabel = "Extended" - disruptiveTestLabel = "Disruptive" - sharedStorageTestLabel = "SharedStorage" - metricsTestLabel = "Metrics" - deprecatedPDTestLabel = "DeprecatedPD" - disaggTestLabel = "Disagg" ) var (