Skip to content
Draft
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
284 changes: 120 additions & 164 deletions .github/workflows/e2e-matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,67 +26,73 @@ on:
schedule:
- cron: "30 2 * * *"
workflow_dispatch:
inputs:
profiles:
description: "Storage profiles (comma-separated): sds, cephrbd"
required: false
default: "sds,cephrbd"
timeout:
description: "Ginkgo timeout (e.g. 2h, 4h)"
required: false
default: "4h"

permissions:
contents: read

concurrency:
group: e2e-matrix-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true

env:
E2E_K8S_URL: https://api.e2e.virtlab.flant.com

jobs:
setup:
name: Setup Profiles
# ============================================
# 1. SETUP - Environment preparation
# ============================================
setup-nested-envs:
name: Setup Nested Envs
runs-on: ubuntu-latest
concurrency:
group: setup-nested-envs-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true
outputs:
profiles: ${{ steps.profiles.outputs.profiles }}
run_id: ${{ steps.prep.outputs.run_id }}
profile: ${{ steps.load.outputs.profile }}
steps:
- uses: actions/checkout@v4

- name: Load storage profiles
id: profiles
- name: Load storage profile
id: load
run: |
# Single profile: sds with storage class sds-replicated-volume
echo 'profiles=["sds"]' >> "$GITHUB_OUTPUT"
cd ci/dvp-e2e
# Map sds-replicated-volume to sds profile from profiles.json
PROFILE=$(jq -r '.[0].name' profiles.json)
echo "profile=$PROFILE" >> "$GITHUB_OUTPUT"
echo "Will test profile: $PROFILE (mapped from sds-replicated-volume)"

- name: Print matrix
- name: Prepare run context
id: prep
run: |
echo "Will test profiles: ${{ steps.profiles.outputs.profiles }}"

RUN_ID="nightly-nested-e2e-sds-$(date +%H%M%S)"
PROFILE="${{ steps.load.outputs.profile }}"
echo "run_id=$RUN_ID" >> "$GITHUB_OUTPUT"
mkdir -p ./tmp/run-context
{
echo "profile: ${PROFILE}"
echo "run_id: ${RUN_ID}"
echo "timestamp: $(date -Iseconds)"
} > ./tmp/run-context/config.yaml

# ============================================
# 2. PREPARE - Cluster preparation
# ============================================
prepare:
name: Matrix Setup (${{ matrix.profile }})
needs: [setup]
name: Prepare Cluster
needs: [setup-nested-envs]
runs-on: ubuntu-latest
timeout-minutes: 300
concurrency:
group: prepare-${{ github.ref }}-${{ matrix.profile }}
group: prepare-${{ github.head_ref || github.ref_name }}-${{ needs.setup-nested-envs.outputs.profile }}
cancel-in-progress: true
strategy:
fail-fast: false
matrix:
profile: ${{ fromJson(needs.setup.outputs.profiles) }}

env:
GO_VERSION: "1.24.6"
PROFILE: ${{ needs.setup-nested-envs.outputs.profile }}
TMP_ROOT: ${{ github.workspace }}/ci/dvp-e2e/tmp
STORAGE_CLASS: sds-replicated-volume

outputs:
run_id: ${{ steps.prep.outputs.run_id }}
storage_class: ${{ env.STORAGE_CLASS }}
REGISTRY_DOCKER_CFG: ${{ secrets.DEV_REGISTRY_DOCKER_CFG }}

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Install Task
uses: arduino/setup-task@v2
Expand All @@ -102,20 +108,17 @@ jobs:
- name: Install kubectl
uses: azure/setup-kubectl@v4
with:
version: 'latest'
version: "latest"

- name: Install Deckhouse CLI
env:
D8_VERSION: v0.13.2
run: |
set -euo pipefail
echo "Installing d8 ${D8_VERSION}..."
curl -fsSL -o d8.tgz "https://deckhouse.io/downloads/deckhouse-cli/${D8_VERSION}/d8-${D8_VERSION}-linux-amd64.tar.gz"
tar -xzf d8.tgz linux-amd64/bin/d8
mv linux-amd64/bin/d8 /usr/local/bin/d8
chmod +x /usr/local/bin/d8
rm -rf d8.tgz linux-amd64
d8 --version
- name: Setup d8
uses: werf/trdl/actions/[email protected]
with:
repo: d8
url: https://deckhouse.ru/downloads/deckhouse-cli-trdl/
root-version: 1
root-sha512: 343bd5f0d8811254e5f0b6fe292372a7b7eda08d276ff255229200f84e58a8151ab2729df3515cb11372dc3899c70df172a4e54c8a596a73d67ae790466a0491
group: 0
channel: stable

- name: Install yq
run: |
Expand All @@ -126,39 +129,17 @@ jobs:
- name: Prepare environment
id: prep
run: |
RUN_ID="nightly-nested-e2e-${{ matrix.profile }}-$(date +%H%M)"
echo "run_id=$RUN_ID" >> "$GITHUB_OUTPUT"
RUN_ID="${{ needs.setup-nested-envs.outputs.run_id }}"
echo "RUN_ID=$RUN_ID" >> "$GITHUB_ENV"
echo "PROFILE=${{ matrix.profile }}" >> "$GITHUB_ENV"
echo "TMP_ROOT=${{ env.TMP_ROOT }}" >> "$GITHUB_ENV"
mkdir -p "${{ env.TMP_ROOT }}/shared" "${{ env.TMP_ROOT }}/matrix-logs"

- name: Build parent kubeconfig from secret
shell: bash
working-directory: ci/dvp-e2e
run: |
set -euo pipefail
mkdir -p "$HOME/.kube"
cat > "$HOME/.kube/config" <<EOF
apiVersion: v1
kind: Config
clusters:
- cluster:
server: ${E2E_K8S_URL}
insecure-skip-tls-verify: true
name: parent
contexts:
- context:
cluster: parent
user: sa
name: parent
current-context: parent
users:
- name: sa
user:
token: "${{ secrets.E2E_NESTED_SA_SECRET }}"
EOF
chmod 600 "$HOME/.kube/config"
echo "KUBECONFIG=$HOME/.kube/config" >> "$GITHUB_ENV"
KCFG="$HOME/.kube/config"
task parent:kubeconfig OUTPUT="$KCFG" API_URL="${E2E_K8S_URL}" SA_TOKEN="${{ secrets.E2E_NESTED_SA_SECRET }}"
echo "KUBECONFIG=$KCFG" >> "$GITHUB_ENV"

- name: Prepare run values.yaml
working-directory: ci/dvp-e2e
Expand All @@ -167,119 +148,94 @@ jobs:
RUN_ID="${{ env.RUN_ID }}" \
RUN_NAMESPACE="${{ env.RUN_ID }}" \
RUN_DIR="${{ env.TMP_ROOT }}/runs/${{ env.RUN_ID }}"
echo "VALUES_TEMPLATE_FILE=${{ env.TMP_ROOT }}/runs/${{ env.RUN_ID }}/values.yaml" >> $GITHUB_ENV

- name: Configure registry auth for installer pull
run: |
mkdir -p ~/.docker
printf '%s' "$REGISTRY_DOCKER_CFG" | base64 -d > ~/.docker/config.json

- name: Configure storage profile
working-directory: ci/dvp-e2e
id: profile-config
run: |
# Set storage profile to sds with storage class sds-replicated-volume
PROFILE='sds' yq eval --inplace '.storageProfile = strenv(PROFILE)' "${{ env.TMP_ROOT }}/runs/${{ env.RUN_ID }}/values.yaml"
echo "Configured storage profile: sds with storage class: ${STORAGE_CLASS}"

- name: Upload run context
if: always()
uses: actions/upload-artifact@v4
with:
name: run-context-${{ env.RUN_ID }}
path: |
ci/dvp-e2e/tmp/runs/${{ env.RUN_ID }}
ci/dvp-e2e/tmp/shared
if-no-files-found: warn
PROFILE_JSON=$(jq -c --arg profile "$PROFILE" '.[] | select(.name == $profile)' profiles.json)
if [ -z "$PROFILE_JSON" ]; then
echo "Profile '$PROFILE' not found in profiles.json" >&2
echo "Available profiles:" >&2
jq -r '.[] | " - \(.name)"' profiles.json >&2
exit 1
fi

run-e2e:
name: E2E (${{ matrix.profile }}) [skeleton]
needs: [setup, prepare]
runs-on: ubuntu-latest
concurrency:
group: e2e-${{ github.ref }}-${{ matrix.profile }}
cancel-in-progress: true
strategy:
fail-fast: false
matrix:
profile: ${{ fromJson(needs.setup.outputs.profiles) }}
steps:
- name: Echo run
run: |
echo "E2E stage for profile=${{ matrix.profile }} (skeleton - placeholder)"
report:
name: Report [skeleton]
needs: [setup, run-e2e]
if: always()
runs-on: ubuntu-latest
steps:
- name: Echo report
STORAGE_CLASS=$(jq -r '.storage_class // ""' <<<"$PROFILE_JSON")
IMAGE_STORAGE_CLASS=$(jq -r '.image_storage_class // ""' <<<"$PROFILE_JSON")
SNAPSHOT_STORAGE_CLASS=$(jq -r '.snapshot_storage_class // ""' <<<"$PROFILE_JSON")
PARENT_STORAGE_CLASS=$(jq -r '.parent_storage_class // ""' <<<"$PROFILE_JSON")
ATTACH_DISK_SIZE=$(jq -r '.worker_data_disk_size // "10Gi"' <<<"$PROFILE_JSON")

echo "Profile: ${PROFILE}"
echo "Storage Class: ${STORAGE_CLASS}"
echo "Image Storage Class: ${IMAGE_STORAGE_CLASS}"
echo "Snapshot Storage Class: ${SNAPSHOT_STORAGE_CLASS}"
echo "Parent Storage Class: ${PARENT_STORAGE_CLASS}"
echo "Attach Disk Size: ${ATTACH_DISK_SIZE}"

# Export variables to GitHub Actions environment
echo "STORAGE_CLASS=${STORAGE_CLASS}" >> $GITHUB_ENV
echo "PARENT_STORAGE_CLASS=${PARENT_STORAGE_CLASS}" >> $GITHUB_ENV
echo "ATTACH_DISK_SIZE=${ATTACH_DISK_SIZE}" >> $GITHUB_ENV
# Pass storage profile into run values for Helm templates
yq eval --inplace ".storageProfile = \"${PROFILE}\"" "${{ env.TMP_ROOT }}/runs/${{ env.RUN_ID }}/values.yaml"
# Effective disk SC used for worker data disks (prefer image SC when set)
EFF_DISK_SC=${IMAGE_STORAGE_CLASS:-$STORAGE_CLASS}
echo "EFFECTIVE_DISK_SC=${EFF_DISK_SC}" >> $GITHUB_ENV

- name: Install nested environment
working-directory: ci/dvp-e2e
run: |
echo "Report stage (skeleton). Collecting results from matrix..."
task install:nested:env \
TMP_DIR="${{ env.TMP_ROOT }}/runs/${{ env.RUN_ID }}" \
VALUES_FILE="${{ env.TMP_ROOT }}/runs/${{ env.RUN_ID }}/values.yaml" \
PARENT_KUBECONFIG="${KUBECONFIG}" \
TARGET_STORAGE_CLASS="${{ env.PARENT_STORAGE_CLASS }}" \
ATTACH_DISK_SIZE="${{ env.ATTACH_DISK_SIZE }}" \
EFFECTIVE_DISK_SC="${{ env.EFFECTIVE_DISK_SC }}" \
NAMESPACE="${{ env.RUN_ID }}" \
NESTED_KUBECONFIG="${{ env.TMP_ROOT }}/runs/${{ env.RUN_ID }}/nested/kubeconfig" \
SDS_SC_NAME="${{ env.STORAGE_CLASS }}"

cleanup:
name: Cleanup Resources
needs: report
name: Cleanup [skeleton]
needs: [setup-nested-envs, prepare]
if: always()
runs-on: ubuntu-latest
env:
CLEANUP_PREFIX: ${{ vars.CLEANUP_PREFIX || 'nightly-nested-e2e-' }}
steps:
- uses: actions/checkout@v4

- name: Install Task
uses: arduino/setup-task@v2

- name: Install kubectl
uses: azure/setup-kubectl@v4
with:
version: 'latest'
version: "latest"

- name: Install Task
uses: arduino/setup-task@v2

- name: Build parent kubeconfig from secret (cleanup)
shell: bash
- name: Build parent kubeconfig from secret
working-directory: ci/dvp-e2e
run: |
set -euo pipefail
mkdir -p "$HOME/.kube"
cat > "$HOME/.kube/config" <<EOF
apiVersion: v1
kind: Config
clusters:
- cluster:
server: ${E2E_K8S_URL}
insecure-skip-tls-verify: true
name: parent
contexts:
- context:
cluster: parent
user: sa
name: parent
current-context: parent
users:
- name: sa
user:
token: "${{ secrets.E2E_NESTED_SA_SECRET }}"
EOF
chmod 600 "$HOME/.kube/config"
echo "KUBECONFIG=$HOME/.kube/config" >> "$GITHUB_ENV"
KCFG="$HOME/.kube/config"
task parent:kubeconfig OUTPUT="$KCFG" API_URL="${E2E_K8S_URL}" SA_TOKEN="${{ secrets.E2E_NESTED_SA_SECRET }}"
echo "KUBECONFIG=$KCFG" >> "$GITHUB_ENV"

- name: Cleanup test namespaces
working-directory: ci/dvp-e2e
run: |
set -euo pipefail
PREFIX="nightly-nested-e2e-"
echo "🧹 Cleaning up namespaces matching prefix '${PREFIX}'"
mapfile -t CANDIDATES < <(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' | grep "^${PREFIX}" || true)
OURS=()
for ns in "${CANDIDATES[@]:-}"; do
[ -z "$ns" ] && continue
if kubectl -n "$ns" get deploy jump-host >/dev/null 2>&1; then
OURS+=("$ns")
fi
done
if [ "${#OURS[@]}" -eq 0 ]; then
echo "[INFO] No namespaces to delete."
else
echo "[INFO] Deleting namespaces:"
printf ' - %s\n' "${OURS[@]}"
for ns in "${OURS[@]}"; do
kubectl delete ns "$ns" --wait=false || true
done
fi
task cleanup:namespaces PREFIX="${CLEANUP_PREFIX}" PARENT_KUBECONFIG="${KUBECONFIG}"

- name: Report cleanup results
if: always()
run: |
echo "### Cleanup Results" >> $GITHUB_STEP_SUMMARY
echo "✅ Cleanup job completed" >> $GITHUB_STEP_SUMMARY
echo "🧹 Attempted to clean up namespaces matching 'nightly-nested-e2e-*'" >> $GITHUB_STEP_SUMMARY
echo "🧹 Attempted to clean up namespaces with prefix '${CLEANUP_PREFIX}'" >> $GITHUB_STEP_SUMMARY
Loading
Loading