Skip to content

add dockerignore

add dockerignore #1925

Workflow file for this run

name: CI - PR Checks
# Cancel previous runs on the same PR when new commits are pushed
# Only group by PR number for legitimate triggers (pull_request, workflow_dispatch, e2e trigger comments)
# Regular comments get a unique group (run_id) so they don't cancel in-progress test runs
#
# Logic:
# - Regular comments (not e2e trigger): unique group prevents cancellation of real tests
# - Valid triggers: group 'ci-pr-checks-{pr_number}' (can cancel previous runs for same PR)
# - Fallback chain for ID: pull_request.number -> issue.number -> run_id
#
# NOTE: Accepted commands (/trigger-e2e-full, /test-e2e-full, /test-full) must stay in sync
# with check-full-tests job validation
concurrency:
group: >-
${{
github.event_name == 'issue_comment' &&
!contains(github.event.comment.body, '/trigger-e2e-full') &&
!contains(github.event.comment.body, '/test-e2e-full') &&
!contains(github.event.comment.body, '/test-full')
&& format('comment-isolated-{0}', github.run_id)
|| format('ci-pr-checks-{0}',
github.event.pull_request.number
|| github.event.issue.number
|| github.run_id)
}}
cancel-in-progress: true
on:
pull_request:
branches:
- main
- dev
# Allow manual triggering of full e2e tests
workflow_dispatch:
inputs:
run_full_tests:
description: 'Run full e2e test suite on Kind (default: smoke tests only)'
required: false
default: false
type: boolean
# Allow triggering via PR comments
issue_comment:
types: [created]
jobs:
# Check if PR contains code changes (not just docs/metadata)
check-code-changes:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read # For reading PR details when triggered via issue_comment
outputs:
has_code_changes: ${{ steps.set-output.outputs.has_code_changes }}
steps:
- name: Get PR number for issue_comment events
id: pr-info
if: github.event_name == 'issue_comment'
uses: actions/github-script@v7
with:
script: |
const issue = context.payload.issue;
if (!issue.pull_request) {
core.setOutput('pr_number', '');
return;
}
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: issue.number
});
core.setOutput('pr_number', issue.number.toString());
core.setOutput('pr_head_sha', pr.head.sha);
- name: Checkout source
uses: actions/checkout@v4
with:
# For issue_comment events, checkout the PR head SHA
ref: ${{ github.event_name == 'issue_comment' && steps.pr-info.outputs.pr_head_sha || github.event.pull_request.head.sha || github.sha }}
# For pull_request events, fetch the PR head
fetch-depth: 0
- name: Check for code changes
uses: dorny/paths-filter@v3
id: filter
continue-on-error: true # Don't fail if paths-filter can't determine changes (e.g., issue_comment without PR context)
with:
filters: |
code:
- '!docs/**'
- '!README.md'
- '!CONTRIBUTING.md'
- '!LICENSE'
- '!OWNERS'
- '!PROJECT'
- name: Set output with default
id: set-output
run: |
# Use filter output if available, otherwise default to 'true' for issue_comment events
# This ensures /trigger-e2e-full works even if PR context is unclear
FILTER_OUTPUT="${{ steps.filter.outputs.code }}"
if [ "${{ github.event_name }}" == "issue_comment" ] && [ -z "$FILTER_OUTPUT" ]; then
echo "has_code_changes=true" >> $GITHUB_OUTPUT
elif [ -n "$FILTER_OUTPUT" ]; then
echo "has_code_changes=$FILTER_OUTPUT" >> $GITHUB_OUTPUT
else
echo "has_code_changes=true" >> $GITHUB_OUTPUT
fi
lint-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Sanity check repo contents
run: ls -la
- name: Extract Go version from go.mod
run: sed -En 's/^go (.*)$/GO_VERSION=\1/p' go.mod >> $GITHUB_ENV
- name: Set up Go with cache
uses: actions/setup-go@v6
with:
go-version: "${{ env.GO_VERSION }}"
cache-dependency-path: ./go.sum
- name: Install dependencies
run: go mod download
- name: Install golangci-lint
uses: golangci/golangci-lint-action@v8
with:
version: v2.8.0
args: ""
- name: Run make build
shell: bash
run: |
make build
- name: Run make test
shell: bash
run: |
make test
# Check if full e2e tests should run (via workflow_dispatch or comment trigger)
check-full-tests:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write # For posting comments and reactions on PRs
outputs:
run_full: ${{ steps.check.outputs.run_full }}
steps:
- name: Check if full tests requested
id: check
uses: actions/github-script@v7
with:
script: |
// Helper to check if user has write access
async function hasWriteAccess(username) {
try {
const { data: permission } = await github.rest.repos.getCollaboratorPermissionLevel({
owner: context.repo.owner,
repo: context.repo.repo,
username: username
});
const privilegedRoles = ['admin', 'maintain', 'write'];
return privilegedRoles.includes(permission.permission);
} catch (e) {
console.log(`Could not get permissions for ${username}: ${e.message}`);
return false;
}
}
// Check workflow_dispatch input
const workflowInput = '${{ github.event.inputs.run_full_tests }}';
// Handle both boolean and string inputs
if (workflowInput === 'true' || workflowInput === true || workflowInput === 'True') {
core.setOutput('run_full', 'true');
return;
}
// Check for /trigger-e2e-full comment trigger
if (context.eventName === 'issue_comment') {
const comment = context.payload.comment.body.trim();
const issue = context.payload.issue;
// Only process /trigger-e2e-full comments on PRs
if (!issue.pull_request) {
console.log('Comment is not on a PR, skipping');
core.setOutput('run_full', 'false');
return;
}
// Accept multiple command variants (case-sensitive, exact match)
const validCommands = ['/trigger-e2e-full', '/test-e2e-full', '/test-full'];
if (!validCommands.includes(comment)) {
console.log(`Comment "${comment}" is not a valid trigger command, skipping`);
core.setOutput('run_full', 'false');
return;
}
// Check if commenter has write access
const commenter = context.payload.comment.user.login;
const hasAccess = await hasWriteAccess(commenter);
if (!hasAccess) {
console.log(`User ${commenter} does not have write access, ignoring ${comment}`);
core.setOutput('run_full', 'false');
return;
}
// Get PR details
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: issue.number
});
console.log(`${comment} approved by ${commenter} for PR #${issue.number}`);
console.log(`PR head SHA: ${pr.head.sha}`);
// Add reaction to acknowledge
await github.rest.reactions.createForIssueComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: context.payload.comment.id,
content: 'rocket'
});
// Post comment with link to the workflow run
const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body: `🚀 **Full E2E tests triggered by ${comment}**\n\n[View the Kind E2E workflow run](${runUrl})`
});
core.setOutput('run_full', 'true');
return;
}
core.setOutput('run_full', 'false');
# E2E tests - smoke tests run automatically, full tests on approval
# Skip e2e tests if PR only contains docs/metadata changes (unless explicitly triggered via /trigger-e2e-full)
e2e-tests:
runs-on: ubuntu-latest
needs: [lint-and-test, check-code-changes, check-full-tests]
if: always() && (needs.check-full-tests.outputs.run_full == 'true' || (needs.check-code-changes.result == 'success' && needs.check-code-changes.outputs.has_code_changes == 'true'))
timeout-minutes: 60
permissions:
contents: read
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Extract Go version from go.mod
run: sed -En 's/^go (.*)$/GO_VERSION=\1/p' go.mod >> $GITHUB_ENV
- name: Set up Go with cache
uses: actions/setup-go@v6
with:
go-version: "${{ env.GO_VERSION }}"
cache-dependency-path: ./go.sum
- name: Install dependencies
run: go mod download
- name: Install Kind
run: |
ARCH=$(uname -m)
case "$ARCH" in
x86_64) KIND_ARCH="amd64" ;;
aarch64) KIND_ARCH="arm64" ;;
*) echo "Unsupported architecture: $ARCH"; exit 1 ;;
esac
curl -Lo ./kind "https://kind.sigs.k8s.io/dl/v0.25.0/kind-linux-${KIND_ARCH}"
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
kind version
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build WVA image locally
id: build-image
run: |
# Generate unique image tag for this PR run (local image, no registry needed)
IMAGE_NAME="llm-d-workload-variant-autoscaler"
IMAGE_TAG="pr-${GITHUB_RUN_ID}-${GITHUB_SHA:0:7}"
# Use localhost prefix for local-only image (Kind will load it directly)
FULL_IMAGE="localhost/${IMAGE_NAME}:${IMAGE_TAG}"
echo "Building local image: $FULL_IMAGE"
echo "Image will be loaded into Kind cluster (no push needed)"
# Build image locally (no push needed for Kind)
make docker-build IMG="$FULL_IMAGE"
echo "image=$FULL_IMAGE" >> $GITHUB_OUTPUT
echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT
echo "Image built locally: $FULL_IMAGE"
- name: Determine test type
id: test-type
run: |
if [ "${{ needs.check-full-tests.outputs.run_full }}" == "true" ]; then
echo "test_target=test-e2e-full-with-setup" >> $GITHUB_OUTPUT
echo "test_name=full" >> $GITHUB_OUTPUT
echo "scale_to_zero=true" >> $GITHUB_OUTPUT
echo "delete_cluster=false" >> $GITHUB_OUTPUT
else
echo "test_target=test-e2e-smoke-with-setup" >> $GITHUB_OUTPUT
echo "test_name=smoke" >> $GITHUB_OUTPUT
echo "scale_to_zero=false" >> $GITHUB_OUTPUT
echo "delete_cluster=true" >> $GITHUB_OUTPUT
fi
- name: Run e2e tests (${{ steps.test-type.outputs.test_name }})
shell: bash
env:
ENVIRONMENT: kind-emulator
USE_SIMULATOR: "true"
SCALE_TO_ZERO_ENABLED: ${{ steps.test-type.outputs.scale_to_zero }}
CREATE_CLUSTER: "true"
INSTALL_GATEWAY_CTRLPLANE: "true"
E2E_TESTS_ENABLED: "true"
IMG: ${{ steps.build-image.outputs.image }}
SKIP_BUILD: "true"
PROMETHEUS_ADAPTER_WAIT: "false"
DELETE_CLUSTER: ${{ steps.test-type.outputs.delete_cluster }}
# Lower saturation thresholds for simulator mode — the simulator's
# KV-cache and queue metrics are modest, so default thresholds
# (kvSpareTrigger=0.1, queueSpareTrigger=3) are too high to trigger
# scale-up reliably. These values trigger when kvUsage > 0.30 or
# queueLength > 0.5, which the simulator produces under load.
KV_SPARE_TRIGGER: "0.5"
QUEUE_SPARE_TRIGGER: "4.5"
run: |
make ${{ steps.test-type.outputs.test_target }}