3535 workflow_dispatch :
3636 inputs :
3737 run_full_tests :
38- description : ' Run full e2e test suite on Kind (default: smoke tests only )'
38+ description : ' Run full e2e test suite on Kind (check to run full; unchecked runs no e2e )'
3939 required : false
4040 default : false
4141 type : boolean
@@ -254,24 +254,104 @@ jobs:
254254
255255 core.setOutput('run_full', 'false');
256256
257- # E2E tests - smoke tests run automatically, full tests on approval
258- # Skip e2e tests if PR only contains docs/metadata changes (unless explicitly triggered via /trigger-e2e-full)
259- e2e-tests :
257+ # E2E smoke tests - run automatically on every PR with code changes
258+ # Skip if PR only contains docs/metadata changes
259+ e2e-tests-smoke :
260+ runs-on : ubuntu-latest
261+ needs : [lint-and-test, check-code-changes, check-full-tests]
262+ if : github.event_name == 'pull_request' && needs.check-code-changes.result == 'success' && needs.check-code-changes.outputs.has_code_changes == 'true'
263+ timeout-minutes : 60
264+ permissions :
265+ contents : read
266+ steps :
267+ - name : Checkout source
268+ uses : actions/checkout@v4
269+
270+ - name : Extract Go version from go.mod
271+ run : sed -En 's/^go (.*)$/GO_VERSION=\1/p' go.mod >> $GITHUB_ENV
272+
273+ - name : Set up Go with cache
274+ uses : actions/setup-go@v6
275+ with :
276+ go-version : " ${{ env.GO_VERSION }}"
277+ cache-dependency-path : ./go.sum
278+
279+ - name : Install dependencies
280+ run : go mod download
281+
282+ - name : Install Kind
283+ run : |
284+ ARCH=$(uname -m)
285+ case "$ARCH" in
286+ x86_64) KIND_ARCH="amd64" ;;
287+ aarch64) KIND_ARCH="arm64" ;;
288+ *) echo "Unsupported architecture: $ARCH"; exit 1 ;;
289+ esac
290+ curl -Lo ./kind "https://kind.sigs.k8s.io/dl/v0.25.0/kind-linux-${KIND_ARCH}"
291+ chmod +x ./kind
292+ sudo mv ./kind /usr/local/bin/kind
293+ kind version
294+
295+ - name : Set up Docker Buildx
296+ uses : docker/setup-buildx-action@v3
297+
298+ - name : Build WVA image locally
299+ id : build-image
300+ env :
301+ CHECKOUT_SHA : ${{ needs.check-code-changes.outputs.pr_head_sha || github.sha }}
302+ run : |
303+ # Generate unique image tag for this PR run (local image, no registry needed)
304+ IMAGE_NAME="llm-d-workload-variant-autoscaler"
305+ IMAGE_TAG="pr-${GITHUB_RUN_ID}-${CHECKOUT_SHA:0:7}"
306+ # Use localhost prefix for local-only image (Kind will load it directly)
307+ FULL_IMAGE="localhost/${IMAGE_NAME}:${IMAGE_TAG}"
308+
309+ echo "Building local image: $FULL_IMAGE"
310+ echo "Image will be loaded into Kind cluster (no push needed)"
311+
312+ # Build image locally (no push needed for Kind)
313+ make docker-build IMG="$FULL_IMAGE"
314+
315+ echo "image=$FULL_IMAGE" >> $GITHUB_OUTPUT
316+ echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT
317+ echo "Image built locally: $FULL_IMAGE"
318+
319+ - name : Run e2e tests (smoke)
320+ shell : bash
321+ env :
322+ ENVIRONMENT : kind-emulator
323+ USE_SIMULATOR : " true"
324+ SCALE_TO_ZERO_ENABLED : " false"
325+ CREATE_CLUSTER : " true"
326+ INSTALL_GATEWAY_CTRLPLANE : " true"
327+ E2E_TESTS_ENABLED : " true"
328+ IMG : ${{ steps.build-image.outputs.image }}
329+ SKIP_BUILD : " true"
330+ PROMETHEUS_ADAPTER_WAIT : " false"
331+ DELETE_CLUSTER : " true"
332+ # Lower saturation thresholds for simulator mode — the simulator's
333+ # KV-cache and queue metrics are modest, so default thresholds
334+ # (kvSpareTrigger=0.1, queueSpareTrigger=3) are too high to trigger
335+ # scale-up reliably. These values trigger when kvUsage > 0.30 or
336+ # queueLength > 0.5, which the simulator produces under load.
337+ KV_SPARE_TRIGGER : " 0.5"
338+ QUEUE_SPARE_TRIGGER : " 4.5"
339+ run : |
340+ make test-e2e-smoke-with-setup
341+
342+ # Full Kind E2E - runs only when triggered (/trigger-e2e-full or workflow_dispatch with run_full_tests).
343+ # Add "e2e-tests-full" as a required status check in branch protection so it appears on every PR
344+ # and must run and pass before merge (shows as "Expected" until triggered).
345+ e2e-tests-full :
260346 runs-on : ubuntu-latest
261347 needs : [lint-and-test, check-code-changes, check-full-tests]
262348 if : >-
263- always() && (
264- (github.event_name == 'issue_comment' && needs.check-full-tests.outputs.run_full == 'true' && needs.check-code-changes.result == 'success') ||
265- (github.event_name == 'workflow_dispatch' && (
266- needs.check-full-tests.outputs.run_full == 'true' ||
267- (needs.check-code-changes.result == 'success' && needs.check-code-changes.outputs.has_code_changes == 'true')
268- )) ||
269- (github.event_name == 'pull_request' && needs.check-code-changes.result == 'success' && needs.check-code-changes.outputs.has_code_changes == 'true')
270- )
349+ always() && needs.check-full-tests.outputs.run_full == 'true' && needs.check-code-changes.result == 'success'
350+ && (github.event_name == 'issue_comment' || github.event_name == 'workflow_dispatch')
271351 timeout-minutes : 60
272352 permissions :
273353 contents : read
274- statuses : write # For reporting status on fork PR commits
354+ statuses : write
275355 steps :
276356 - name : Set pending status on PR head
277357 if : github.event_name == 'issue_comment' && needs.check-code-changes.outputs.pr_head_sha != ''
@@ -284,7 +364,7 @@ jobs:
284364 sha: '${{ needs.check-code-changes.outputs.pr_head_sha }}',
285365 state: 'pending',
286366 target_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
287- description: 'E2E tests running...',
367+ description: 'Full E2E tests running...',
288368 context: '${{ github.workflow }} / e2e (comment trigger)'
289369 });
290370
@@ -301,7 +381,6 @@ jobs:
301381 - name : Checkout source
302382 uses : actions/checkout@v4
303383 with :
304- # For issue_comment on a fork PR: checkout from head repo so the commit exists
305384 repository : ${{ needs.check-code-changes.outputs.pr_head_repo || github.repository }}
306385 ref : ${{ needs.check-code-changes.outputs.pr_head_sha || github.sha }}
307386 token : ${{ secrets.GITHUB_TOKEN }}
@@ -339,65 +418,37 @@ jobs:
339418 env :
340419 CHECKOUT_SHA : ${{ needs.check-code-changes.outputs.pr_head_sha || github.sha }}
341420 run : |
342- # Generate unique image tag for this PR run (local image, no registry needed)
343421 IMAGE_NAME="llm-d-workload-variant-autoscaler"
344422 IMAGE_TAG="pr-${GITHUB_RUN_ID}-${CHECKOUT_SHA:0:7}"
345- # Use localhost prefix for local-only image (Kind will load it directly)
346423 FULL_IMAGE="localhost/${IMAGE_NAME}:${IMAGE_TAG}"
347-
348424 echo "Building local image: $FULL_IMAGE"
349- echo "Image will be loaded into Kind cluster (no push needed)"
350-
351- # Build image locally (no push needed for Kind)
352425 make docker-build IMG="$FULL_IMAGE"
353-
354426 echo "image=$FULL_IMAGE" >> $GITHUB_OUTPUT
355427 echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT
356- echo "Image built locally: $FULL_IMAGE"
357-
358- - name : Determine test type
359- id : test-type
360- run : |
361- if [ "${{ needs.check-full-tests.outputs.run_full }}" == "true" ]; then
362- echo "test_target=test-e2e-full-with-setup" >> $GITHUB_OUTPUT
363- echo "test_name=full" >> $GITHUB_OUTPUT
364- echo "scale_to_zero=true" >> $GITHUB_OUTPUT
365- echo "delete_cluster=false" >> $GITHUB_OUTPUT
366- else
367- echo "test_target=test-e2e-smoke-with-setup" >> $GITHUB_OUTPUT
368- echo "test_name=smoke" >> $GITHUB_OUTPUT
369- echo "scale_to_zero=false" >> $GITHUB_OUTPUT
370- echo "delete_cluster=true" >> $GITHUB_OUTPUT
371- fi
372428
373- - name : Run e2e tests (${{ steps.test-type.outputs.test_name }} )
429+ - name : Run e2e tests (full )
374430 shell : bash
375431 env :
376432 ENVIRONMENT : kind-emulator
377433 USE_SIMULATOR : " true"
378- SCALE_TO_ZERO_ENABLED : ${{ steps.test-type.outputs.scale_to_zero }}
434+ SCALE_TO_ZERO_ENABLED : " true "
379435 CREATE_CLUSTER : " true"
380436 INSTALL_GATEWAY_CTRLPLANE : " true"
381437 E2E_TESTS_ENABLED : " true"
382438 IMG : ${{ steps.build-image.outputs.image }}
383439 SKIP_BUILD : " true"
384440 PROMETHEUS_ADAPTER_WAIT : " false"
385- DELETE_CLUSTER : ${{ steps.test-type.outputs.delete_cluster }}
386- # Lower saturation thresholds for simulator mode — the simulator's
387- # KV-cache and queue metrics are modest, so default thresholds
388- # (kvSpareTrigger=0.1, queueSpareTrigger=3) are too high to trigger
389- # scale-up reliably. These values trigger when kvUsage > 0.30 or
390- # queueLength > 0.5, which the simulator produces under load.
441+ DELETE_CLUSTER : " false"
391442 KV_SPARE_TRIGGER : " 0.5"
392443 QUEUE_SPARE_TRIGGER : " 4.5"
393444 run : |
394- make ${{ steps. test-type.outputs.test_target }}
445+ make test-e2e-full-with-setup
395446
396447 # Report status back to PR for issue_comment triggered runs
397448 # This ensures fork PRs show the correct status after /trigger-e2e-full runs complete
398449 report-status :
399450 runs-on : ubuntu-latest
400- needs : [check-code-changes, check-full-tests, e2e-tests]
451+ needs : [check-code-changes, check-full-tests, e2e-tests-full ]
401452 if : always() && github.event_name == 'issue_comment' && needs.check-full-tests.outputs.run_full == 'true'
402453 permissions :
403454 statuses : write
@@ -407,7 +458,7 @@ jobs:
407458 with :
408459 script : |
409460 const prHeadSha = '${{ needs.check-code-changes.outputs.pr_head_sha }}';
410- const e2eResult = '${{ needs.e2e-tests.result }}';
461+ const e2eResult = '${{ needs.e2e-tests-full .result }}';
411462
412463 if (!prHeadSha) {
413464 console.log('No PR head SHA available, skipping status report');
0 commit comments